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 TickDropped,
68 LogRecord(LogRecord),
69 LogMessage(String),
70 Error(String),
71}
72
73#[derive(Debug, Clone, Default)]
74pub struct EvSnapshotEntry {
75 pub ev: f64,
76 pub p_win: f64,
77 pub gate_mode: String,
78 pub gate_blocked: bool,
79 pub updated_at_ms: u64,
80}
81
82#[derive(Debug, Clone, Default)]
83pub struct ExitPolicyEntry {
84 pub stop_price: Option<f64>,
85 pub expected_holding_ms: Option<u64>,
86 pub protective_stop_ok: Option<bool>,
87 pub updated_at_ms: u64,
88}
89
90#[derive(Debug, Clone, Default)]
91pub struct AssetPnlEntry {
92 pub is_futures: bool,
93 pub side: Option<OrderSide>,
94 pub position_qty: f64,
95 pub entry_price: f64,
96 pub realized_pnl_usdt: f64,
97 pub unrealized_pnl_usdt: f64,
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum LogLevel {
102 Debug,
103 Info,
104 Warn,
105 Error,
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum LogDomain {
110 Ws,
111 Strategy,
112 Risk,
113 Order,
114 Portfolio,
115 Ui,
116 System,
117}
118
119#[derive(Debug, Clone)]
120pub struct LogRecord {
121 pub ts_ms: u64,
122 pub level: LogLevel,
123 pub domain: LogDomain,
124 pub event: &'static str,
125 pub symbol: Option<String>,
126 pub strategy_tag: Option<String>,
127 pub trace_id: Option<String>,
128 pub msg: String,
129}
130
131impl LogRecord {
132 pub fn new(level: LogLevel, domain: LogDomain, event: &'static str, msg: impl Into<String>) -> Self {
133 Self {
134 ts_ms: chrono::Utc::now().timestamp_millis() as u64,
135 level,
136 domain,
137 event,
138 symbol: None,
139 strategy_tag: None,
140 trace_id: None,
141 msg: msg.into(),
142 }
143 }
144}