feat(options): attach_market() panel helper (regime panel, causal, no look-ahead)
attach_market(df, asset): merge_asof causale del pannello market_snapshots (spot/VRP/funding/net-GEX/gamma-flip/liquidation) sul prezzo, pronto per regime_lab. Fix look-ahead: merge su datetime tz-aware (ns-aligned), MAI astype(int64) su datetime (darebbe ns -> match all'ultimo snapshot = leak). Copertura reale documentata: net-GEX denso solo da ~2026-05-01 (~5-6 sett, singolo regime) -> infrastruttura pronta, edge validabile solo forward. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,6 +68,30 @@ def load_market(asset: str | None = None) -> pd.DataFrame:
|
||||
return df.sort_values("ts_ms").reset_index(drop=True)
|
||||
|
||||
|
||||
def attach_market(price_df: pd.DataFrame, asset: str, cols: list[str] | None = None) -> pd.DataFrame:
|
||||
"""merge_asof CAUSALE: ogni barra di price_df (serve colonna 'timestamp' in ms) riceve
|
||||
l'ultimo market_snapshot con ts <= barra. Pannello pronto per regime_lab/ricerca:
|
||||
spot, dvol, realized_vol_30d, iv_minus_rv (VRP), funding perp/cross, dealer_net_gamma
|
||||
(net-GEX), gamma_flip_level, oi_delta_pct_4h, liquidation_long/short_risk.
|
||||
Ritorna una copia con le colonne pannello (NaN dove non c'e' ancora storia: dal 2026-03-26)."""
|
||||
m = load_market(asset)
|
||||
cols = cols or (_MKT_NUM + ["liquidation_long_risk", "liquidation_short_risk"])
|
||||
keep = [c for c in cols if c in m.columns]
|
||||
base = price_df.copy()
|
||||
# chiave di merge = datetime tz-aware (robusto a timestamp int-ms o datetime; NIENTE astype int64
|
||||
# su datetime -> darebbe nanosecondi e matcherebbe tutto all'ultimo snapshot = LOOK-AHEAD).
|
||||
if np.issubdtype(base["timestamp"].dtype, np.integer):
|
||||
base["_k"] = pd.to_datetime(base["timestamp"], unit="ms", utc=True)
|
||||
else:
|
||||
base["_k"] = pd.to_datetime(base["timestamp"], utc=True)
|
||||
base["_k"] = base["_k"].astype("datetime64[ns, UTC]")
|
||||
mk = m[["ts"] + keep].rename(columns={"ts": "_k"})
|
||||
mk["_k"] = mk["_k"].astype("datetime64[ns, UTC]")
|
||||
out = pd.merge_asof(base.sort_values("_k"), mk.sort_values("_k"),
|
||||
on="_k", direction="backward")
|
||||
return out.drop(columns="_k")
|
||||
|
||||
|
||||
class OptionChain:
|
||||
def __init__(self, asset: str):
|
||||
self.asset = asset
|
||||
|
||||
Reference in New Issue
Block a user