export const meta = {
  name: 'crypto-lead-sweep',
  description: 'Sweep multi-agente dell\'anticipazione crypto->mercati IB (mercati x timing x lead), verifica avversariale multi-anno, sintesi della soluzione migliore',
  phases: [
    { title: 'Sweep', detail: '~52 agenti: grid (lead x mercato x giorno x predict x finestra) via harness onesto' },
    { title: 'Verify', detail: 'top candidati: stress costi + OOS recente + multi-anno' },
    { title: 'Synthesize', detail: 'migliore soluzione robusta + caveat di tradabilita' },
  ],
}

// ---- universo mercati certificati (cache su disco) ----
const MARKETS = ["SPY","QQQ","IWM","DIA","XLK","XLF","XLE","XLV","XLI","XLP","XLY","XLU","XLB","XLRE","XLC",
                 "HYG","TLT","IEF","GLD","SLV","USO","DBC","VNQ","EEM","FXI","EWJ"]
const LEADS = ["BTC","ETH"]
const DAYS = ["all","mon"]
const PREDICTS = ["gap","intraday"]
const HOURS = ["overnight","6"]

// ---- genera la grid completa ----
const grid = []
for (const lead of LEADS) for (const target of MARKETS) for (const day of DAYS)
  for (const predict of PREDICTS) for (const hours of HOURS)
    grid.push({ lead, target, day, predict, hours })
log(`grid totale: ${grid.length} configurazioni (mercati ${MARKETS.length} x lead 2 x giorno 2 x predict 2 x finestra 2)`)

// ---- chunk in batch da 8 -> ~52 agenti ----
const BATCH = 8
const batches = []
for (let i = 0; i < grid.length; i += BATCH) batches.push(grid.slice(i, i + BATCH))
log(`sweep: ${batches.length} agenti, ${BATCH} config ciascuno`)

const RAW_SCHEMA = {
  type: "object",
  properties: { raw: { type: "string", description: "stdout JSON ESATTO dell'harness, senza modifiche" } },
  required: ["raw"],
}

// ---- PHASE 1: SWEEP ----
phase('Sweep')
const sweepResults = await parallel(batches.map((batch, bi) => () =>
  agent(
    `Sei un esecutore deterministico. Esegui ESATTAMENTE questo comando dalla root del repo e restituisci il suo stdout.\n\n` +
    `uv run python scripts/research/crypto_lead_harness.py --configs '${JSON.stringify(batch)}'\n\n` +
    `Il comando stampa un array JSON di risultati. Mettilo VERBATIM nel campo "raw" (nessun commento, nessuna modifica ai numeri). ` +
    `Se il comando fallisce, metti il messaggio d'errore in "raw".`,
    { label: `sweep:${bi}`, phase: 'Sweep', schema: RAW_SCHEMA, effort: 'low' }
  )
))

// ---- parse + flatten ----
const all = []
for (const r of sweepResults) {
  if (!r || !r.raw) continue
  try {
    const arr = JSON.parse(r.raw.trim())
    for (const x of arr) if (x && !x.err) all.push(x)
  } catch (e) { /* skip batch non parsabile */ }
}
log(`risultati validi raccolti: ${all.length}/${grid.length}`)

// ---- ranking robustezza: tutti gli anni positivi + t-stat alto + OOS positivo ----
function score(x) {
  const yr = x.years_tot ? x.years_pos / x.years_tot : 0
  const oosOK = (x.sh_ls_oos > 0 || x.sh_lf_oos > 0) ? 1 : 0
  return yr * Math.abs(x.t_incremental || 0) * (1 + Math.max(x.sh_ls_oos || 0, x.sh_lf_oos || 0)) * oosOK
}
all.sort((a, b) => score(b) - score(a))
const top = all.slice(0, 12)
// separa per tradabilita': intraday = ETF-tradabile; gap = fenomeno (serve future)
const topIntraday = all.filter(x => x.predict === 'intraday').slice(0, 6)
const topGap = all.filter(x => x.predict === 'gap').slice(0, 6)
log(`TOP overall: ${top.map(x => `${x.lead}->${x.target}/${x.day}/${x.predict} t=${x.t_incremental} oos=${Math.max(x.sh_ls_oos,x.sh_lf_oos)} ${x.years_pos}/${x.years_tot}y`).join(' | ')}`)

// ---- PHASE 2: VERIFY (stress costi + OOS recente, multi-anno) ----
phase('Verify')
const VERDICT_SCHEMA = {
  type: "object",
  properties: {
    config: { type: "string" },
    robust: { type: "boolean", description: "regge stress (costi alti + OOS recente) e multi-anno?" },
    tradeable_via: { type: "string", description: "etf-intraday | futures-gap | none" },
    sh_oos_4bps: { type: "number" }, sh_oos_10bps: { type: "number" }, sh_oos_recent: { type: "number" },
    years_pos: { type: "number" }, years_tot: { type: "number" },
    note: { type: "string", description: "1-2 frasi: cosa regge, cosa no, spiegazione alternativa" },
  },
  required: ["config", "robust", "tradeable_via", "note"],
}
const cands = [...new Map([...topIntraday, ...topGap, ...top].map(x => [`${x.lead}|${x.target}|${x.day}|${x.predict}|${x.hours}`, x])).values()].slice(0, 12)
const verified = await parallel(cands.map((c) => () => {
  const cfg = JSON.stringify([{ lead: c.lead, target: c.target, day: c.day, predict: c.predict, hours: c.hours }])
  return agent(
    `Verifica avversariale di UN candidato lead-lag crypto->mercato. Config: ${JSON.stringify(c)}.\n` +
    `Esegui questi 3 comandi dalla root e leggi i campi t_incremental, sh_ls_oos, sh_lf_oos, years_pos, years_tot:\n` +
    `1) base 4bps:   uv run python scripts/research/crypto_lead_harness.py --cost 0.0004 --oos 2022-01-01 --configs '${cfg}'\n` +
    `2) stress 10bps: uv run python scripts/research/crypto_lead_harness.py --cost 0.0010 --oos 2022-01-01 --configs '${cfg}'\n` +
    `3) OOS recente:  uv run python scripts/research/crypto_lead_harness.py --cost 0.0004 --oos 2024-01-01 --configs '${cfg}'\n\n` +
    `Giudica: robust=true SOLO se l'edge resta positivo a 10bps E nell'OOS recente (2024+) E years_pos/years_tot>=0.6. ` +
    `tradeable_via: "etf-intraday" se predict=intraday e regge (eseguibile comprando l'ETF al Monday/giorno open); ` +
    `"futures-gap" se predict=gap e regge (il gap si cattura solo con i futures indice overnight, NON con l'ETF); "none" se non regge. ` +
    `note: spiega anche un'alternativa plausibile (e' solo risk-beta? autocorrelazione? multiple-testing su ${grid.length} test?).`,
    { label: `verify:${c.lead}->${c.target}/${c.predict}`, phase: 'Verify', schema: VERDICT_SCHEMA }
  )
}))
const robust = verified.filter(v => v && v.robust)
log(`candidati robusti: ${robust.length}/${cands.length}`)

// ---- PHASE 3: SYNTHESIZE ----
phase('Synthesize')
const SYNTH_SCHEMA = {
  type: "object",
  properties: {
    best_solution: { type: "string", description: "la migliore soluzione: lead+mercato+timing+predict+come si tradea" },
    why: { type: "string" },
    expected_edge: { type: "string", description: "Sharpe OOS onesto (post-stress), hit, anni positivi" },
    tradeability: { type: "string", description: "ETF intraday vs futures overnight; eseguibile a $0.5-2k?" },
    multi_year: { type: "string", description: "evidenza su piu' anni (per-anno)" },
    caveats: { type: "string" },
    runner_ups: { type: "string" },
  },
  required: ["best_solution", "why", "expected_edge", "tradeability", "multi_year", "caveats"],
}
const synthesis = await agent(
  `Sei l'analista quant capo, disciplina ONESTA (questo progetto uccide i falsi positivi: multiple-testing, hold-out-luck, ` +
  `tradabilita' reale a basso capitale). Obiettivo: dalla ricerca multi-agente sull'anticipazione crypto->mercati IB, ` +
  `determina la SOLUZIONE MIGLIORE (mercato + timing + lead) verificata su PIU' ANNI.\n\n` +
  `TOP candidati (sweep, ${grid.length} config testate): ${JSON.stringify(top)}\n\n` +
  `VERDETTI di verifica avversariale (stress costi 10bps + OOS recente 2024+): ${JSON.stringify(verified)}\n\n` +
  `Candidati robusti: ${JSON.stringify(robust)}\n\n` +
  `Fatti noti: (a) il GAP di apertura (predict=gap) ha t-stat altissimi ma NON e' catturabile con l'ETF (serve un future ` +
  `indice tradato overnight, es. MNQ/MES su IB); (b) l'INTRADAY (predict=intraday) e' debole ma eseguibile comprando l'ETF; ` +
  `(c) abbiamo testato ${grid.length} configurazioni -> correggi mentalmente per multiple-testing (un t-stat ~2 non basta qui).\n\n` +
  `Produci la sintesi: la soluzione migliore REALMENTE utile (distingui fenomeno-forte-non-tradabile da edge-tradabile), ` +
  `il suo edge atteso onesto post-stress, come si tradea a $0.5-2k, l'evidenza multi-anno, i caveat, e i runner-up.`,
  { label: 'synthesize', phase: 'Synthesize', schema: SYNTH_SCHEMA, effort: 'high' }
)

return {
  grid_size: grid.length,
  sweep_agents: batches.length,
  results_collected: all.length,
  top12: top,
  verified,
  robust_count: robust.length,
  synthesis,
}
