feat(live): REAL-TRUTH ledger — capital aggiornato dal PnL dei fill reali, sim ridotto a diagnostica
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ class PairsWorker:
|
||||
data_dir: Path = Path("data/paper_trades"),
|
||||
executor=None, # PairsExecutionClient: esecuzione REALE shadow a 2 gambe
|
||||
exec_instruments: dict | None = None, # {asset: instrument USDC}
|
||||
real_truth: bool = False,
|
||||
):
|
||||
self.asset_a = asset_a
|
||||
self.asset_b = asset_b
|
||||
@@ -88,6 +89,9 @@ class PairsWorker:
|
||||
self.inst_a = self.exec_instruments.get(asset_a)
|
||||
self.inst_b = self.exec_instruments.get(asset_b)
|
||||
self.execution_enabled = bool(executor and self.inst_a and self.inst_b)
|
||||
# REAL-TRUTH (2026-06-10): come StrategyWorker — `capital` aggiornato dal
|
||||
# PnL dei fill reali (2 gambe, fee reali); sim solo diagnostica nel log.
|
||||
self.real_truth = bool(real_truth and self.execution_enabled)
|
||||
self.real_capital = capital
|
||||
self.real_in_position = False
|
||||
self.real_dir = 0
|
||||
@@ -231,11 +235,15 @@ class PairsWorker:
|
||||
self._notify("REAL_OPEN_FAIL", {**data, "note": pf.notes})
|
||||
self._save_state() # persisti subito il ledger reale (resume-safe sui crash)
|
||||
|
||||
def _real_close_pair(self, sim_a: float, sim_b: float, reason: str, sim_pnl: float):
|
||||
def _real_close_pair(self, sim_a: float, sim_b: float, reason: str,
|
||||
sim_pnl: float) -> tuple[float | None, bool]:
|
||||
"""Chiusura REALE shadow: richiude entrambe le gambe reduce-only, riconcilia
|
||||
PnL reale (per gamba) e fee, aggiorna il ledger reale parallelo."""
|
||||
PnL reale (per gamba) e fee, aggiorna il ledger reale parallelo.
|
||||
|
||||
Ritorna (real_pnl, applied): applied=True se almeno una gamba ha chiuso con
|
||||
fill verificato (PnL reale utilizzabile come verita' in real-truth)."""
|
||||
if not self.real_in_position:
|
||||
return
|
||||
return None, False
|
||||
pf = self.executor.close_pair(self.inst_a, self.inst_b, self.real_side_a,
|
||||
self.real_side_b, self.real_amount_a, self.real_amount_b,
|
||||
label=self.worker_id)
|
||||
@@ -264,6 +272,7 @@ class PairsWorker:
|
||||
self.real_notional_a = self.real_notional_b = 0.0
|
||||
self.real_entry_fee = 0.0
|
||||
self._save_state()
|
||||
return real_pnl, bool(pf.verified or pf.leg_a.verified or pf.leg_b.verified)
|
||||
|
||||
def _close(self, ca: float, cb: float, z: float, reason: str):
|
||||
if not self.in_position:
|
||||
@@ -273,9 +282,17 @@ class PairsWorker:
|
||||
gross = (ret_a - ret_b) * self.direction * self.leverage
|
||||
fee = 2 * self.fee_rt * self.leverage # 2 gambe
|
||||
net = gross - fee
|
||||
pnl = self.capital * self.position_size * net
|
||||
sim_pnl = self.capital * self.position_size * net
|
||||
|
||||
# REAL-TRUTH: chiusura reale PRIMA dell'update ledger (come StrategyWorker)
|
||||
real_pnl, real_applied = (None, False)
|
||||
if self.execution_enabled:
|
||||
real_pnl, real_applied = self._real_close_pair(ca, cb, reason, sim_pnl)
|
||||
use_real = self.real_truth and real_applied
|
||||
pnl = real_pnl if use_real else sim_pnl
|
||||
|
||||
self.capital = max(self.capital + pnl, 0.0)
|
||||
is_win = net > 0
|
||||
is_win = pnl > 0
|
||||
self.total_trades += 1
|
||||
self.total_wins += is_win
|
||||
acc = self.total_wins / self.total_trades * 100 if self.total_trades else 0
|
||||
@@ -284,9 +301,12 @@ class PairsWorker:
|
||||
"net_return": round(net * 100, 3), "pnl": round(pnl, 2),
|
||||
"capital": round(self.capital, 2), "bars_held": self.bars_held,
|
||||
"win": bool(is_win), "total_trades": self.total_trades, "accuracy": round(acc, 1)}
|
||||
if self.real_truth:
|
||||
data["pnl_source"] = "real" if use_real else "sim_fallback"
|
||||
data["sim_pnl"] = round(sim_pnl, 2)
|
||||
if real_pnl is not None:
|
||||
data["real_pnl"] = round(real_pnl, 4)
|
||||
self._log("CLOSE", data); self._notify("CLOSED", data)
|
||||
if self.execution_enabled:
|
||||
self._real_close_pair(ca, cb, reason, pnl)
|
||||
self.in_position = False
|
||||
self.direction = 0
|
||||
self.entry_a = self.entry_b = self.entry_z = 0.0
|
||||
|
||||
Reference in New Issue
Block a user