Files
Adriano Dal Pastro 5ac4e16af8 research(alt): sweep 104 strategie alternative su Deribit (153 agenti) + marginal scorer
Ondata di ricerca onesta a largo spettro su BTC/ETH+DVOL certificati: 104 ipotesi
distinte (11 famiglie), un agente-finder per ipotesi, verifica avversariale a 3
scettici sui promettenti, sintesi (153 agenti totali). Esito: NIENTE di nuovo regge
-> conferma del soffitto strutturale ~1.3 BTC/ETH-direzionale; lo stack
TP01+XS01+VRP01 resta imbattuto.

- altlib.py: harness condiviso vettoriale leak-free (eval_weights/study_weights,
  fee-sweep, both-asset + hold-out 2025+). Riproduce i numeri canonici di TP01.
- MARGINAL SCORER (study_marginal/marginal_vs_tp01): Sharpe INCREMENTALE vs baseline
  TP01 (corr, blend uplift OOS, alpha residua) + jackknife OOS (clean-year +
  drop-best-month). earns_slot = abs!=FAIL & ADDS & robust_oos. Smaschera gli overlay
  su TSMOM con PASS assoluti fasulli (CMB04, VOL11, ...) e il falso positivo KAMA
  (ADDS ma muore al jackknife).
- runs/*.py (104) script riproducibili per ipotesi; wf_altstrat.js workflow.
- Verdetto: 0 candidati deployabili; 2 LEAD fragili (VOL08, STA05_LS) da forward-monitor.
- test_marginal_scorer.py blocca baseline + invarianti. Suite: 32 verde.

Diario: docs/diary/2026-06-20-alt-strategies-100agent-sweep.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 19:50:39 +00:00

95 lines
3.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""TRD13 — SMA200 regime + vol-target (long-flat).
HYPOTHESIS: Long when close > SMA200, flat otherwise.
Position sized by vol_target(20%, 30d). Pure regime-trend.
Small grid: SMA window {150, 200} x vol_target window {20, 30} days.
Only 2 param sets tested (4 total cells with BTC/ETH) to stay within budget.
Best config selected by min(BTC, ETH) full Sharpe.
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
import altlib as al
import numpy as np
# --------------------------------------------------------------------------
# Signal factory
# --------------------------------------------------------------------------
def make_target(sma_win_bars: int, vol_win_days: int):
"""Returns a function df -> target_array using SMA regime + vol_target."""
def target_fn(df):
c = df["close"].values
bpd = al.bars_per_day(df)
# SMA computed causally (sma already uses rolling with min_periods=win)
s200 = al.sma(c, sma_win_bars)
# Direction: +1 when close > SMA, else 0 (long-flat)
direction = np.where(c > s200, 1.0, 0.0)
# Vol-targeted position
vol_win = int(round(vol_win_days * bpd))
pos = al.vol_target(direction, df, target_vol=0.20,
vol_win_days=vol_win_days, leverage_cap=2.0)
# Mask NaN (during SMA warmup) -> flat
pos = np.where(np.isnan(s200), 0.0, pos)
return pos
return target_fn
# --------------------------------------------------------------------------
# Grid: 2 configs × 2 TFs (1d, 12h)
# --------------------------------------------------------------------------
CONFIGS = [
{"label": "SMA150_v20", "sma_days": 150, "vol_win": 20},
{"label": "SMA200_v30", "sma_days": 200, "vol_win": 30},
]
TFS = ("1d", "12h")
reports = []
for cfg in CONFIGS:
sma_days = cfg["sma_days"]
vol_win = cfg["vol_win"]
def make_fn(sd=sma_days, vw=vol_win):
def target_fn(df):
bpd = al.bars_per_day(df)
sma_bars = int(round(sd * bpd))
c = df["close"].values
s = al.sma(c, sma_bars)
direction = np.where(c > s, 1.0, 0.0)
pos = al.vol_target(direction, df, target_vol=0.20,
vol_win_days=vw, leverage_cap=2.0)
pos = np.where(np.isnan(s), 0.0, pos)
return pos
return target_fn
name = f"TRD13_{cfg['label']}"
rep = al.study_weights(name, make_fn(), tfs=TFS)
reports.append((rep, cfg))
# --------------------------------------------------------------------------
# Pick best config by min(BTC_full_sharpe, ETH_full_sharpe) on best TF
# --------------------------------------------------------------------------
def best_score(rep):
v = rep["verdict"]
best_tf = v["best_tf"]
# find the cell for best_tf
for cell in rep["cells"]:
if cell["tf"] == best_tf:
btc_sh = cell["per_asset"]["BTC"]["full"]["sharpe"]
eth_sh = cell["per_asset"]["ETH"]["full"]["sharpe"]
return min(btc_sh, eth_sh)
return -999.0
best_rep, best_cfg = max(reports, key=lambda x: best_score(x[0]))
print("\n" + "=" * 70)
print(f"BEST CONFIG: {best_cfg}")
print("=" * 70)
print(al.fmt(best_rep))
print("JSON:", al.as_json(best_rep))