Files
Adriano Dal Pastro 14522262e6 chore(reset): v2.0.0 — storico certificato Deribit mainnet, ripartenza pulita
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>
2026-06-19 15:20:59 +00:00

82 lines
3.9 KiB
Python

"""Smoke ESECUZIONE REALE a 2 gambe (PairsExecutionClient) su Deribit testnet.
Apre e chiude una posizione pair micro (ETH/BTC lineari USDC) come farebbe il
PairsWorker, esercitando: open_pair (2 market simultanei long A/short B), verifica
per-gamba, close_pair (2 reduce-only), riconciliazione PnL/fee a 2 gambe.
Verifica finale: conto flat su ENTRAMBI gli strumenti.
Costo testnet = €0. Non tocca lo stato di produzione (data_dir temporanea).
uv run python scripts/analysis/live_pairs_smoke.py
"""
from __future__ import annotations
import tempfile
from pathlib import Path
from src.live.cerbero_client import CerberoClient
from src.live.execution import ExecutionClient, PairsExecutionClient
from src.live.pairs_worker import PairsWorker
def main() -> None:
client = CerberoClient()
acct = client.get_account_summary(currency="USDC")
print(f"Account testnet equity={acct.get('equity')} USDC testnet={acct.get('testnet')}")
if not acct.get("testnet"):
raise SystemExit("ABORT: non testnet")
pex = PairsExecutionClient(leg=ExecutionClient(client=client))
inst = {"ETH": "ETH_USDC-PERPETUAL", "BTC": "BTC_USDC-PERPETUAL"}
pex.ensure_specs(*inst.values())
print(f"strumenti: {inst}")
# GUARDIA: questo conto e' condiviso col runner di produzione (fade reali su
# BTC/ETH_USDC). Se ci sono posizioni aperte, ABORT: lo smoke userebbe lo stesso
# strumento e la verifica "conto flat" sarebbe falsata (e un eventuale
# close_position flatterebbe le quote del runner). Mai eseguire close_position qui.
for i in inst.values():
sz = pex.leg._position_size(i)
if sz != 0:
raise SystemExit(f"ABORT: posizione di produzione aperta su {i} (size={sz}). "
f"Eseguire lo smoke solo a conto flat.")
with tempfile.TemporaryDirectory() as tmp:
# capitale piccolo -> notional micro per gamba (capital*pos*lev)
w = PairsWorker("ETH", "BTC", "1h", capital=60.0, position_size=0.15, leverage=2.0,
data_dir=Path(tmp), executor=pex, exec_instruments=inst)
print(f"execution_enabled={w.execution_enabled} notional/gamba atteso=${60*0.15*2:.0f}")
# prezzi sim plausibili (il ramo sim del worker li usa per il suo ledger;
# il reale usa i fill veri). Niente zeri -> niente divisione per zero.
pa = pex.leg._mark_price(inst["ETH"]) or 1668.0
pb = pex.leg._mark_price(inst["BTC"]) or 63000.0
print("\n[A] OPEN long ratio (long ETH / short BTC)")
w._open(1, pa, pb, -2.5)
print(f" real_in_position={w.real_in_position} dir={w.real_dir}")
print(f" gamba A {w.real_side_a} {w.real_amount_a} @ {w.real_entry_a} (notional ${w.real_notional_a:.2f})")
print(f" gamba B {w.real_side_b} {w.real_amount_b} @ {w.real_entry_b} (notional ${w.real_notional_b:.2f})")
print(f" entry_fee ${w.real_entry_fee:.5f}")
assert w.real_in_position, "open pair non verificato"
assert w.real_side_a == "buy" and w.real_side_b == "sell"
print("\n[B] CLOSE (richiude entrambe le gambe reduce-only)")
cap0 = w.real_capital
pa2 = pex.leg._mark_price(inst["ETH"]) or pa
pb2 = pex.leg._mark_price(inst["BTC"]) or pb
w._close(pa2, pb2, 0.3, "mean_revert")
print(f" real_capital {cap0:.4f} -> {w.real_capital:.4f}{w.real_capital-cap0:+.4f}) trades={w.real_trades}")
assert not w.real_in_position, "close pair non azzera la posizione"
# verifica conto flat su entrambi gli strumenti
pa = pex.leg._position_size(inst["ETH"])
pb = pex.leg._position_size(inst["BTC"])
print(f"\n posizione netta ETH={pa} BTC={pb}")
print("✓ catena pairs OK — open 2 gambe verificate, close 2 gambe, fee reali, conto flat"
if pa == 0 and pb == 0 else
f"⚠ residuo sul book (ETH={pa} BTC={pb}) — verificare manualmente")
if __name__ == "__main__":
main()