feat: autonomous trading engine — full implementation
- Database migration 018 with 13 tables for trading engine state - Trading engine service (services/trading/) with 12 pure computation modules: position sizer, stop-loss manager, reserve pool, circuit breaker, risk tier controller, correlation matrix, tax lots, trading window, gradual entry, notifications, micro-trading, backtester - Core TradingEngine with pre-trade evaluation pipeline and integration wiring - FastAPI HTTP service with 14 endpoints (health, config, decisions, metrics, backtest) - Performance tracker with Sharpe ratio, drawdown, profit factor computation - 194 Python tests (165 property-based + 29 integration) - Frontend: 13 TanStack Query hooks, 7 dashboard panels, tabbed Trading Engine page - Helm chart entry, network policy, nginx proxy, ingress for trading-engine - Shared infrastructure: enums, Redis keys, TradingConfig in AppConfig
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user