"""IB EQUITIES/ETF DATA PROBE — certifica cosa il paper IB dà per la ricerca su azioni/ETF.

Gemello equity di certify_feed.py: PRIMA il dato (cosa c'è, quanto indietro, aggiustato per
dividendi/split?, cosa costa), POI la strategia. Disciplina v2.0.0.

Universo candidato per la prima ricerca equity (cross-sectional momentum / trend, l'edge "noioso e
robusto" più plausibile in un mercato efficiente):
  * 11 SPDR settoriali (XLK..XLC) — universo canonico del momentum cross-section settoriale;
  * ETF broad / macro (SPY QQQ IWM TLT GLD HYG) — per trend e risk-on/off;
  * 2 azioni (AAPL MSFT) per tarare profondità/qualità.

Per ogni simbolo: profondità storica daily con whatToShow=ADJUSTED_LAST (split+dividendi, OBBLIGATORIO
per un backtest equity onesto) e TRADES (raw), + flag se scatta errore di subscription market-data.

  uv run --with ib_async python scripts/research/ib_equities_probe.py
"""
import argparse, sys

SECTORS = ["XLK", "XLF", "XLE", "XLV", "XLI", "XLP", "XLY", "XLU", "XLB", "XLRE", "XLC"]
BROAD = ["SPY", "QQQ", "IWM", "TLT", "GLD", "HYG"]
STOCKS = ["AAPL", "MSFT"]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--host", default="127.0.0.1")
    ap.add_argument("--port", type=int, default=4002)
    ap.add_argument("--client-id", type=int, default=88)
    ap.add_argument("--years", default="20 Y", help="durata storica da richiedere")
    args = ap.parse_args()

    try:
        from ib_async import IB, Stock
    except Exception:
        print("ib_async non importabile. Esegui con:  uv run --with ib_async python ...")
        sys.exit(2)

    ib = IB()
    try:
        ib.connect(args.host, args.port, clientId=args.client_id, timeout=15)
    except Exception as e:
        print(f"[CONNESSIONE FALLITA] {args.host}:{args.port} -> {repr(e)[:140]}")
        sys.exit(1)

    print("=" * 96)
    print(f"  IB EQUITIES/ETF PROBE — {args.host}:{args.port} | acct {ib.managedAccounts()} | depth req {args.years}")
    print("=" * 96)

    universe = [("SECTOR", s) for s in SECTORS] + [("BROAD", s) for s in BROAD] + [("STOCK", s) for s in STOCKS]
    print(f"  {'sym':6} {'tipo':7} {'ADJUSTED_LAST':>26} {'TRADES':>22}  note")
    rows = []
    for cat, sym in universe:
        con = Stock(sym, "SMART", "USD")
        try:
            cds = ib.reqContractDetails(con)
            if not cds:
                print(f"  {sym:6} {cat:7} {'-- no contract --':>26}")
                continue
        except Exception as e:
            print(f"  {sym:6} {cat:7} ERR resolve {repr(e)[:40]}")
            continue

        def hist(what):
            try:
                b = ib.reqHistoricalData(con, endDateTime="", durationStr=args.years,
                                         barSizeSetting="1 day", whatToShow=what,
                                         useRTH=True, formatDate=1, timeout=45)
                if not b:
                    return "0 barre", None
                return f"{len(b)}b {b[0].date}..{b[-1].date}", b
            except Exception as e:
                return f"ERR {repr(e)[:30]}", None

        adj_s, adj_b = hist("ADJUSTED_LAST")
        trd_s, _ = hist("TRADES")
        note = ""
        if "ERR" in adj_s or "0 barre" in adj_s:
            note = "subscription? prova delayed"
        print(f"  {sym:6} {cat:7} {adj_s:>26} {trd_s:>22}  {note}")
        if adj_b:
            rows.append((sym, len(adj_b), str(adj_b[0].date), str(adj_b[-1].date)))

    print("-" * 96)
    if rows:
        depth = min(r[1] for r in rows); start = max(r[2] for r in rows)
        print(f"  CERTIFICABILI (ADJUSTED_LAST): {len(rows)}/{len(universe)} | profondità comune ~{depth}b | start comune {start}")
        print(f"  -> per un backtest cross-sectional servono date allineate: lo start comune e' il limite.")
    else:
        print("  NESSUN simbolo ha reso storia ADJUSTED — probabile mancanza market-data subscription.")
        print("  Ripiego: whatToShow='TRADES' (raw, non adj) o dati 'delayed' / fonte esterna certificabile.")
    ib.disconnect()


if __name__ == "__main__":
    main()
