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>
82 lines
3.4 KiB
Python
82 lines
3.4 KiB
Python
"""Smoke LIVE del nuovo percorso 15m: fetch DIRETTO 15m da Cerbero per ETH/BTC +
|
|
freschezza + flat-fraction + un tick reale del PairsWorker(flat_skip).
|
|
|
|
Verifica cio' che il backtest non vede: che Cerbero serva candele 15m fresche per
|
|
entrambe le gambe (il runner ora le fetcha dirette, non resamplate dal 1h) e che il
|
|
worker 15m le processi senza errori. NON apre ordini reali (l'esecuzione a 2 gambe e'
|
|
gia' coperta da live_pairs_smoke.py, indipendente dal timeframe).
|
|
|
|
uv run python scripts/analysis/pairs15m_live_smoke.py
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import shutil
|
|
import tempfile
|
|
from datetime import datetime, timezone, timedelta
|
|
from pathlib import Path
|
|
|
|
import pandas as pd
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
from src.live.cerbero_client import CerberoClient
|
|
from src.live.multi_runner import INSTRUMENT_MAP
|
|
from src.live.pairs_worker import PairsWorker
|
|
|
|
CFG = {"n": 66, "z_in": 1.674, "z_exit": 1.0, "max_bars": 35, "flat_skip": True}
|
|
|
|
|
|
def fetch15(cli, asset, days=14):
|
|
inst = INSTRUMENT_MAP.get(asset, f"{asset}-PERPETUAL")
|
|
end = datetime.now(timezone.utc)
|
|
start = end - timedelta(days=days)
|
|
candles = cli.get_historical_v2(inst, start.strftime("%Y-%m-%d"),
|
|
end.strftime("%Y-%m-%d"), "15m")
|
|
if not candles:
|
|
return inst, None
|
|
df = pd.DataFrame(candles)
|
|
df["timestamp"] = df["timestamp"].astype("int64")
|
|
return inst, df.sort_values("timestamp").reset_index(drop=True)
|
|
|
|
|
|
def main():
|
|
print("=" * 84)
|
|
print(" SMOKE LIVE — ETH/BTC pairs 15m (fetch diretto Cerbero + tick worker flat-skip)")
|
|
print("=" * 84)
|
|
cli = CerberoClient()
|
|
inst_a, da = fetch15(cli, "ETH")
|
|
inst_b, db = fetch15(cli, "BTC")
|
|
ok = True
|
|
for asset, inst, df in [("ETH", inst_a, da), ("BTC", inst_b, db)]:
|
|
if df is None or df.empty:
|
|
print(f" {asset} ({inst}): NESSUNA candela 15m -> FAIL"); ok = False; continue
|
|
last = pd.to_datetime(df["timestamp"].iloc[-1], unit="ms", utc=True)
|
|
age_min = (datetime.now(timezone.utc) - last).total_seconds() / 60
|
|
flat = ((df["open"] == df["high"]) & (df["high"] == df["low"]) &
|
|
(df["low"] == df["close"])).mean() * 100
|
|
fresh = age_min < 60
|
|
print(f" {asset} ({inst}): {len(df)} barre 15m | ultima {last:%Y-%m-%d %H:%M} "
|
|
f"({age_min:.0f} min fa, {'FRESCO' if fresh else 'STALE'}) | flat {flat:.1f}%")
|
|
ok &= fresh
|
|
if da is None or db is None:
|
|
print("\n ESITO: FAIL (feed 15m assente)."); return
|
|
# tick reale del worker 15m
|
|
tmp = Path(tempfile.mkdtemp(prefix="smoke15m_"))
|
|
try:
|
|
w = PairsWorker("ETH", "BTC", "15m", params=CFG, fee_rt=0.001, data_dir=tmp)
|
|
df_a = pd.DataFrame({"timestamp": da["timestamp"], "open": da["open"], "high": da["high"],
|
|
"low": da["low"], "close": da["close"]})
|
|
df_b = pd.DataFrame({"timestamp": db["timestamp"], "open": db["open"], "high": db["high"],
|
|
"low": db["low"], "close": db["close"]})
|
|
w.tick(df_a, df_b)
|
|
print(f"\n Worker 15m flat_skip={w.flat_skip} -> tick OK | {w.status_summary}")
|
|
print(f" ESITO: {'OK — feed 15m fresco e worker ticca' if ok else 'ATTENZIONE: feed 15m stale/parziale'}")
|
|
finally:
|
|
shutil.rmtree(tmp, ignore_errors=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|