Skip to main content

sandbox_quant/
event.rs

1use std::collections::HashMap;
2
3use crate::model::candle::Candle;
4use crate::model::order::OrderSide;
5use crate::model::signal::Signal;
6use crate::model::tick::Tick;
7use crate::order_manager::{OrderHistorySnapshot, OrderHistoryStats, OrderUpdate};
8use crate::risk_module::RateBudgetSnapshot;
9
10#[derive(Debug, Clone)]
11pub enum WsConnectionStatus {
12    Connected,
13    Disconnected,
14    Reconnecting { attempt: u32, delay_ms: u64 },
15}
16
17#[derive(Debug, Clone)]
18pub enum AppEvent {
19    MarketTick(Tick),
20    StrategySignal {
21        signal: Signal,
22        symbol: String,
23        source_tag: String,
24        price: Option<f64>,
25        timestamp_ms: u64,
26    },
27    StrategyState {
28        fast_sma: Option<f64>,
29        slow_sma: Option<f64>,
30    },
31    OrderUpdate(OrderUpdate),
32    WsStatus(WsConnectionStatus),
33    HistoricalCandles {
34        candles: Vec<Candle>,
35        interval_ms: u64,
36        interval: String,
37    },
38    BalanceUpdate(HashMap<String, f64>),
39    OrderHistoryUpdate(OrderHistorySnapshot),
40    StrategyStatsUpdate {
41        strategy_stats: HashMap<String, OrderHistoryStats>,
42    },
43    PredictorMetricsUpdate {
44        symbol: String,
45        market: String,
46        predictor: String,
47        horizon: String,
48        r2: Option<f64>,
49        hit_rate: Option<f64>,
50        mae: Option<f64>,
51        sample_count: u64,
52        updated_at_ms: u64,
53    },
54    ExitPolicyUpdate {
55        symbol: String,
56        source_tag: String,
57        stop_price: Option<f64>,
58        expected_holding_ms: Option<u64>,
59        protective_stop_ok: Option<bool>,
60    },
61    PortfolioStateUpdate {
62        snapshot: PortfolioStateSnapshot,
63    },
64    RegimeUpdate {
65        symbol: String,
66        regime: MarketRegimeSignal,
67    },
68    RiskRateSnapshot {
69        global: RateBudgetSnapshot,
70        orders: RateBudgetSnapshot,
71        account: RateBudgetSnapshot,
72        market_data: RateBudgetSnapshot,
73    },
74    CloseAllRequested {
75        job_id: u64,
76        total: usize,
77        symbols: Vec<String>,
78    },
79    CloseAllProgress {
80        job_id: u64,
81        symbol: String,
82        completed: usize,
83        total: usize,
84        failed: usize,
85        reason: Option<String>,
86    },
87    CloseAllFinished {
88        job_id: u64,
89        completed: usize,
90        total: usize,
91        failed: usize,
92    },
93    TickDropped,
94    LogRecord(LogRecord),
95    LogMessage(String),
96    Error(String),
97}
98
99#[derive(Debug, Clone, Default)]
100pub struct PredictorMetricEntry {
101    pub symbol: String,
102    pub market: String,
103    pub predictor: String,
104    pub horizon: String,
105    pub r2: Option<f64>,
106    pub hit_rate: Option<f64>,
107    pub mae: Option<f64>,
108    pub sample_count: u64,
109    pub updated_at_ms: u64,
110}
111
112#[derive(Debug, Clone, Default)]
113pub struct ExitPolicyEntry {
114    pub stop_price: Option<f64>,
115    pub expected_holding_ms: Option<u64>,
116    pub protective_stop_ok: Option<bool>,
117    pub updated_at_ms: u64,
118}
119
120#[derive(Debug, Clone, Default)]
121pub struct AssetPnlEntry {
122    pub is_futures: bool,
123    pub side: Option<OrderSide>,
124    pub position_qty: f64,
125    pub entry_price: f64,
126    pub realized_pnl_usdt: f64,
127    pub unrealized_pnl_usdt: f64,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
131pub enum MarketRegime {
132    TrendUp,
133    TrendDown,
134    Range,
135    Unknown,
136}
137
138impl Default for MarketRegime {
139    fn default() -> Self {
140        Self::Unknown
141    }
142}
143
144#[derive(Debug, Clone, Copy, Default)]
145pub struct MarketRegimeSignal {
146    pub regime: MarketRegime,
147    pub confidence: f64,
148    pub ema_fast: f64,
149    pub ema_slow: f64,
150    pub vol_ratio: f64,
151    pub slope: f64,
152    pub updated_at_ms: u64,
153}
154
155#[derive(Debug, Clone, Default)]
156pub struct PortfolioStateSnapshot {
157    pub by_symbol: HashMap<String, AssetPnlEntry>,
158    pub total_realized_pnl_usdt: f64,
159    pub total_unrealized_pnl_usdt: f64,
160    pub open_orders_count: usize,
161    pub reserved_cash_usdt: f64,
162    pub gross_exposure_usdt: f64,
163    pub net_exposure_usdt: f64,
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
167pub enum LogLevel {
168    Debug,
169    Info,
170    Warn,
171    Error,
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq)]
175pub enum LogDomain {
176    Ws,
177    Strategy,
178    Risk,
179    Order,
180    Portfolio,
181    Ui,
182    System,
183}
184
185#[derive(Debug, Clone)]
186pub struct LogRecord {
187    pub ts_ms: u64,
188    pub level: LogLevel,
189    pub domain: LogDomain,
190    pub event: &'static str,
191    pub symbol: Option<String>,
192    pub strategy_tag: Option<String>,
193    pub trace_id: Option<String>,
194    pub msg: String,
195}
196
197impl LogRecord {
198    pub fn new(
199        level: LogLevel,
200        domain: LogDomain,
201        event: &'static str,
202        msg: impl Into<String>,
203    ) -> Self {
204        Self {
205            ts_ms: chrono::Utc::now().timestamp_millis() as u64,
206            level,
207            domain,
208            event,
209            symbol: None,
210            strategy_tag: None,
211            trace_id: None,
212            msg: msg.into(),
213        }
214    }
215}