Files
PythagorasGoal/tests/test_dvol_directional.py
T
Adriano Dal Pastro aad69f9790 research(crypto): 4 filoni 2026-06-29 — ERM lead sub-daily (forward), 3 scartati/deboli
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>
2026-06-29 19:48:36 +00:00

58 lines
2.3 KiB
Python

"""Test del filone DVOL-DIREZIONALE (scripts/research/dvol_directional.py).
Verifica le proprieta' che DEVONO valere per ogni segnale del progetto:
* il percentile espandente del DVOL e' CAUSALE (rank su un prefisso == rank(full)[:cut]);
* il leader (DVOL-fear long-flat) passa causality_ok di altlib (niente future-peeking);
* a $600 (eval_weights_smallcap) l'haircut e' trascurabile (segnale eseguibile, low-turnover);
* sign-falsification: la tesi (buy-the-fear) batte il suo flip (buy-the-calm) sull'era DVOL.
"""
import sys
from pathlib import Path
import numpy as np
import pytest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT / "scripts" / "research" / "alt"))
import altlib as al # noqa: E402
from scripts.research import dvol_directional as dd # noqa: E402
def test_expanding_rank_is_causal():
"""rank calcolato su un prefisso deve coincidere con rank(full) ristretto al prefisso."""
x = np.asarray(al.dvol(al.get("BTC", "1d"), "BTC"), float)
full = dd._expanding_rank_arr(x)
cut = int(len(x) * 0.7)
pref = dd._expanding_rank_arr(x[:cut])
a, b = full[:cut], pref
m = np.isfinite(a) & np.isfinite(b)
assert m.sum() > 100
assert np.max(np.abs(a[m] - b[m])) < 1e-9
def test_leader_causality_ok():
"""Il leader (DVOL-fear q0.4 long-flat) non deve avere look-ahead (altlib causality_ok)."""
fn = dd.make_dvol_level(0.4, "fear", True)
co = al.causality_ok(fn, tf="1d")
assert co["ok"], co
assert co["max_tail_diff"] <= 1e-6
@pytest.mark.parametrize("asset", ["BTC", "ETH"])
def test_leader_executable_at_600(asset):
"""A $600 il segnale e' a basso turnover: haircut Sharpe trascurabile, trade eseguiti reali."""
fn = dd.make_dvol_level(0.4, "fear", True)
df = al.get(asset, "1d")
sc = al.eval_weights_smallcap(df, al._call_target(fn, df, asset), capital=600, min_order=5)
assert sc["n_executed_trades"] > 10
assert abs(sc["sharpe_haircut"]) < 0.10
def test_sign_falsification():
"""La tesi (buy-the-fear) deve battere il flip (buy-the-calm) sull'era DVOL."""
thesis = dd.era_full_sharpe(dd.make_dvol_level(0.5, "fear", True))["sharpe"]
flip = dd.era_full_sharpe(dd.make_dvol_level(0.5, "calm", True))["sharpe"]
assert thesis > flip