# app/src/trading/auto/service.py from __future__ import annotations import asyncio from src.core.types import JsonDict from src.trading.auto.auto_lifecycle import AutoLifecycleMixin from src.trading.auto.state import AutoTradeState class AutoTradeService(AutoLifecycleMixin): # GLOBAL SERVICE STATE # единый runtime state автоторговли # хранит: # - сигналы # - market context # - execution context # - PnL открытой позиции и реализованный PnL # - lifecycle # - protection state _state = AutoTradeState() # background asyncio loop task # нужен для continuous auto-trading worker # None -> loop не запущен _loop_task: asyncio.Task | None = None # интервал между auto-trading циклами # run_cycle() вызывается каждые N секунд _loop_interval_seconds: int = 5 # SIGNAL CONFIRMATION ENGINE # минимальное количество одинаковых BUY/SELL подряд # чтобы сигнал считался подтвержденным _confirm_repeats: int = 2 # минимальное время удержания сигнала # перед execution _confirm_min_duration_seconds: int = 10 # EXECUTION CONFIDENCE RULES # минимальный confidence для READY state # ниже -> сигнал не считается готовым _ready_confidence = 0.45 # минимальный execution confidence # для реального допуска execution engine _execution_confidence_required_score = 0.65 # RUNTIME TTL # время жизни signal runtime # после ttl сигнал считается устаревшим _signal_ttl_seconds: int = 90 # время жизни market analysis runtime # после ttl market context считается stale _market_analysis_ttl_seconds: int = 180 # последний logged runtime expiration key # нужен чтобы не спамить одинаковыми логами _last_logged_runtime_expired_key: str | None = None # SIGNAL MEMORY # уникальный ключ последнего сигнала # используется для deduplication _last_signal_key: str | None = None # последнее signal значение: # BUY / SELL / HOLD _last_signal_value: str | None = None # последнее объяснение сигнала _last_signal_reason: str = "" # confidence последнего сигнала _last_signal_confidence: float = 0.0 # полный payload последнего signal анализа # содержит market metrics / indicators / runtime info _last_signal_payload: JsonDict | None = None # monotonic timestamp начала сигнала # нужен для confirmation timing _last_signal_started_at: float | None = None # количество одинаковых сигналов подряд # используется confirmation engine _same_signal_count: int = 0 # EXECUTION SNAPSHOT VALIDATION # максимальный допустимый возраст execution snapshot # старше -> snapshot stale _max_snapshot_age_seconds: float = 5.0 # warning threshold snapshot age # выше -> degraded execution quality _warning_snapshot_age_seconds: float = 2.0 # SPREAD RISK THRESHOLDS # asset-specific spread thresholds # # warning_enter: # warning при входе # # warning_exit: # warning при выходе # # block_enter: # полный блок входа # # block_exit: # полный блок выхода _spread_thresholds_by_asset: dict[str, dict[str, float]] = { "BTC": { "warning_enter": 0.08, "warning_exit": 0.06, "block_enter": 0.15, "block_exit": 0.12, }, "ETH": { "warning_enter": 0.10, "warning_exit": 0.08, "block_enter": 0.18, "block_exit": 0.15, }, "LTC": { "warning_enter": 0.18, "warning_exit": 0.14, "block_enter": 0.35, "block_exit": 0.28, }, "XRP": { "warning_enter": 0.20, "warning_exit": 0.16, "block_enter": 0.40, "block_exit": 0.32, }, } # default spread thresholds # используются если asset не найден _default_spread_thresholds: dict[str, float] = { "warning_enter": 0.12, "warning_exit": 0.09, "block_enter": 0.25, "block_exit": 0.20, } # последний logged execution quality key # нужен чтобы не спамить одинаковыми warning/block logs _last_logged_execution_quality_key: str | None = None