14522262e6
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera libreria "validata OOS" era artefatto di feed contaminato (print fantasma del feed Cerbero TESTNET + storico Binance/USDT). - Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE 50-82% barre flat; XRP/BNB non certificabili). - Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST con segnale residuo, da ri-validare in isolamento. - Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio, runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/ portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/ (preservati, non cancellati). Diario consolidato in un unico documento. - Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal + src/backtest/engine + load_data; tool dati certificati (rebuild_history, certify_feed, audit_feed, multi_source_check). - Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
87 lines
3.5 KiB
Python
87 lines
3.5 KiB
Python
import sys; sys.path.insert(0,".")
|
|
import numpy as np, pandas as pd
|
|
from scripts.analysis.regime_lab import load_features
|
|
from scripts.analysis.explore_lab import atr
|
|
|
|
FEE=0.001; LEV=3
|
|
|
|
def build(df, gate, k=2.5, sl_atr=2.0, mb=24, bb=50):
|
|
c=df['close'].values; a=atr(df,14)
|
|
ma=pd.Series(c).rolling(bb).mean().values; sd=pd.Series(c).rolling(bb).std().values
|
|
ent=[]
|
|
for i in range(bb+14,len(c)-1):
|
|
if np.isnan(sd[i]) or sd[i]==0 or np.isnan(a[i]): continue
|
|
if not gate(df,i): continue
|
|
if c[i]<ma[i]-k*sd[i]: d,sl=1,c[i]-sl_atr*a[i]
|
|
elif c[i]>ma[i]+k*sd[i]: d,sl=-1,c[i]+sl_atr*a[i]
|
|
else: continue
|
|
ent.append({'i':i,'d':d,'tp':ma[i],'sl':sl,'mb':mb})
|
|
return ent
|
|
|
|
def per_year(df, ent):
|
|
"""replay intrabar fedele (sl-first, tp, poi max_bars@close) -> per anno {n,ret%,win%}."""
|
|
h=df['high'].values; l=df['low'].values; c=df['close'].values
|
|
ts=pd.to_datetime(df['timestamp'],unit='ms',utc=True)
|
|
Y={}
|
|
last=-1
|
|
for e in ent:
|
|
i=e['i']
|
|
if i<=last: continue
|
|
d=e['d']; tp=e['tp']; sl=e['sl']; j=min(i+e['mb'],len(c)-1)
|
|
exit_p=c[j]
|
|
for t in range(i+1,j+1):
|
|
if d==1:
|
|
if l[t]<=sl: exit_p=sl; j=t; break
|
|
if h[t]>=tp: exit_p=tp; j=t; break
|
|
else:
|
|
if h[t]>=sl: exit_p=sl; j=t; break
|
|
if l[t]<=tp: exit_p=tp; j=t; break
|
|
ret=(exit_p-c[i])/c[i]*d*LEV - FEE*LEV
|
|
last=j; yr=ts.iloc[i].year
|
|
if yr not in Y: Y[yr]=[0,0.0,0]
|
|
Y[yr][0]+=1; Y[yr][1]+=ret*100; Y[yr][2]+= (ret>0)
|
|
return Y
|
|
|
|
# gate functions
|
|
def g_hurst_calm(df,i): return df['hurst'].iloc[i]<0.55 and not np.isnan(df['dvol_pct'].iloc[i]) and df['dvol_pct'].iloc[i]<0.40
|
|
def g_vrp_neg(df,i): return not np.isnan(df['vrp'].iloc[i]) and df['vrp'].iloc[i]<0
|
|
def g_hig_vrp(df,i):
|
|
hi=df['higuchi'].iloc[i]; return (not np.isnan(hi)) and hi>1.5 and (not np.isnan(df['vrp'].iloc[i])) and df['vrp'].iloc[i]<0
|
|
def g_none(df,i): return True
|
|
|
|
STRATS=[("HurstCalmFade (hurst<.55 & DVOL<p40)",g_hurst_calm),
|
|
("VRP<0 Fade (core driver)",g_vrp_neg),
|
|
("HigVRP Fade (Higuchi>1.5 & VRP<0)",g_hig_vrp),
|
|
("Fade NUDA (no gate, baseline)",g_none)]
|
|
|
|
# regime mercato BTC per anno (da BTC close annuale)
|
|
btc=load_features("BTC","1d")
|
|
bts=pd.to_datetime(btc['timestamp'],unit='ms',utc=True); bc=btc['close'].values
|
|
mkt={}
|
|
for yr in range(2021,2027):
|
|
m=(bts.dt.year==yr).values
|
|
if m.sum()>5:
|
|
r=(bc[m][-1]/bc[m][0]-1)*100
|
|
mkt[yr]=("BULL" if r>40 else "BEAR" if r<-30 else "RANGE", r)
|
|
|
|
for asset in ("BTC","ETH"):
|
|
df=load_features(asset,"1h")
|
|
print(f"\n{'='*78}\n {asset} 1h — performance per anno (somma ret% per-trade, netto leva3x+fee0.10%)\n{'='*78}")
|
|
print(f" {'Strategia':<40} " + " ".join(f"{y}" for y in range(2021,2027)))
|
|
for name,g in STRATS:
|
|
ent=build(df,g); Y=per_year(df,ent)
|
|
cells=[]
|
|
for y in range(2021,2027):
|
|
if y in Y and Y[y][0]>0:
|
|
cells.append(f"{Y[y][1]:+5.0f}")
|
|
else: cells.append(" . ")
|
|
print(f" {name:<40} " + " ".join(cells))
|
|
# riga trades/anno per la strategia principale
|
|
ent=build(df,g_hurst_calm); Y=per_year(df,ent)
|
|
tr=" ".join(f"{Y.get(y,[0])[0]:>5}" for y in range(2021,2027))
|
|
print(f" {'(HurstCalmFade trades/anno)':<40} {tr}")
|
|
|
|
print(f"\n REGIME MERCATO BTC per anno (ret% annuale prezzo):")
|
|
for y in range(2021,2027):
|
|
if y in mkt: print(f" {y}: {mkt[y][0]:6} ({mkt[y][1]:+.0f}%)")
|