Files
PythagorasGoal/scripts/live/microtest.py
T
Adriano Dal Pastro de83909db9 un flag sconosciuto non e' l'azione di default: guardia su 18 script, indice USDE orario, pulizia
MISURATO oggi durante la revisione: `trades_db.py --help` non stampava l'uso, cadeva in sync()
e riscriveva meta.ultimo_sync. Nessuno dei 18 script di scripts/live/ usava argparse: un flag
sbagliato era il ramo else. Su journal.py avrebbe scritto pagina e riga di DB, su analista.py
avrebbe speso una chiamata al modello e mandato un Telegram.

- src/live/cli.valida: prima istruzione di ogni __main__, prima di connect()/sync/rete.
  --help -> 0 con l'uso; flag ignoto, valore mancante o posizionale -> 2 con l'elenco dei
  previsti (P4). NIENTE argparse: cambierebbe messaggi, codici d'uscita e --help di script
  che il cron gia' chiama.
- 18 script cablati (i 3 che scrivono + 14 + cc01), flag invariati.
- tests/test_cli_flag.py (30): elenco DERIVATO dalla cartella (P1), valida come prima
  istruzione, uso che documenta i flag, e i flag che il CRON usa davvero restano accettati
  (P15/P16); end-to-end su --help e flag ignoto con trades.db non toccato (M15).
  Verificato a mano: monitor_health --quiet, trades_db --sync --quiet, book_execute dry-run.

Debito §5.15, primo passo: balance_watch (orario) registra `usde_usdc` a ogni campione — None
con la ragione se illeggibile, mai 1,0. Il cablaggio nel bound quando la serie ha storia.

Pulizia dalla revisione: tests/helpers.carica_script al posto della 15a copia del loader
importlib (5 file del libro live); il fill di prova via upsert_fills invece di un INSERT che
lasciava verified NULL; asserzioni non ancorate al padding; movimenti_capitale accetta le
righe gia' lette (una SELECT invece di due ai due lati di una scrittura del cron).

Test 910 verdi (+52). Diario 2026-09-02c.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDJsH3iDSaBns3ccpPBwiu
2026-09-02 15:49:40 +00:00

102 lines
4.3 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.")
USO = """uso: microtest.py [--live]
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
Dettaglio nel docstring in testa al file."""
if __name__ == "__main__":
from src.live.cli import valida
valida("microtest.py", USO, flag=("--live",), con_valore=())
main()