5ac4e16af8
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>
101 lines
3.3 KiB
Python
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))
|