1pub mod error;
7pub mod snapshot;
8pub mod tick;
9pub mod constants;
10pub mod types;
11pub mod daily;
12pub mod minute;
13
14pub use snapshot::MDSnapshot;
15pub use tick::Tick;
16pub use error::QAMDError;
17pub use types::*;
18pub use daily::{
19 DailyMarketData,
20 DailyBar,
21 InstrumentType,
22};
23pub use minute::{
24 MinuteMarketData,
25 MinuteBar,
26};
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use chrono::Utc;
32 use serde_json;
33
34 #[test]
35 fn test_create_snapshot() {
36 let now = Utc::now();
37 let snapshot = MDSnapshot {
38 instrument_id: "SSE_688286".to_string(),
39 amount: 1000000.0,
40 ask_price1: 10.5,
41 ask_volume1: 100,
42 bid_price1: 10.4,
43 bid_volume1: 150,
44 last_price: 10.45,
45 datetime: now,
46 highest: 10.6,
47 lowest: 10.3,
48 open: 10.35,
49 close: OptionalF64::Value(10.5),
50 volume: 25000,
51 pre_close: 10.3,
52 lower_limit: 9.3,
53 upper_limit: 11.3,
54 average: 10.45,
55 ask_price2: Some(10.55),
57 ask_volume2: Some(200),
58 bid_price2: Some(10.35),
59 bid_volume2: Some(250),
60 ask_price3: None,
62 ask_price4: None,
63 ask_price5: None,
64 ask_price6: None,
65 ask_price7: None,
66 ask_price8: None,
67 ask_price9: None,
68 ask_price10: None,
69 ask_volume3: None,
70 ask_volume4: None,
71 ask_volume5: None,
72 ask_volume6: None,
73 ask_volume7: None,
74 ask_volume8: None,
75 ask_volume9: None,
76 ask_volume10: None,
77 bid_price3: None,
78 bid_price4: None,
79 bid_price5: None,
80 bid_price6: None,
81 bid_price7: None,
82 bid_price8: None,
83 bid_price9: None,
84 bid_price10: None,
85 bid_volume3: None,
86 bid_volume4: None,
87 bid_volume5: None,
88 bid_volume6: None,
89 bid_volume7: None,
90 bid_volume8: None,
91 bid_volume9: None,
92 bid_volume10: None,
93 open_interest: OptionalF64::String("-".to_string()),
94 pre_open_interest: OptionalF64::String("-".to_string()),
95 pre_settlement: OptionalF64::String("-".to_string()),
96 settlement: OptionalF64::String("-".to_string()),
97 iopv: OptionalF64::Null,
98 };
99
100 assert_eq!(snapshot.instrument_id, "SSE_688286");
101 assert_eq!(snapshot.last_price, 10.45);
102 let spread = snapshot.bid_ask_spread();
103 assert!((spread - 0.1).abs() < f64::EPSILON * 100.0, "Expected spread to be approximately 0.1, got {}", spread);
104 assert!(snapshot.has_level2_depth());
105 assert!(!snapshot.is_futures_or_options());
106 assert!(!snapshot.is_etf());
107 }
108
109 #[test]
110 fn test_create_tick_from_snapshot() {
111 let now = Utc::now();
112 let snapshot = MDSnapshot {
113 instrument_id: "SZSE_300750".to_string(),
114 amount: 500000.0,
115 ask_price1: 55.67,
116 ask_volume1: 500,
117 bid_price1: 55.65,
118 bid_volume1: 300,
119 last_price: 55.66,
120 datetime: now,
121 highest: 56.0,
122 lowest: 55.2,
123 open: 55.5,
124 close: OptionalF64::Value(55.66),
125 volume: 10000,
126 pre_close: 55.4,
127 lower_limit: 50.0,
128 upper_limit: 61.0,
129 average: 55.65,
130 ask_price2: None,
132 ask_price3: None,
133 ask_price4: None,
134 ask_price5: None,
135 ask_price6: None,
136 ask_price7: None,
137 ask_price8: None,
138 ask_price9: None,
139 ask_price10: None,
140 ask_volume2: None,
141 ask_volume3: None,
142 ask_volume4: None,
143 ask_volume5: None,
144 ask_volume6: None,
145 ask_volume7: None,
146 ask_volume8: None,
147 ask_volume9: None,
148 ask_volume10: None,
149 bid_price2: None,
150 bid_price3: None,
151 bid_price4: None,
152 bid_price5: None,
153 bid_price6: None,
154 bid_price7: None,
155 bid_price8: None,
156 bid_price9: None,
157 bid_price10: None,
158 bid_volume2: None,
159 bid_volume3: None,
160 bid_volume4: None,
161 bid_volume5: None,
162 bid_volume6: None,
163 bid_volume7: None,
164 bid_volume8: None,
165 bid_volume9: None,
166 bid_volume10: None,
167 open_interest: OptionalF64::String("-".to_string()),
168 pre_open_interest: OptionalF64::String("-".to_string()),
169 pre_settlement: OptionalF64::String("-".to_string()),
170 settlement: OptionalF64::String("-".to_string()),
171 iopv: OptionalF64::Null,
172 };
173
174 let tick = Tick::from_snapshot(&snapshot);
175
176 assert_eq!(tick.instrument_id, "SZSE_300750");
177 assert_eq!(tick.last_price, 55.66);
178 assert_eq!(tick.volume, 10000);
179 assert_eq!(tick.amount, 500000.0);
180 assert_eq!(tick.datetime, now);
181 }
182
183 #[test]
184 fn test_serialization() {
185 let now = Utc::now();
186 let snapshot = MDSnapshot {
187 instrument_id: "SSE_688286".to_string(),
188 amount: 1000000.0,
189 ask_price1: 10.5,
190 ask_volume1: 100,
191 bid_price1: 10.4,
192 bid_volume1: 150,
193 last_price: 10.45,
194 datetime: now,
195 highest: 10.6,
196 lowest: 10.3,
197 open: 10.35,
198 close: OptionalF64::Value(10.5),
199 volume: 25000,
200 pre_close: 10.3,
201 lower_limit: 9.3,
202 upper_limit: 11.3,
203 average: 10.45,
204 ask_price2: None,
206 ask_price3: None,
207 ask_price4: None,
208 ask_price5: None,
209 ask_price6: None,
210 ask_price7: None,
211 ask_price8: None,
212 ask_price9: None,
213 ask_price10: None,
214 ask_volume2: None,
215 ask_volume3: None,
216 ask_volume4: None,
217 ask_volume5: None,
218 ask_volume6: None,
219 ask_volume7: None,
220 ask_volume8: None,
221 ask_volume9: None,
222 ask_volume10: None,
223 bid_price2: None,
224 bid_price3: None,
225 bid_price4: None,
226 bid_price5: None,
227 bid_price6: None,
228 bid_price7: None,
229 bid_price8: None,
230 bid_price9: None,
231 bid_price10: None,
232 bid_volume2: None,
233 bid_volume3: None,
234 bid_volume4: None,
235 bid_volume5: None,
236 bid_volume6: None,
237 bid_volume7: None,
238 bid_volume8: None,
239 bid_volume9: None,
240 bid_volume10: None,
241 open_interest: OptionalF64::String("-".to_string()),
242 pre_open_interest: OptionalF64::String("-".to_string()),
243 pre_settlement: OptionalF64::String("-".to_string()),
244 settlement: OptionalF64::String("-".to_string()),
245 iopv: OptionalF64::Null,
246 };
247
248 let json = serde_json::to_string(&snapshot).unwrap();
249 let deserialized: MDSnapshot = serde_json::from_str(&json).unwrap();
250
251 assert_eq!(deserialized.instrument_id, snapshot.instrument_id);
252 assert_eq!(deserialized.last_price, snapshot.last_price);
253 assert_eq!(deserialized.bid_ask_spread(), snapshot.bid_ask_spread());
254 }
255}