4ffde8cc06
- 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
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
"""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)
|
|
]
|