"""Reserve Pool Controller — pure computation module. Manages the untouchable cash reserve that grows from realized profits. All methods are pure computations; persistence is handled by the caller. """ from __future__ import annotations from services.trading.models import ReservePoolState # noqa: F401 — re-export for convenience class ReservePoolController: """Compute reserve-pool operations without touching the database. Parameters ---------- siphon_pct: Fraction of realized profit transferred to the reserve on each profitable position close (default 20 %). high_water_pct: When the reserve exceeds this fraction of total portfolio value the risk-tier controller should consider upgrading (default 30 %). """ def __init__( self, siphon_pct: float = 0.20, high_water_pct: float = 0.30, ) -> None: self.siphon_pct = siphon_pct self.high_water_pct = high_water_pct # ------------------------------------------------------------------ # Profit siphoning # ------------------------------------------------------------------ def siphon_profit( self, realized_profit: float, current_balance: float, ) -> tuple[float, float]: """Compute the amount to transfer into the reserve pool. Only positive profits are siphoned. Returns ------- (transfer_amount, new_balance) *transfer_amount* is ``realized_profit * siphon_pct`` when the profit is positive, otherwise ``0.0``. *new_balance* is ``current_balance + transfer_amount``. """ if realized_profit <= 0: return 0.0, current_balance transfer = realized_profit * self.siphon_pct return transfer, current_balance + transfer # ------------------------------------------------------------------ # Emergency liquidation # ------------------------------------------------------------------ def emergency_liquidate(self, current_balance: float) -> float: """Return the full reserve balance to be released into the active pool. The caller is responsible for zeroing the persisted balance and recording the ledger entry. Returns ------- float The amount to release (equal to *current_balance*). """ return current_balance # ------------------------------------------------------------------ # Active pool computation # ------------------------------------------------------------------ def compute_active_pool( self, total_portfolio_value: float, reserve_balance: float, ) -> float: """Active Pool = total portfolio value − reserve balance.""" return total_portfolio_value - reserve_balance # ------------------------------------------------------------------ # High-water mark detection # ------------------------------------------------------------------ def is_high_water( self, reserve_balance: float, total_portfolio_value: float, ) -> bool: """Return ``True`` when the reserve exceeds *high_water_pct* of total portfolio.""" if total_portfolio_value <= 0: return False return reserve_balance > self.high_water_pct * total_portfolio_value # ------------------------------------------------------------------ # Emergency liquidation trigger check # ------------------------------------------------------------------ def should_emergency_liquidate( self, current_drawdown_pct: float, emergency_threshold_pct: float, ) -> bool: """Return ``True`` when drawdown exceeds the emergency threshold.""" return current_drawdown_pct > emergency_threshold_pct