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>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user