chart/scripts/calibrate_alerts.py

56 lines
2.3 KiB
Python

"""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())