cddea50c5a
Correzione post-micro-test (il conto e' USDC, non BTC/ETH): - deribit.py: INSTRUMENT -> BTC/ETH_USDC-PERPETUAL (lineari, gli unici eseguibili sul conto USDC); notional_to_amount gestisce i lineari (amount in base-coin = notional/price); + quantize_price; trade_history (read-only) per i trade reali. build_rebalance_order passa il prezzo. - shadow.py: sizing col prezzo; espone live_trades (trade reali eseguiti su Deribit). Entrata/uscita verificate (logica presa da Old/src/live/execution.py): - execution.py: open() market verificato (state=='filled' + trade, fill/fee reali, filled_amount autorevole), close() market reduce_only (le CHIUSURE si tentano SEMPRE, senza cap), disaster-SL STOP_MARKET reduce_only. Cap di size SOLO sulle aperture. Fill dataclass. - microtest.py: usa open()/close(); safe-close se l'apertura non e' verificata. Dashboard: sezione PAPER (backtest+forward) separata da sezione LIVE (conto reale Deribit: shadow TP01 + Trades REALI eseguiti). Test 27/27. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
93 lines
4.0 KiB
Python
93 lines
4.0 KiB
Python
"""MICRO-TEST esecuzione su Deribit mainnet — round-trip minimo su BTC_USDC-PERPETUAL, apri+chiudi.
|
|
|
|
Conto reale = USDC -> strumento ESEGUIBILE = perp LINEARE `BTC_USDC-PERPETUAL` (amount in BTC, step
|
|
0.0001 ~ $6). Valida il percorso ordine->fill->reconciliation->chiusura con soldi VERI a size MINIMA
|
|
(~0x leva, decoupled dal segnale): test della plumbing, non della strategia. Usa open()/close()
|
|
verificati di src/live/execution.py (logica entrata/uscita presa da Old).
|
|
|
|
Sicurezze: default DRY-RUN. Pre-flight ABORT se posizione preesistente. La chiusura (reduce_only,
|
|
sempre permessa) flatta comunque dopo l'apertura; verifica finale di FLAT (alert se no).
|
|
|
|
uv run python scripts/live/microtest.py # DRY-RUN: nessun ordine inviato
|
|
uv run python scripts/live/microtest.py --live # invia il round-trip REALE
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
from src.live.execution import FLAT_USD, MAX_AMOUNT, DeribitTrader
|
|
|
|
INSTRUMENT = "BTC_USDC-PERPETUAL"
|
|
AMOUNT = 0.0001 # base-coin (BTC) = 1 contratto minimo (~$6 a $63k)
|
|
|
|
|
|
def main():
|
|
live = "--live" in sys.argv[1:]
|
|
t = DeribitTrader()
|
|
|
|
print("=" * 82)
|
|
print(" MICRO-TEST esecuzione TP01 — round-trip 0.0001 BTC su BTC_USDC-PERPETUAL (leva ~0x)")
|
|
print("=" * 82)
|
|
try:
|
|
equity = float(t.account_summary("USDC").get("equity") or 0)
|
|
mark = t.mark_price(INSTRUMENT)
|
|
pos0 = t.position_usd(INSTRUMENT)
|
|
except Exception as e:
|
|
print(f" PRE-FLIGHT FALLITO (read): {type(e).__name__}: {e}\n -> non procedo.")
|
|
return
|
|
|
|
notional = AMOUNT * mark
|
|
print(f" conto USDC equity : ${equity:,.2f}")
|
|
print(f" mark {INSTRUMENT} : ${mark:,.1f}")
|
|
print(f" posizione attuale : ${pos0:,.2f} notional (dev'essere 0)")
|
|
print(f" apertura : BUY {AMOUNT:.4f} BTC market (~${notional:.2f}, leva {notional/equity:.4f}x)")
|
|
print(f" chiusura : SELL {AMOUNT:.4f} BTC market reduce_only")
|
|
print(f" guardrail: solo {INSTRUMENT}, cap apertura {MAX_AMOUNT[INSTRUMENT]} BTC")
|
|
|
|
if abs(pos0) >= FLAT_USD:
|
|
print(f"\n ABORT: posizione preesistente (${pos0:,.2f}). Non la tocco. Chiudila a mano e ripeti.")
|
|
return
|
|
if not live:
|
|
print("\n DRY-RUN: nessun ordine inviato. Rilancia con --live per il round-trip reale.")
|
|
return
|
|
|
|
# ---- LIVE: apertura ----
|
|
print("\n >>> LIVE: APERTURA ...")
|
|
fo = t.open(INSTRUMENT, "buy", AMOUNT, label="tp01-microtest-open")
|
|
if not fo.verified:
|
|
print(f" apertura NON verificata: {fo.notes}")
|
|
# safety: assicura comunque il flat
|
|
fc = t.close(INSTRUMENT, label="tp01-microtest-safeclose")
|
|
print(f" safe-close: {'eseguita' if fc else 'gia flat'}; posizione ${t.position_usd(INSTRUMENT):,.2f}")
|
|
return
|
|
print(f" FILL: {fo.filled:.4f} BTC @ ${fo.price:,.1f} fee {fo.fee_usdc:.6f} USDC (state={fo.state})")
|
|
|
|
# ---- LIVE: chiusura (reduce_only) ----
|
|
print(" >>> LIVE: CHIUSURA (reduce_only) ...")
|
|
fc = t.close(INSTRUMENT, label="tp01-microtest-close")
|
|
pos_end = t.position_usd(INSTRUMENT)
|
|
if fc:
|
|
print(f" FILL: {fc.filled:.4f} BTC @ ${fc.price:,.1f} fee {fc.fee_usdc:.6f} USDC (state={fc.state})")
|
|
print(f" posizione finale: ${pos_end:,.2f} notional")
|
|
|
|
# ---- report ----
|
|
print("\n " + "-" * 62)
|
|
if abs(pos_end) < FLAT_USD:
|
|
print(" ✓ ROUND-TRIP COMPLETO — posizione tornata a FLAT.")
|
|
else:
|
|
print(f" ⚠️ posizione NON flat (${pos_end:,.2f}) — INTERVENTO MANUALE: chiudi a mano.")
|
|
if fo.verified and fc:
|
|
tot_fee = fo.fee_usdc + fc.fee_usdc
|
|
pnl = AMOUNT * ((fc.price or 0) - (fo.price or 0))
|
|
print(f" entry ${fo.price:,.1f} -> exit ${fc.price:,.1f} | fee {tot_fee:.6f} USDC | "
|
|
f"pnl lordo {pnl:+.4f} | netto {pnl - tot_fee:+.4f} USDC")
|
|
print(" Validato: invio ordine reale, fill, fee reali, reconciliation, ritorno a flat.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|