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