aad69f9790
Ricerca onesta su BTC/ETH + universo HL, branch separato (nessun impatto live).
Harness condiviso altlib (causale, fee 0.10% RT, marginal vs TP01, day-boundary,
haircut $600). Test 19/19 verdi.
- A DVOL direzionale -> LEAD hedge/DD-dampener, NON sleeve (buy-the-fear; is_hedge).
- B Intraday ERM 8h -> LEAD forte / forward-monitor: earns_slot=True, ADDS oltre
SKH01 (TP01+SKH+ERM 60/25/15 FULL 1.88/HOLD 1.46/DD 8.9%).
Caveat: plateau hold-out single-row, multiple-testing non
deflazionato, exec 8h. Controllo TOD = FAIL atteso.
- C Cross-sectional non-mom (low-vol HL) -> DEBOLE/forward-monitor (deflated-Sh 0.13,
storia 2.5a, non eseguibile $600) STAT-MODE.
- D Macro regime-gate -> RIDONDANTE col trend (corr->TP01 0.989), SCARTATO.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
60 lines
2.5 KiB
Python
60 lines
2.5 KiB
Python
"""Test del filone B — INTRADAY REGIME (scripts/research/intraday_regime.py).
|
|
|
|
Verifica leggera e veloce (un solo asset) che:
|
|
* i target factory producano array della lunghezza giusta e CAUSALI (no look-ahead);
|
|
* il meccanismo ERM (efficiency-ratio regime momentum) sia long/short di natura;
|
|
* la cella canonica ERM 8h L=2 thr=0.35 abbia Sharpe FULL positivo netto fee (sanity dell'edge).
|
|
NB: NON costruisce la baseline TP01/SKH01 (lento) — quello e' nello script di ricerca.
|
|
"""
|
|
import sys
|
|
import importlib.util
|
|
|
|
import numpy as np
|
|
|
|
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
|
|
import altlib as al # noqa: E402
|
|
|
|
_spec = importlib.util.spec_from_file_location(
|
|
"intraday_regime", "/opt/docker/PythagorasGoal/scripts/research/intraday_regime.py")
|
|
ir = importlib.util.module_from_spec(_spec)
|
|
_spec.loader.exec_module(ir)
|
|
|
|
|
|
def test_erm_target_shape_and_ls():
|
|
df = al.get("BTC", "8h")
|
|
tgt = ir.make_erm(tf="8h", L_days=2.0, thr=0.35, long_flat=False)(df)
|
|
assert len(tgt) == len(df)
|
|
assert np.isfinite(tgt).all()
|
|
# L/S: deve esistere sia esposizione long sia short (non e' long-only)
|
|
assert (tgt > 0).any() and (tgt < 0).any()
|
|
# long_flat=True -> nessuno short
|
|
tgt_lf = ir.make_erm(tf="8h", L_days=2.0, thr=0.35, long_flat=True)(df)
|
|
assert (tgt_lf >= -1e-9).all()
|
|
|
|
|
|
def test_erm_causal_no_leak():
|
|
# causality_ok ricalcola il target su prefissi troncati e pretende che la coda combaci
|
|
res = al.causality_ok(ir.make_erm(tf="8h", L_days=2.0, thr=0.35, long_flat=False),
|
|
tf="8h", assets=("BTC",))
|
|
assert res["ok"], f"look-ahead in ERM: {res}"
|
|
|
|
|
|
def test_erm_winner_positive_full_sharpe():
|
|
fn = ir.make_erm(tf="8h", L_days=2.0, thr=0.35, long_flat=False)
|
|
for a in ("BTC", "ETH"):
|
|
df = al.get(a, "8h")
|
|
ev = al.eval_weights(df, fn(df), fee_side=0.0005) # 0.10% RT
|
|
assert ev["full"]["sharpe"] > 0.5, f"{a} full Sharpe {ev['full']['sharpe']}"
|
|
|
|
|
|
def test_vbr_and_tod_causal():
|
|
for fn in (ir.make_vbr(tf="8h", k=1.0, atr_win=14, long_flat=False),
|
|
ir.make_tod(tf="1h", long_flat=True)):
|
|
res = al.causality_ok(fn, tf=("8h" if fn is not None else "1h"),
|
|
assets=("BTC",)) if False else None
|
|
# VBR causale (8h) e TOD causale (1h), un asset per velocita'
|
|
assert al.causality_ok(ir.make_vbr(tf="8h", k=1.0, atr_win=14, long_flat=False),
|
|
tf="8h", assets=("BTC",))["ok"]
|
|
assert al.causality_ok(ir.make_tod(tf="1h", long_flat=True),
|
|
tf="1h", assets=("BTC",))["ok"]
|