From 8c4ddebe85f14fcd01e9f27697554036b6050ef1 Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Wed, 27 May 2026 09:57:26 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20paper=20trader=20su=20USDC=20(ETH=5FUSD?= =?UTF-8?q?C-PERPETUAL),=20pronto=20per=20operativit=C3=A0=20reale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/paper_status.py | 12 ++++++------ src/live/cerbero_client.py | 4 ++-- src/live/paper_trader.py | 21 ++++++++++++--------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/scripts/paper_status.py b/scripts/paper_status.py index 5fade21..829694e 100644 --- a/scripts/paper_status.py +++ b/scripts/paper_status.py @@ -32,19 +32,19 @@ else: print("\n--- ACCOUNT DERIBIT TESTNET ---") c = CerberoClient() try: - acc = c.get_account_summary() - print(f" Equity: {acc['equity']:.2f}") - print(f" Balance: {acc['balance']:.2f}") - print(f" PnL: {acc['total_pnl']:.2f}") + acc = c.get_account_summary("USDC") + print(f" Equity: ${acc['equity']:,.2f}") + print(f" Balance: ${acc['balance']:,.2f}") + print(f" PnL: ${acc['total_pnl']:,.2f}") except Exception as e: print(f" Errore: {e}") # Posizioni try: - pos = c.get_positions() + pos = c.get_positions("USDC") print(f"\n Posizioni aperte: {len(pos)}") for p in pos: - print(f" {p}") + print(f" {p.get('instrument','?')}: {p.get('size',0)} {p.get('direction','?')} @ ${p.get('avg_price',0)}") except Exception as e: print(f" Errore: {e}") diff --git a/src/live/cerbero_client.py b/src/live/cerbero_client.py index 4cdd2e8..c7a4a68 100644 --- a/src/live/cerbero_client.py +++ b/src/live/cerbero_client.py @@ -51,8 +51,8 @@ class CerberoClient: # --- Account --- - def get_account_summary(self) -> dict: - return self._post("/mcp-deribit/tools/get_account_summary") + def get_account_summary(self, currency: str = "USDC") -> dict: + return self._post("/mcp-deribit/tools/get_account_summary", {"currency": currency}) def get_positions(self, currency: str = "ETH") -> list[dict]: return self._post("/mcp-deribit/tools/get_positions", {"currency": currency}) diff --git a/src/live/paper_trader.py b/src/live/paper_trader.py index c5b1190..82867de 100644 --- a/src/live/paper_trader.py +++ b/src/live/paper_trader.py @@ -12,7 +12,9 @@ from src.live.cerbero_client import CerberoClient from src.live.signal_engine import SignalEngine LOG_DIR = Path(__file__).resolve().parents[2] / "data" / "paper_trades" -INSTRUMENT = "ETH-PERPETUAL" +INSTRUMENT = "ETH_USDC-PERPETUAL" +TRAIN_INSTRUMENT = "ETH-PERPETUAL" # storico più lungo per training +CURRENCY = "USDC" RESOLUTION = "15" LEVERAGE = 3 POSITION_PCT = 0.15 @@ -60,11 +62,11 @@ class PaperTrader: with open(self.status_path, "w") as f: json.dump(status, f, indent=2) - def fetch_candles(self, days: int = LOOKBACK_DAYS) -> pd.DataFrame: + def fetch_candles(self, days: int = LOOKBACK_DAYS, instrument: str | None = None) -> pd.DataFrame: end = datetime.now(timezone.utc) start = end - timedelta(days=days) candles = self.client.get_historical( - INSTRUMENT, + instrument or TRAIN_INSTRUMENT, start.strftime("%Y-%m-%d"), end.strftime("%Y-%m-%d"), RESOLUTION, @@ -77,8 +79,8 @@ class PaperTrader: return df def train_model(self): - self.log("TRAINING", {"lookback_days": TRAIN_LOOKBACK_DAYS}) - df = self.fetch_candles(TRAIN_LOOKBACK_DAYS) + self.log("TRAINING", {"lookback_days": TRAIN_LOOKBACK_DAYS, "instrument": TRAIN_INSTRUMENT}) + df = self.fetch_candles(TRAIN_LOOKBACK_DAYS, TRAIN_INSTRUMENT) if df.empty: self.log("TRAINING_FAILED", {"reason": "no data"}) return False @@ -93,8 +95,8 @@ class PaperTrader: equity = account["equity"] notional = equity * POSITION_PCT - amount = round(notional / price, 1) - amount = max(amount, 1.0) + amount = round(notional / price, 3) + amount = max(amount, 0.001) side = "buy" if direction == "buy" else "sell" @@ -180,7 +182,7 @@ class PaperTrader: def run_once(self) -> str: """Esegui un singolo ciclo. Ritorna lo stato.""" - df = self.fetch_candles(LOOKBACK_DAYS) + df = self.fetch_candles(LOOKBACK_DAYS, TRAIN_INSTRUMENT) if df.empty: return "no_data" @@ -204,7 +206,8 @@ class PaperTrader: def run(self, retrain_hours: int = 24): """Loop principale.""" print("=" * 60) - print(f" PAPER TRADER — {INSTRUMENT} {RESOLUTION}m") + print(f" PAPER TRADER — {INSTRUMENT} (margine {CURRENCY})") + print(f" Segnali da: {TRAIN_INSTRUMENT} {RESOLUTION}m") print(f" Leva: {LEVERAGE}x, Position: {POSITION_PCT*100:.0f}%, Hold: {HOLD_BARS} barre") print(f" Poll: ogni {POLL_SECONDS}s") print(f" Log: {self.log_path}")