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

101 lines
3.3 KiB
Python

"""BRK10 — Vol-contraction (squeeze) long
HYPOTHESIS: When Bollinger bandwidth is in its low expanding-percentile (squeeze detected),
go long-flat on subsequent upside close > midline. Honest entry at close[i].
Strategy logic:
- Compute Bollinger bandwidth = (upper - lower) / middle
- Compute expanding percentile of bandwidth to define "squeeze" (low vol percentile)
- Long signal: bandwidth in low percentile (squeeze) AND close > midline (momentum up)
- Vol-targeted position, long-flat (no short)
Internal grid (<=4 configs, total backtests <=6):
- bb_win: Bollinger window [20, 30]
- squeeze_pct: bandwidth percentile threshold [25, 20]
Best config picked by min(BTC/ETH) hold-out Sharpe.
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
import altlib as al
import numpy as np
import pandas as pd
def make_target(df: pd.DataFrame, bb_win: int = 20, k: float = 2.0,
squeeze_pct: float = 25.0) -> np.ndarray:
"""
BRK10: vol-contraction squeeze long.
- Compute BB bandwidth = (upper - lower) / mid (all causal via bbands)
- Use expanding percentile of bandwidth to define squeeze
- Long when: bandwidth <= squeeze_pct expanding percentile AND close > midline
- Vol-targeted position, long-flat
"""
c = df["close"].values.astype(float)
n = len(c)
# Bollinger bands (causal: uses data <= i)
upper, mid, lower = al.bbands(c, win=bb_win, k=k)
# Bandwidth = (upper - lower) / mid; avoid div by zero
bw = np.where(mid > 0, (upper - lower) / mid, np.nan)
# Expanding percentile of bandwidth (causal: uses data <= i)
# squeeze = bandwidth is in the lower squeeze_pct% of historical values
squeeze_mask = np.zeros(n, dtype=bool)
bw_series = pd.Series(bw)
for i in range(bb_win, n):
hist = bw_series.iloc[:i+1].dropna().values
if len(hist) < bb_win:
continue
threshold = np.percentile(hist, squeeze_pct)
if np.isfinite(bw[i]) and bw[i] <= threshold:
squeeze_mask[i] = True
# Direction: long when squeeze AND close > midline
# NaN midline bars -> flat
direction = np.where(
squeeze_mask & np.isfinite(mid) & (c > mid),
1.0,
0.0
)
# Vol-targeted, long-flat
target = al.vol_target(direction, df, target_vol=0.20, vol_win_days=30, leverage_cap=2.0)
return target
# Grid: bb_win x squeeze_pct (4 configs, both tested on 1d only -> 4 total backtests <= 6)
GRID = [
dict(bb_win=20, squeeze_pct=25.0),
dict(bb_win=20, squeeze_pct=20.0),
dict(bb_win=30, squeeze_pct=25.0),
dict(bb_win=30, squeeze_pct=20.0),
]
best_rep = None
best_score = -9999.0
best_cfg = None
TFS = ("1d",)
for cfg in GRID:
print(f"\n--- Testing config: {cfg} ---")
label = f"BRK10_bb{cfg['bb_win']}_sq{int(cfg['squeeze_pct'])}"
fn = lambda df, c=cfg: make_target(df, bb_win=c["bb_win"], squeeze_pct=c["squeeze_pct"])
rep = al.study_weights(label, fn, tfs=TFS)
# Score = min holdout Sharpe across assets in best TF
score = rep["verdict"].get("best_holdout_sharpe", -9999.0) or -9999.0
print(al.fmt(rep))
if score > best_score:
best_score = score
best_rep = rep
best_cfg = cfg
print("\n" + "=" * 70)
print(f"BEST CONFIG: {best_cfg}")
print(al.fmt(best_rep))
print("JSON:", al.as_json(best_rep))