"""
scanner_feature_study.py

[2026-09-25] Which 9:28 scanner measures actually predicted the stocks that
ran in the first 30 minutes? For every stock-day in the opening-window
universe (20 trading days), recompute the scanner's inputs exactly as the
FIXED scanner would (previous session = the real prior day), score it with
scanner.score_breakout_candidate, and compare against the 9:30-10:00 outcome.

Writes scanner_features_<first>_<last>.csv next to this file.
"""
import csv
import glob
import sys
from datetime import datetime, time, timedelta
from pathlib import Path
from zoneinfo import ZoneInfo

HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE.parents[1]))
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame, TimeFrameUnit
from alpaca_client import get_client
import scanner
import volatility

ET = ZoneInfo("America/New_York")


def main():
    uni_path = sorted(glob.glob(str(HERE / "open_window_universe_*.csv")))[-1]
    rows = list(csv.DictReader(open(uni_path)))
    days = sorted({r["date"] for r in rows})
    client = get_client()
    syms = sorted({r["symbol"] for r in rows})
    first = datetime.fromisoformat(days[0]).replace(tzinfo=ET)
    daily = client.get_daily_bars_bulk(syms, first - timedelta(days=45), datetime.now(ET), limit=80)
    out_path = HERE / f"scanner_features_{days[0].replace('-', '')}_{days[-1].replace('-', '')}.csv"
    with open(out_path, "w", newline="") as f:
        w = csv.writer(f)
        w.writerow(["date", "symbol", "score", "rvol", "pm_volume", "gap_pct", "pm_strength_pct",
                    "dist_to_resistance_pct", "resistance_level", "pm_high", "prev_day_high", "range_20d_high",
                    "daily_atr_pct", "pm_bars", "run_up_pct", "chg_0930_1000_pct", "volume_0930_1000"])
        for d in days:
            day_rows = [r for r in rows if r["date"] == d and r["run_up_pct"] != ""]
            dsyms = [r["symbol"] for r in day_rows]
            dd = datetime.fromisoformat(d).replace(tzinfo=ET)
            pm = {}
            for i in range(0, len(dsyms), 100):
                req = StockBarsRequest(symbol_or_symbols=dsyms[i:i + 100], timeframe=TimeFrame(1, TimeFrameUnit.Minute),
                                       start=dd.replace(hour=3, minute=28), end=dd.replace(hour=9, minute=28),
                                       limit=None, feed=client._feed)
                pm.update(client.hist_data.get_stock_bars(req).data)
            for r in day_rows:
                s = r["symbol"]
                bars = [{"t": b.timestamp, "o": float(b.open), "h": float(b.high), "l": float(b.low),
                         "c": float(b.close), "v": float(b.volume)} for b in pm.get(s, [])]
                hist = [b for b in daily.get(s, []) if b["t"].astimezone(ET).date() < dd.date()]
                if len(bars) < 3 or len(hist) < 2:
                    continue
                prev = hist[-1]
                h20 = max(b["h"] for b in hist[-20:])
                datr = volatility.daily_atr(hist)
                res = scanner.score_breakout_candidate(
                    s, bars, max(b["h"] for b in bars), min(b["l"] for b in bars),
                    prev["v"], prev["c"], prev["h"], h20)
                m = res["metrics"]
                w.writerow([d, s, res["candidate_score"], m["rvol"], m["premarket_volume"], m["gap_pct"],
                            m["price_strength_pct"], m["distance_to_resistance_pct"], m["resistance_level_used"],
                            m["premarket_high"], prev["h"], h20,
                            round(datr / m["price"] * 100, 2) if datr else "", len(bars),
                            r["run_up_pct"], r["chg_0930_1000_pct"], r["volume_0930_1000"]])
            print(d, "done", flush=True)
    print("wrote", out_path)


if __name__ == "__main__":
    main()
