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 EvSnapshotUpdate {
44 symbol: String,
45 source_tag: String,
46 ev: f64,
47 p_win: f64,
48 gate_mode: String,
49 gate_blocked: bool,
50 },
51 ExitPolicyUpdate {
52 symbol: String,
53 source_tag: String,
54 stop_price: Option<f64>,
55 expected_holding_ms: Option<u64>,
56 protective_stop_ok: Option<bool>,
57 },
58 AssetPnlUpdate {
59 by_symbol: HashMap<String, AssetPnlEntry>,
60 },
61 RiskRateSnapshot {
62 global: RateBudgetSnapshot,
63 orders: RateBudgetSnapshot,
64 account: RateBudgetSnapshot,
65 market_data: RateBudgetSnapshot,
66 },
67 CloseAllRequested {
68 job_id: u64,
69 total: usize,
70 symbols: Vec<String>,
71 },
72 CloseAllProgress {
73 job_id: u64,
74 symbol: String,
75 completed: usize,
76 total: usize,
77 failed: usize,
78 reason: Option<String>,
79 },
80 CloseAllFinished {
81 job_id: u64,
82 completed: usize,
83 total: usize,
84 failed: usize,
85 },
86 TickDropped,
87 LogRecord(LogRecord),
88 LogMessage(String),
89 Error(String),
90}
91
92#[derive(Debug, Clone, Default)]
93pub struct EvSnapshotEntry {
94 pub ev: f64,
95 pub p_win: f64,
96 pub gate_mode: String,
97 pub gate_blocked: bool,
98 pub updated_at_ms: u64,
99}
100
101#[derive(Debug, Clone, Default)]
102pub struct ExitPolicyEntry {
103 pub stop_price: Option<f64>,
104 pub expected_holding_ms: Option<u64>,
105 pub protective_stop_ok: Option<bool>,
106 pub updated_at_ms: u64,
107}
108
109#[derive(Debug, Clone, Default)]
110pub struct AssetPnlEntry {
111 pub is_futures: bool,
112 pub side: Option<OrderSide>,
113 pub position_qty: f64,
114 pub entry_price: f64,
115 pub realized_pnl_usdt: f64,
116 pub unrealized_pnl_usdt: f64,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub enum LogLevel {
121 Debug,
122 Info,
123 Warn,
124 Error,
125}
126
127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128pub enum LogDomain {
129 Ws,
130 Strategy,
131 Risk,
132 Order,
133 Portfolio,
134 Ui,
135 System,
136}
137
138#[derive(Debug, Clone)]
139pub struct LogRecord {
140 pub ts_ms: u64,
141 pub level: LogLevel,
142 pub domain: LogDomain,
143 pub event: &'static str,
144 pub symbol: Option<String>,
145 pub strategy_tag: Option<String>,
146 pub trace_id: Option<String>,
147 pub msg: String,
148}
149
150impl LogRecord {
151 pub fn new(level: LogLevel, domain: LogDomain, event: &'static str, msg: impl Into<String>) -> Self {
152 Self {
153 ts_ms: chrono::Utc::now().timestamp_millis() as u64,
154 level,
155 domain,
156 event,
157 symbol: None,
158 strategy_tag: None,
159 trace_id: None,
160 msg: msg.into(),
161 }
162 }
163}