PINK Phases 1-4: E-anchored capital, atomic snapshot, sizer feedback, kernel hardening
Phase 1: account.py anchor_to_exchange, capital_source provenance, settle includes fees in capital delta. Phase 2: atomic snapshot swap, CH provenance DDL (08_provenance.sql), naive-UTC timestamps, ch_writer wait_for_async_insert=1 for all tables, head-of-line stuck-row logging at WARNING per 100 attempts. Phase 3: sizer feedback uses slot realized_pnl (not capital delta), FILL_SETTLED repairs slot-level PnL for price-less exit legs. Phase 4: resolve_slot returns Option<usize>, UNRESOLVED_SLOT diagnostic. bars_held clamped to max(0, ...) at row-build time.
This commit is contained in:
@@ -259,13 +259,13 @@ def _reconcile_position_slot(
|
||||
# No open positions — ensure slot is idle
|
||||
kernel.reconcile_from_slots([])
|
||||
|
||||
# Seed capital once from exchange balance.
|
||||
# Seed capital once from exchange balance — E-anchored.
|
||||
if exchange_balance_capital > 0:
|
||||
kernel.account.snapshot.capital = exchange_balance_capital
|
||||
kernel.account.snapshot.peak_capital = max(
|
||||
kernel.account.snapshot.peak_capital, exchange_balance_capital
|
||||
kernel.account.anchor_to_exchange(
|
||||
wallet_balance=exchange_balance_capital,
|
||||
available_margin=exchange_balance_capital,
|
||||
event_seq=0,
|
||||
)
|
||||
kernel.account.snapshot.equity = exchange_balance_capital
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -1453,9 +1453,11 @@ class PinkDirectRuntime:
|
||||
def _sizer_trade_feedback(self, acc: dict, slot_dict: dict) -> None:
|
||||
"""Close-out detection → feed realized PnL into the alpha layers.
|
||||
|
||||
Capital-delta PnL (net of fees) — the kernel's capital is the
|
||||
authoritative ledger, and bucket/streak multipliers only need the
|
||||
sign and rough magnitude.
|
||||
PnL is sourced from the closing slot's realized_pnl (kernel estimate,
|
||||
overridden by exchange FILL_SETTLED when available) — NOT the capital
|
||||
delta, which absorbs funding, fees of other activity, and foreign fills
|
||||
from the shared VST account (PRODGREEN collision class).
|
||||
Bucket/streak multipliers only need sign and rough magnitude.
|
||||
"""
|
||||
if self.alpha_sizer is None or not self._sizer_open_tid:
|
||||
return
|
||||
@@ -1467,11 +1469,17 @@ class PinkDirectRuntime:
|
||||
)
|
||||
if still_open:
|
||||
return
|
||||
pnl = float(acc.get("capital") or 0.0) - self._sizer_entry_capital
|
||||
# Phase 3: slot.realized_pnl is the trade's own PnL (no capital-delta
|
||||
# contamination from funding, foreign fills, or other-activity fees).
|
||||
pnl = float(slot_dict.get("realized_pnl") or 0.0)
|
||||
# Subtract accumulated fees when available (fees_paid on slot metadata)
|
||||
fees = float(slot_dict.get("fees_paid", 0.0) or slot_dict.get("metadata", {}).get("fees_paid", 0.0) or 0.0)
|
||||
pnl = pnl - fees
|
||||
self._sizer_open_tid = ""
|
||||
try:
|
||||
self.alpha_sizer.record_close(pnl)
|
||||
self.logger.info("alpha sizer feedback: trade closed pnl=%.4f", pnl)
|
||||
self.logger.info("alpha sizer feedback: trade closed pnl=%.4f (rp=%.4f fees=%.4f)", pnl,
|
||||
float(slot_dict.get("realized_pnl") or 0.0), fees)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user