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,87 @@
|
||||
"""Risk tier auto-adjustment controller for the autonomous trading engine.
|
||||
|
||||
Pure computation module — no DB access. Persistence of tier changes is
|
||||
handled by the caller. All methods operate on values passed in as
|
||||
arguments and return deterministic results.
|
||||
|
||||
Tier ordering: conservative → moderate → aggressive
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from services.trading.models import PerformanceMetrics
|
||||
|
||||
# Ordered from lowest to highest risk.
|
||||
TIER_ORDER: list[str] = ["conservative", "moderate", "aggressive"]
|
||||
|
||||
|
||||
class RiskTierController:
|
||||
"""Evaluates performance metrics and determines whether the active
|
||||
risk tier should change.
|
||||
|
||||
Downgrade conditions (any one triggers a downgrade by one level):
|
||||
- Trailing 30-day win rate < 40%
|
||||
- Current drawdown > 15%
|
||||
|
||||
Upgrade conditions (ALL must be true):
|
||||
- Trailing 30-day win rate > 55%
|
||||
- Reserve pool > 20% of total portfolio
|
||||
- Current drawdown < 5%
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
# No configuration needed — uses TIER_ORDER for ordering.
|
||||
pass
|
||||
|
||||
def evaluate(
|
||||
self,
|
||||
current_tier: str,
|
||||
metrics: PerformanceMetrics,
|
||||
reserve_pct: float,
|
||||
) -> str | None:
|
||||
"""Evaluate whether the tier should change based on performance.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
current_tier:
|
||||
The currently active tier name (e.g. ``"moderate"``).
|
||||
metrics:
|
||||
Latest portfolio performance metrics.
|
||||
reserve_pct:
|
||||
Reserve pool balance as a fraction of total portfolio value
|
||||
(e.g. 0.25 means 25%).
|
||||
|
||||
Returns
|
||||
-------
|
||||
str | None
|
||||
The new tier name if a change is needed, or ``None`` if the
|
||||
current tier should remain.
|
||||
"""
|
||||
current_index = TIER_ORDER.index(current_tier)
|
||||
|
||||
# --- Downgrade check (any condition triggers) ---
|
||||
should_downgrade = (
|
||||
metrics.win_rate < 0.40 or metrics.current_drawdown_pct > 0.15
|
||||
)
|
||||
|
||||
if should_downgrade:
|
||||
if current_index > 0:
|
||||
return TIER_ORDER[current_index - 1]
|
||||
# Already at the lowest tier — no change.
|
||||
return None
|
||||
|
||||
# --- Upgrade check (all conditions must be true) ---
|
||||
should_upgrade = (
|
||||
metrics.win_rate > 0.55
|
||||
and reserve_pct > 0.20
|
||||
and metrics.current_drawdown_pct < 0.05
|
||||
)
|
||||
|
||||
if should_upgrade:
|
||||
if current_index < len(TIER_ORDER) - 1:
|
||||
return TIER_ORDER[current_index + 1]
|
||||
# Already at the highest tier — no change.
|
||||
return None
|
||||
|
||||
# Neither condition met — stay at current tier.
|
||||
return None
|
||||
Reference in New Issue
Block a user