Files
dzentra_bot/app/src/trading/auto/service.py

153 lines
4.9 KiB
Python

# 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