fix(TP01): bug look-ahead ffill mixed-TF -> deploy a >=12h (1d), strategia DIFENSIVA
Segnalato: ffill MIXED-TIMEFRAME su barre open-labeled (resample label="left") gonfiava il 4h (~1.60 -> reale ~1.1). Ri-verifica per-SINGOLO-TF leak-free (guard prefix-recompute, leak=0 su 4h/6h/12h/1d): FULL Sh piatto ~1.3, hold-out 2025-26 MIGLIORE a 1d (Sh 0.31 / +3.5% vs buy&hold -39%). Conclusione adottata: NON scendere sotto le 12h (sotto, costi+overfit dominano senza vantaggio). - trend_portfolio.py: canonica PORT LF1d; resample_tf/resample_1d (resample_4h deprecato deploy); docstring con nota look-ahead + natura DIFENSIVA (taglia DD ~6x, non alpha). - paper_trend.py: deploy a 1d (resample_1d, build_bars). 5 test passano. - CLAUDE.md: TP01 ridescritta (>=12h/1d, gotcha ffill mixed-TF, difensiva). - tp01_lowfreq.py + diario 2026-06-19-tp01-lookahead-fix-lf.md. Gotcha: mai ffill/combine mixed-TF su timestamp open-labeled (close propagata indietro = leak). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,13 +4,16 @@ Vincitrice della ricerca su dati certificati BTC/ETH (Deribit mainnet). TSMOM mu
|
||||
(1-3-6 mesi) vol-targeted, portafoglio 50/50 BTC+ETH. Validata onestamente (no look-ahead,
|
||||
fee 0.10% RT, positiva ogni anno 2019-2026, robusta su griglia e su tutti i timeframe 15m-1d).
|
||||
|
||||
Config canonica deployabile (PORT LF4h):
|
||||
timeframe 4h, LONG-FLAT (niente short), vol-target 20%, leverage cap 2x.
|
||||
-> CAGR ~16.6%, Sharpe ~1.32, maxDD ~12.3% (backtest 2019-2026 su 50/50 BTC+ETH).
|
||||
Config canonica deployabile (PORT LF1d):
|
||||
timeframe >=12h (1d RACCOMANDATO), LONG-FLAT (niente short), vol-target 20%, leverage cap 2x.
|
||||
-> FULL Sharpe ~1.30, maxDD ~14%, HOLD-OUT 2025-26 Sharpe ~0.31 (calcolo per-TF leak-free).
|
||||
|
||||
Perche' long-flat e 4h: gli short del trend rendono meno e aggiungono DD; il 4h e' il punto
|
||||
dolce (meno rumore/fee del 15m, meno lag dell'1d). Vedi docs/diary/2026-06-19-research-synthesis.md
|
||||
e scripts/research/trackD_*.py.
|
||||
NB LOOK-AHEAD (2026-06-19): un ffill MIXED-TIMEFRAME su barre open-labeled (label="left")
|
||||
gonfiava il 4h (~1.60 -> reale ~1.1). Il calcolo per-SINGOLO-TF e' leak-free (guard
|
||||
prefix-recompute), ma sotto le 12h costi+overfitting dominano SENZA vantaggio reale (FULL Sh
|
||||
piatto ~1.3 da 12h a 4h; hold-out MIGLIORE a 1d). -> NON scendere sotto le 12h; deploy a 1d.
|
||||
TP01 e' DIFENSIVA (taglia il DD ~6x vs buy&hold), NON alpha. Vedi
|
||||
docs/diary/2026-06-19-tp01-lookahead-fix-lf.md e scripts/analysis/tp01_lowfreq.py.
|
||||
|
||||
API (tutto causale, decide con dati <= close[i]):
|
||||
from src.strategies.trend_portfolio import TrendPortfolio, CANONICAL
|
||||
@@ -168,16 +171,28 @@ def _bars_per_year(idx: pd.DatetimeIndex) -> float:
|
||||
return 86400 * 365.25 / dt if dt and dt > 0 else 365.25
|
||||
|
||||
|
||||
def resample_4h(df_1h: pd.DataFrame) -> pd.DataFrame:
|
||||
"""Resample 1h -> 4h (confini 00:00 UTC). Schema con 'datetime'."""
|
||||
def resample_tf(df_1h: pd.DataFrame, rule: str) -> pd.DataFrame:
|
||||
"""Resample 1h -> rule (confini 00:00 UTC). Schema con 'datetime'.
|
||||
NB: usare SOLO per-singolo-TF (qui leak-free); MAI ffill/combine mixed-TF su questi
|
||||
timestamp open-labeled (label='left') -> look-ahead. Deploy a >=12h (vedi docstring modulo)."""
|
||||
g = df_1h.copy()
|
||||
idx = pd.to_datetime(g["timestamp"], unit="ms", utc=True)
|
||||
idx.name = "dt"
|
||||
g.index = idx
|
||||
out = g.resample("4h", label="left", closed="left").agg(
|
||||
out = g.resample(rule, label="left", closed="left").agg(
|
||||
{"open": "first", "high": "max", "low": "min", "close": "last", "volume": "sum"})
|
||||
out = out.dropna(subset=["open"])
|
||||
out["datetime"] = out.index
|
||||
epoch = pd.Timestamp("1970-01-01", tz="UTC")
|
||||
out["timestamp"] = ((out.index - epoch) // pd.Timedelta(milliseconds=1)).astype("int64")
|
||||
return out.reset_index(drop=True)[["timestamp", "open", "high", "low", "close", "volume", "datetime"]]
|
||||
|
||||
|
||||
def resample_1d(df_1h: pd.DataFrame) -> pd.DataFrame:
|
||||
"""TF canonico di deploy (>=12h). Resample 1h -> 1d."""
|
||||
return resample_tf(df_1h, "1D")
|
||||
|
||||
|
||||
def resample_4h(df_1h: pd.DataFrame) -> pd.DataFrame:
|
||||
"""DEPRECATO per il deploy (sotto le 12h: costi+overfit dominano). Retro-compat ricerca."""
|
||||
return resample_tf(df_1h, "4h")
|
||||
|
||||
Reference in New Issue
Block a user