1#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6pub struct Security {
7 pub market: QotMarket,
9 pub code: String,
11}
12
13impl Security {
14 pub fn new(market: QotMarket, code: impl Into<String>) -> Self {
16 Self {
17 market,
18 code: code.into(),
19 }
20 }
21
22 pub fn from_proto(s: &futu_proto::qot_common::Security) -> Self {
24 Self {
25 market: QotMarket::from_i32(s.market),
26 code: s.code.clone(),
27 }
28 }
29
30 pub fn to_proto(&self) -> futu_proto::qot_common::Security {
32 futu_proto::qot_common::Security {
33 market: self.market as i32,
34 code: self.code.clone(),
35 }
36 }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
41#[repr(i32)]
42#[non_exhaustive]
43pub enum QotMarket {
44 Unknown = 0,
45 HkSecurity = 1,
46 HkFuture = 2,
47 UsSecurity = 11,
48 CnshSecurity = 21,
49 CnszSecurity = 22,
50 SgSecurity = 31,
51 JpSecurity = 41,
52 AuSecurity = 51,
53 MySecurity = 61,
54 CaSecurity = 71,
55 FxSecurity = 81,
56 Crypto = 91,
60}
61
62impl QotMarket {
63 pub fn from_i32(v: i32) -> Self {
65 match v {
66 1 => Self::HkSecurity,
67 2 => Self::HkFuture,
68 11 => Self::UsSecurity,
69 21 => Self::CnshSecurity,
70 22 => Self::CnszSecurity,
71 31 => Self::SgSecurity,
72 41 => Self::JpSecurity,
73 51 => Self::AuSecurity,
74 61 => Self::MySecurity,
75 71 => Self::CaSecurity,
76 81 => Self::FxSecurity,
77 91 => Self::Crypto,
78 _ => Self::Unknown,
79 }
80 }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
85#[repr(i32)]
86#[non_exhaustive]
87pub enum SubType {
88 None = 0,
89 Basic = 1,
90 OrderBook = 2,
91 OrderBookOdd = 22,
92 Ticker = 4,
93 RT = 5,
94 KLDay = 6,
95 KL5Min = 7,
96 KL15Min = 8,
97 KL30Min = 9,
98 KL60Min = 10,
99 KL1Min = 11,
100 KLWeek = 12,
101 KLMonth = 13,
102 Broker = 14,
103 KLQuarter = 15,
104 KLYear = 16,
105 KL3Min = 17,
106 OrderDetail = 18,
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111#[repr(i32)]
112#[non_exhaustive]
113pub enum KLType {
114 Unknown = 0,
115 Min1 = 1,
116 Day = 2,
117 Week = 3,
118 Month = 4,
119 Year = 5,
120 Min5 = 6,
121 Min15 = 7,
122 Min30 = 8,
123 Min60 = 9,
124 Min3 = 10,
125 Quarter = 11,
126}
127
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130#[repr(i32)]
131#[non_exhaustive]
132pub enum RehabType {
133 None = 0,
134 Forward = 1,
135 Backward = 2,
136}
137
138#[derive(Debug, Clone)]
140pub struct KLine {
141 pub time: String,
143 pub is_blank: bool,
145 pub high_price: f64,
147 pub open_price: f64,
149 pub low_price: f64,
151 pub close_price: f64,
153 pub last_close_price: f64,
155 pub volume: i64,
157 pub turnover: f64,
159 pub turnover_rate: f64,
161 pub pe: f64,
163 pub change_rate: f64,
165 pub timestamp: f64,
167}
168
169impl KLine {
170 pub fn from_proto(k: &futu_proto::qot_common::KLine) -> Self {
171 Self {
172 time: k.time.clone(),
173 is_blank: k.is_blank,
174 high_price: k.high_price.unwrap_or(0.0),
175 open_price: k.open_price.unwrap_or(0.0),
176 low_price: k.low_price.unwrap_or(0.0),
177 close_price: k.close_price.unwrap_or(0.0),
178 last_close_price: k.last_close_price.unwrap_or(0.0),
179 volume: k.volume.unwrap_or(0),
180 turnover: k.turnover.unwrap_or(0.0),
181 turnover_rate: k.turnover_rate.unwrap_or(0.0),
182 pe: k.pe.unwrap_or(0.0),
183 change_rate: k.change_rate.unwrap_or(0.0),
184 timestamp: k.timestamp.unwrap_or(0.0),
185 }
186 }
187}
188
189#[derive(Debug, Clone)]
191pub struct BasicQot {
192 pub security: Security,
194 pub is_suspended: bool,
196 pub list_time: String,
198 pub price_spread: f64,
200 pub update_time: String,
202 pub high_price: f64,
204 pub open_price: f64,
206 pub low_price: f64,
208 pub cur_price: f64,
210 pub last_close_price: f64,
212 pub volume: i64,
214 pub turnover: f64,
216 pub turnover_rate: f64,
218 pub amplitude: f64,
220}
221
222impl BasicQot {
223 pub fn from_proto(q: &futu_proto::qot_common::BasicQot) -> Self {
224 Self {
225 security: Security::from_proto(&q.security),
226 is_suspended: q.is_suspended,
227 list_time: q.list_time.clone(),
228 price_spread: q.price_spread,
229 update_time: q.update_time.clone(),
230 high_price: q.high_price,
231 open_price: q.open_price,
232 low_price: q.low_price,
233 cur_price: q.cur_price,
234 last_close_price: q.last_close_price,
235 volume: q.volume,
236 turnover: q.turnover,
237 turnover_rate: q.turnover_rate,
238 amplitude: q.amplitude,
239 }
240 }
241}
242
243#[derive(Debug, Clone)]
245pub struct OrderBookEntry {
246 pub price: f64,
248 pub volume: i64,
250 pub order_count: i32,
252}
253
254impl OrderBookEntry {
255 pub fn from_proto(ob: &futu_proto::qot_common::OrderBook) -> Self {
256 Self {
257 price: ob.price,
258 volume: ob.volume,
259 order_count: ob.oreder_count, }
261 }
262}
263
264#[derive(Debug, Clone)]
266pub struct OrderBookData {
267 pub security: Security,
269 pub ask_list: Vec<OrderBookEntry>,
271 pub bid_list: Vec<OrderBookEntry>,
273}
274
275pub fn market_state_label(s: i32) -> &'static str {
284 match s {
285 0 => "None", 1 => "Auction", 2 => "WaitingOpen", 3 => "Morning", 4 => "Rest", 5 => "Afternoon", 6 => "Closed", 8 => "PreMarketBegin", 9 => "PreMarketEnd", 10 => "AfterHoursBegin", 11 => "AfterHoursEnd", 12 => "FutuSwitchDate", 13 => "NightOpen", 14 => "NightEnd", 15 => "FutureDayOpen", 16 => "FutureDayBreak", 17 => "FutureDayClose", 18 => "FutureDayWaitForOpen", 19 => "HkCas", 20 => "FutureNightWait", 21 => "FutureAfternoon", 22 => "FutureSwitchDate", 23 => "FutureOpen", 24 => "FutureBreak", 25 => "FutureBreakOver", 26 => "FutureClose", 27 => "StibAfterHoursWait", 28 => "StibAfterHoursBegin", 29 => "StibAfterHoursEnd", 30 => "CloseAuction", 31 => "AfternoonEnd", 32 => "Night", 33 => "OvernightBegin", 34 => "OvernightEnd", 35 => "TradeAtLast", 36 => "TradeAuction", 37 => "Overnight", _ => "Unknown",
323 }
324}
325
326#[cfg(test)]
327mod tests;