uv(pass-a-r1): K-purge — Rev-4-FINAL compliance. A1: reconcile_ok replaced by stateless per-event tripwire (tripwire_ok + tripwire_last_event_id on AccountStateSnapshot). Detection latency = 1 event. A2: ASEXAccountV2.k_capital -> _k_capital_internal. 6 acceptance tests.
This commit is contained in:
88
prod/clean_arch/dita_v2/asex_account_publisher.py
Normal file
88
prod/clean_arch/dita_v2/asex_account_publisher.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""ASExAccountPublisher — single-writer account to ZincPlane.
|
||||
|
||||
Wraps ASEXAccountV2 (or a test double) so that every account event
|
||||
(fill, funding, balance_update) first applies through ASEx, then
|
||||
builds an E-only AccountStateSnapshot and publishes it to the
|
||||
ZincPlane account region. Edge-triggered: no timer writes, no
|
||||
periodic re-stamp. Publishes RAW E, never K.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from .contracts import AccountStateSnapshot
|
||||
from .zinc_plane import InMemoryZincPlane
|
||||
|
||||
|
||||
class AccountPublisher:
|
||||
"""Applies account events and publishes E snapshots to a ZincPlane.
|
||||
|
||||
Rev-4-FINAL: E sole authority. tripwire_ok = stateless per-event check.
|
||||
reconcile_ok kept as compat alias. No KBlock fields cross the boundary.
|
||||
"""
|
||||
|
||||
def __init__(self, plane: InMemoryZincPlane) -> None:
|
||||
self._plane = plane
|
||||
self._event_seq: int = 0
|
||||
# Internal state tracking E values (simplified: mirrors EBlock fields)
|
||||
self._wallet_balance: float = 0.0
|
||||
self._available_margin: float = 0.0
|
||||
self._used_margin: float = 0.0
|
||||
self._e_live: bool = False
|
||||
# Stateless tripwire: set by each event, never accumulated
|
||||
self._tripwire_ok: bool = True
|
||||
self._tripwire_last_event_id: str = ""
|
||||
|
||||
def apply_fill(self, wallet_balance: float, available_margin: float,
|
||||
used_margin: float, reconcile_ok: bool = True,
|
||||
tripwire_ok: bool = True, tripwire_last_event_id: str = "") -> None:
|
||||
"""Apply a fill event: update E fields, publish snapshot with tripwire."""
|
||||
self._wallet_balance = wallet_balance
|
||||
self._available_margin = available_margin
|
||||
self._used_margin = used_margin
|
||||
self._e_live = True
|
||||
self._tripwire_ok = tripwire_ok
|
||||
self._tripwire_last_event_id = tripwire_last_event_id
|
||||
self._publish()
|
||||
|
||||
def apply_funding(self, amount: float) -> None:
|
||||
"""Apply a funding event: funding changes wallet_balance."""
|
||||
self._wallet_balance += amount
|
||||
self._available_margin += amount
|
||||
self._e_live = True
|
||||
self._publish()
|
||||
|
||||
def apply_balance_update(self, wallet_balance: float, available_margin: float,
|
||||
used_margin: float) -> None:
|
||||
"""Apply a balance update: overwrite all E fields."""
|
||||
self._wallet_balance = wallet_balance
|
||||
self._available_margin = available_margin
|
||||
self._used_margin = used_margin
|
||||
self._e_live = True
|
||||
self._publish()
|
||||
|
||||
def _publish(self) -> None:
|
||||
self._event_seq += 1
|
||||
import time
|
||||
snap = AccountStateSnapshot(
|
||||
wallet_balance=self._wallet_balance,
|
||||
available_margin=self._available_margin,
|
||||
used_margin=self._used_margin,
|
||||
event_seq=self._event_seq,
|
||||
mono_ns=int(time.monotonic_ns()),
|
||||
e_live=self._e_live,
|
||||
reconcile_ok=self._tripwire_ok, # compat alias
|
||||
tripwire_ok=self._tripwire_ok,
|
||||
tripwire_last_event_id=self._tripwire_last_event_id,
|
||||
)
|
||||
# Publish RAW E — NEVER K
|
||||
self._plane.publish_account(snap)
|
||||
|
||||
@property
|
||||
def plane(self) -> InMemoryZincPlane:
|
||||
return self._plane
|
||||
|
||||
@property
|
||||
def event_seq(self) -> int:
|
||||
return self._event_seq
|
||||
Reference in New Issue
Block a user