c85c0068a2
- Replace all datetime.utcnow() with datetime.now(tz=timezone.utc) across 8 files - Fix 12 failing tests to match current implementation behavior - Fix pytest_plugins in non-top-level conftest (moved to root conftest.py) - Auto-fix 189 lint issues (import sorting, unused imports) - Add CI/CD pipeline infrastructure (ARC, ArgoCD, Kargo manifests) - Add values-beta.yaml and values-paper.yaml for staged deployments - Update GitHub Actions workflow to use self-hosted-gremlin runners - Add integration-test job to CI pipeline Result: 1596 passed, 0 failed, 0 warnings
254 lines
7.1 KiB
Python
254 lines
7.1 KiB
Python
"""Core data models for the autonomous trading engine.
|
|
|
|
Defines dataclasses for risk tier configuration, portfolio state,
|
|
trading decisions, position sizing results, stop levels, and
|
|
performance metrics used across all trading engine components.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Risk Tier Configuration
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class RiskTierConfig:
|
|
"""Parameters for a named risk tier (conservative/moderate/aggressive)."""
|
|
|
|
name: str
|
|
min_confidence: float
|
|
max_position_pct: float
|
|
stop_loss_atr_multiplier: float
|
|
reward_risk_ratio: float
|
|
max_sector_pct: float
|
|
max_portfolio_heat: float
|
|
|
|
|
|
RISK_TIER_DEFAULTS: dict[str, RiskTierConfig] = {
|
|
"conservative": RiskTierConfig(
|
|
name="conservative",
|
|
min_confidence=0.75,
|
|
max_position_pct=0.05,
|
|
stop_loss_atr_multiplier=1.5,
|
|
reward_risk_ratio=2.0,
|
|
max_sector_pct=0.20,
|
|
max_portfolio_heat=0.10,
|
|
),
|
|
"moderate": RiskTierConfig(
|
|
name="moderate",
|
|
min_confidence=0.55,
|
|
max_position_pct=0.10,
|
|
stop_loss_atr_multiplier=2.0,
|
|
reward_risk_ratio=1.5,
|
|
max_sector_pct=0.30,
|
|
max_portfolio_heat=0.20,
|
|
),
|
|
"aggressive": RiskTierConfig(
|
|
name="aggressive",
|
|
min_confidence=0.40,
|
|
max_position_pct=0.15,
|
|
stop_loss_atr_multiplier=2.5,
|
|
reward_risk_ratio=1.2,
|
|
max_sector_pct=0.40,
|
|
max_portfolio_heat=0.30,
|
|
),
|
|
}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Portfolio State
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class PortfolioState:
|
|
"""Snapshot of the current portfolio used for decision-making."""
|
|
|
|
positions: list = field(default_factory=list)
|
|
total_value: float = 0.0
|
|
cash: float = 0.0
|
|
active_pool: float = 0.0
|
|
reserve_pool: float = 0.0
|
|
sector_exposure: dict[str, float] = field(default_factory=dict)
|
|
portfolio_heat: float = 0.0
|
|
open_position_count: int = 0
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Trading Decision
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class TradingDecision:
|
|
"""Record of a trading decision (act or skip), persisted for audit trail."""
|
|
|
|
id: str
|
|
recommendation_id: str | None
|
|
decision: str
|
|
skip_reason: str | None
|
|
ticker: str
|
|
computed_position_size: float | None
|
|
computed_share_quantity: int | None
|
|
risk_tier_at_decision: str
|
|
portfolio_heat_at_decision: float | None
|
|
active_pool_at_decision: float | None
|
|
reserve_pool_at_decision: float | None
|
|
circuit_breaker_status: str
|
|
correlation_check_result: dict = field(default_factory=dict)
|
|
sector_exposure_check_result: dict = field(default_factory=dict)
|
|
earnings_proximity_flag: bool = False
|
|
is_micro_trade: bool = False
|
|
decision_trace: dict = field(default_factory=dict)
|
|
created_at: datetime = field(default_factory=lambda: datetime.now(tz=timezone.utc))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Position Sizing
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class PositionSizeResult:
|
|
"""Output of the position sizer computation."""
|
|
|
|
dollar_amount: float
|
|
share_quantity: int
|
|
allocation_pct: float
|
|
adjustments: list[str] = field(default_factory=list)
|
|
rejected: bool = False
|
|
rejection_reason: str = ""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Stop-Loss / Take-Profit Levels
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class StopLevels:
|
|
"""Current stop-loss and take-profit levels for an open position."""
|
|
|
|
stop_loss_price: float
|
|
take_profit_price: float
|
|
trailing_stop_active: bool
|
|
atr_value: float
|
|
atr_multiplier: float
|
|
reward_risk_ratio: float
|
|
last_updated: datetime = field(default_factory=lambda: datetime.now(tz=timezone.utc))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Open / Closed Positions
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class OpenPosition:
|
|
"""Representation of a currently held position."""
|
|
|
|
ticker: str
|
|
quantity: int
|
|
entry_price: float
|
|
current_price: float
|
|
unrealized_pnl: float
|
|
market_value: float
|
|
sector: str
|
|
stop_loss_price: float
|
|
take_profit_price: float
|
|
signal_confidence: float
|
|
is_micro_trade: bool = False
|
|
|
|
|
|
@dataclass
|
|
class ClosedTrade:
|
|
"""Record of a completed (closed) trade."""
|
|
|
|
ticker: str
|
|
entry_price: float
|
|
exit_price: float
|
|
quantity: int
|
|
pnl: float
|
|
pnl_pct: float
|
|
hold_duration: timedelta
|
|
recommendation_id: str | None = None
|
|
is_micro_trade: bool = False
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Performance Metrics
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class PerformanceMetrics:
|
|
"""Portfolio-wide performance metrics computed periodically."""
|
|
|
|
total_portfolio_value: float
|
|
active_pool: float
|
|
reserve_pool: float
|
|
unrealized_pnl: float
|
|
realized_pnl: float
|
|
daily_pnl: float
|
|
win_count: int
|
|
loss_count: int
|
|
win_rate: float
|
|
avg_win: float
|
|
avg_loss: float
|
|
profit_factor: float
|
|
sharpe_ratio: float
|
|
max_drawdown: float
|
|
current_drawdown_pct: float
|
|
portfolio_heat: float
|
|
computed_at: datetime = field(default_factory=lambda: datetime.now(tz=timezone.utc))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Circuit Breaker
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class CircuitBreakerState:
|
|
"""Current state of the circuit breaker safety mechanism."""
|
|
|
|
active: bool = False
|
|
trigger_type: str | None = None
|
|
triggered_at: datetime | None = None
|
|
cooldown_expires: datetime | None = None
|
|
ticker_cooldowns: dict[str, datetime] = field(default_factory=dict)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Reserve Pool
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class ReservePoolState:
|
|
"""Current state of the reserve pool."""
|
|
|
|
balance: float = 0.0
|
|
total_deposits: float = 0.0
|
|
total_withdrawals: float = 0.0
|
|
last_updated: datetime = field(default_factory=lambda: datetime.now(tz=timezone.utc))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Stop Trigger
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@dataclass
|
|
class StopTrigger:
|
|
"""A triggered stop-loss or take-profit event for a position."""
|
|
|
|
ticker: str
|
|
trigger_type: str # "stop_loss" or "take_profit"
|
|
current_price: float
|
|
trigger_price: float
|