Files
PythagorasGoal/scripts/analysis/options_fetcher.py
T
Adriano Dal Pastro df8bfbceaa research(mr02eth): ricerca sostituto + integrazione dati opzioni cerbero-bite
Ricerca sostituto/miglioria a MR02/ETH (127 strategie + 18 overlay opzioni,
verifica avversariale, gate PORT06). Esito: miglioria = no-SL (gia' ~catturata
da EXIT-16 live); tail-hedge opzioni NO-GO empirico su prezzi reali.

Infrastruttura opzioni REALE (muro ARGO/GEX caduto):
- options_fetcher.py: importa lo storico per-strike + market_snapshots da
  cerbero-bite -> data/options/ (chain bid/ask/IV/greche/OI + pannello regime
  con net-GEX dealer/gamma-flip/VRP/funding/liquidation).
- options_chain.py: loader + skew_curve/premium_levels (aggregati reali) +
  quote() causale + load_market() (pannello regime).
- option_overlay_lab.py: overlay opzioni BS su DVOL (pricing sintetico).
- mr02eth_port06_gate.py / eth_collar_gate.py: gate swap-sleeve e collar.
- mr02eth_search/options.workflow.js: i 2 workflow.

Numeri reali: skew put 10%OTM ~1.1 (liquido), premio ~1.0%/mese; niente strike
10%OTM a 24h (overlay per-trade infattibile); collar standing paga nei crash ma
net-negativo a PORT06 (alza OOS DD). Diario + CLAUDE.md aggiornati.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 07:05:00 +00:00

84 lines
3.3 KiB
Python

"""Importa lo storico per-strike delle opzioni da cerbero-bite -> data/options/.
cerbero-bite (container Docker accanto) accumula in continuo gli snapshot della
catena opzioni Deribit (BTC+ETH) nella tabella `option_chain_snapshots` del suo
SQLite (`/app/data/state.sqlite`, volume `cerbero-bite_bite-data`, root-only).
Questo e' lo storico per-strike REALE (bid/ask/mid/IV/greche/OI/volume) che il
progetto credeva non-backtestabile (muro ARGO/GEX): qui esiste ed e' gratis.
Il volume non e' leggibile direttamente (root), quindi esportiamo via `docker
exec` (il container ha pandas+pyarrow) e copiamo i parquet in data/options/.
Analogo a regime_fetcher.py -> data/regime/. Rigenera con:
uv run python scripts/analysis/options_fetcher.py
NB: snapshot da 2026-05-01 in poi (cerbero-bite e' partito allora), cadenza ~12min.
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
OUT = PROJECT_ROOT / "data" / "options"
BITE_COMPOSE = "/opt/docker/cerbero-bite/docker-compose.yml"
BITE_SERVICE = "cerbero-bite"
_EXPORT = r'''
import sqlite3, pandas as pd
con = sqlite3.connect("file:/app/data/state.sqlite?mode=ro", uri=True)
for asset in ("ETH", "BTC"):
df = pd.read_sql_query(
"SELECT * FROM option_chain_snapshots WHERE asset=?", con, params=(asset,))
df.to_parquet(f"/tmp/{asset.lower()}_chain.parquet")
print(f"{asset} {len(df)}")
try:
dv = pd.read_sql_query("SELECT * FROM dvol_history", con)
dv.to_parquet("/tmp/dvol_history.parquet"); print(f"DVOL {len(dv)}")
except Exception as e:
print("dvol skip", e)
# market_snapshots: pannello regime allineato (spot, dvol, VRP, funding, GEX dealer,
# gamma_flip, liquidation risk, oi_delta) -- feature reali pre-calcolate.
try:
ms = pd.read_sql_query("SELECT * FROM market_snapshots", con)
ms.to_parquet("/tmp/market_snapshots.parquet"); print(f"MARKET {len(ms)}")
except Exception as e:
print("market skip", e)
'''
def _container_id() -> str:
out = subprocess.run(["docker", "compose", "-f", BITE_COMPOSE, "ps", "-q", BITE_SERVICE],
capture_output=True, text=True, check=True)
cid = out.stdout.strip().splitlines()[0]
if not cid:
raise RuntimeError("container cerbero-bite non trovato (e' su?)")
return cid
def fetch() -> None:
OUT.mkdir(parents=True, exist_ok=True)
print("export dalla SQLite di cerbero-bite (docker exec)...")
r = subprocess.run(["docker", "compose", "-f", BITE_COMPOSE, "exec", "-T", BITE_SERVICE,
"python", "-c", _EXPORT], capture_output=True, text=True)
print(r.stdout.strip())
if r.returncode != 0:
print(r.stderr[-2000:], file=sys.stderr)
raise SystemExit("export fallito")
cid = _container_id()
for fn in ("eth_chain.parquet", "btc_chain.parquet", "dvol_history.parquet",
"market_snapshots.parquet"):
dst = OUT / fn
cp = subprocess.run(["docker", "cp", f"{cid}:/tmp/{fn}", str(dst)],
capture_output=True, text=True)
if cp.returncode == 0:
print(f" -> {dst.relative_to(PROJECT_ROOT)} ({dst.stat().st_size // 1024} KB)")
else:
print(f" (skip {fn}: {cp.stderr.strip()})")
print("OK. Loader: scripts/analysis/options_chain.py")
if __name__ == "__main__":
fetch()