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:
Celes Renata
2026-04-15 16:12:22 +00:00
parent da86132f0c
commit 4ffde8cc06
58 changed files with 14168 additions and 1 deletions
+81
View File
@@ -0,0 +1,81 @@
"""Gradual entry logic for the autonomous trading engine.
Pure computation module that determines whether an order should be split
into multiple tranches and performs the splitting. The
``GradualEntryManager`` class (which tracks pending tranches at runtime
and re-evaluates conditions) is intentionally left as a thin wrapper
here — the core logic is in the pure functions below.
"""
from __future__ import annotations
from dataclasses import dataclass
# ---------------------------------------------------------------------------
# Tranche dataclass
# ---------------------------------------------------------------------------
@dataclass
class Tranche:
"""A single tranche within a gradual-entry order sequence."""
tranche_index: int
quantity: int
parent_decision_id: str
status: str = "pending"
# ---------------------------------------------------------------------------
# Pure computation helpers
# ---------------------------------------------------------------------------
def should_use_gradual_entry(
position_size_dollars: float,
active_pool: float,
threshold_dollars: float = 30.0,
) -> bool:
"""Return True when the position size exceeds the gradual-entry threshold.
The effective threshold is ``min(threshold_dollars, 5% of active_pool)``.
"""
effective_threshold = min(threshold_dollars, 0.05 * active_pool)
return position_size_dollars > effective_threshold
def split_into_tranches(total_quantity: int, num_tranches: int = 3) -> list[int]:
"""Split *total_quantity* into *num_tranches* approximately equal parts.
The remainder is distributed one unit at a time to the first tranches
so that:
* ``sum(result) == total_quantity``
* All values differ by at most 1
"""
if num_tranches <= 0:
return []
if total_quantity <= 0:
return [0] * num_tranches
base, remainder = divmod(total_quantity, num_tranches)
return [base + (1 if i < remainder else 0) for i in range(num_tranches)]
def create_tranches(
total_quantity: int,
parent_decision_id: str,
num_tranches: int = 3,
) -> list[Tranche]:
"""Create :class:`Tranche` objects linked to *parent_decision_id*.
Uses :func:`split_into_tranches` for the quantity distribution.
"""
quantities = split_into_tranches(total_quantity, num_tranches)
return [
Tranche(
tranche_index=i,
quantity=q,
parent_decision_id=parent_decision_id,
)
for i, q in enumerate(quantities)
]