"""Replay Yahoo's available minute tape and report alerts per CME session.""" import asyncio from collections import Counter from app.analysis.alerts import AlertEngine from app.analysis.confluence import cluster_levels from app.analysis.indicators import atr from app.analysis.moving_averages import build_ma_levels from app.bars.aggregator import Aggregator from app.bars.models import Timeframe from app.bars.session import bucket_start from app.bars.store import InMemoryBarStore from app.config import Settings from app.market.yahoo import YahooSource async def main() -> None: settings = Settings() source = YahooSource(settings.yahoo_poll_seconds) hourly, minutes = await asyncio.gather( source.history(settings.yahoo_symbol, Timeframe.H1, range_=settings.seed_1h_range), source.history(settings.yahoo_symbol, Timeframe.M1, range_=settings.seed_1m_range), ) if not minutes: raise RuntimeError("Yahoo returned no minute tape") aggregator = Aggregator(settings.enabled_timeframes) store = InMemoryBarStore(25_000) levels = [] cutoff = minutes[0].t for source_bar in [bar for bar in hourly if bar.t < cutoff] + minutes: for bar in aggregator.update(source_bar): store.put(bar) if settings.ma_sets.get(bar.tf): levels = build_ma_levels( {tf: store.get(tf) for tf in settings.ma_sets}, settings.ma_sets ) if bar.tf is not Timeframe.M1 or not bar.closed: continue atr_values = atr(store.get(Timeframe.M15), 14) atr15 = next((value for value in reversed(atr_values) if value is not None), 0.0) clusters = cluster_levels(levels, bar.t, bar.c, atr15) alerts = engine.evaluate(clusters, bar.c, atr15, bar.t, settings.yahoo_symbol) counts[bucket_start(bar.t, Timeframe.D1)] += len(alerts) print(f"threshold={settings.confluence_min_score:g} minute_bars={len(minutes)}") print("alerts/session:", ", ".join(str(value) for _, value in sorted(counts.items()))) print(f"total={sum(counts.values())} max_session={max(counts.values(), default=0)}") settings = Settings() engine = AlertEngine(settings.confluence_min_score, settings.alert_cooldown_seconds) counts: Counter[int] = Counter() if __name__ == "__main__": asyncio.run(main())