1use crate::presentation::serialization::string_as_float_opt;
2use lightstreamer_rs::subscription::ItemUpdate;
3use pretty_simple_display::{DebugPretty, DisplaySimple};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
9#[serde(rename_all = "UPPERCASE")]
10pub enum DealingFlag {
11 #[default]
13 Closed,
14 Call,
16 Deal,
18 Edit,
20 ClosingOnly,
22 DealNoEdit,
24 Auction,
26 AuctionNoEdit,
28 Suspend,
30}
31
32#[derive(DebugPretty, Clone, DisplaySimple, Serialize, Deserialize, Default)]
35pub struct PriceData {
36 pub item_name: String,
38 pub item_pos: i32,
40 pub fields: PriceFields,
42 pub changed_fields: PriceFields,
44 pub is_snapshot: bool,
46}
47
48#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
50pub struct PriceFields {
51 #[serde(rename = "MID_OPEN")]
53 #[serde(with = "string_as_float_opt")]
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub mid_open: Option<f64>,
56
57 #[serde(rename = "HIGH")]
59 #[serde(with = "string_as_float_opt")]
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub high: Option<f64>,
62
63 #[serde(rename = "LOW")]
65 #[serde(with = "string_as_float_opt")]
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub low: Option<f64>,
68
69 #[serde(rename = "BID")]
71 #[serde(with = "string_as_float_opt")]
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub bid: Option<f64>,
74
75 #[serde(rename = "OFFER")]
77 #[serde(with = "string_as_float_opt")]
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub offer: Option<f64>,
80
81 #[serde(rename = "CHANGE")]
83 #[serde(with = "string_as_float_opt")]
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub change: Option<f64>,
86
87 #[serde(rename = "CHANGE_PCT")]
89 #[serde(with = "string_as_float_opt")]
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub change_pct: Option<f64>,
92
93 #[serde(rename = "MARKET_DELAY")]
95 #[serde(with = "string_as_float_opt")]
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub market_delay: Option<f64>,
98
99 #[serde(rename = "MARKET_STATE")]
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub market_state: Option<String>,
103
104 #[serde(rename = "UPDATE_TIME")]
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub update_time: Option<String>,
108
109 #[serde(rename = "BIDQUOTEID")]
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub bid_quote_id: Option<String>,
113
114 #[serde(rename = "ASKQUOTEID")]
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub ask_quote_id: Option<String>,
118
119 #[serde(rename = "BIDPRICE1")]
122 #[serde(with = "string_as_float_opt")]
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub bid_price1: Option<f64>,
125
126 #[serde(rename = "BIDPRICE2")]
128 #[serde(with = "string_as_float_opt")]
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub bid_price2: Option<f64>,
131
132 #[serde(rename = "BIDPRICE3")]
134 #[serde(with = "string_as_float_opt")]
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub bid_price3: Option<f64>,
137
138 #[serde(rename = "BIDPRICE4")]
140 #[serde(with = "string_as_float_opt")]
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub bid_price4: Option<f64>,
143
144 #[serde(rename = "BIDPRICE5")]
146 #[serde(with = "string_as_float_opt")]
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub bid_price5: Option<f64>,
149
150 #[serde(rename = "ASKPRICE1")]
153 #[serde(with = "string_as_float_opt")]
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub ask_price1: Option<f64>,
156
157 #[serde(rename = "ASKPRICE2")]
159 #[serde(with = "string_as_float_opt")]
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub ask_price2: Option<f64>,
162
163 #[serde(rename = "ASKPRICE3")]
165 #[serde(with = "string_as_float_opt")]
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub ask_price3: Option<f64>,
168
169 #[serde(rename = "ASKPRICE4")]
171 #[serde(with = "string_as_float_opt")]
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub ask_price4: Option<f64>,
174
175 #[serde(rename = "ASKPRICE5")]
177 #[serde(with = "string_as_float_opt")]
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub ask_price5: Option<f64>,
180
181 #[serde(rename = "BIDSIZE1")]
184 #[serde(with = "string_as_float_opt")]
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub bid_size1: Option<f64>,
187
188 #[serde(rename = "BIDSIZE2")]
190 #[serde(with = "string_as_float_opt")]
191 #[serde(skip_serializing_if = "Option::is_none")]
192 pub bid_size2: Option<f64>,
193
194 #[serde(rename = "BIDSIZE3")]
196 #[serde(with = "string_as_float_opt")]
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub bid_size3: Option<f64>,
199
200 #[serde(rename = "BIDSIZE4")]
202 #[serde(with = "string_as_float_opt")]
203 #[serde(skip_serializing_if = "Option::is_none")]
204 pub bid_size4: Option<f64>,
205
206 #[serde(rename = "BIDSIZE5")]
208 #[serde(with = "string_as_float_opt")]
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub bid_size5: Option<f64>,
211
212 #[serde(rename = "ASKSIZE1")]
215 #[serde(with = "string_as_float_opt")]
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub ask_size1: Option<f64>,
218
219 #[serde(rename = "ASKSIZE2")]
221 #[serde(with = "string_as_float_opt")]
222 #[serde(skip_serializing_if = "Option::is_none")]
223 pub ask_size2: Option<f64>,
224
225 #[serde(rename = "ASKSIZE3")]
227 #[serde(with = "string_as_float_opt")]
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub ask_size3: Option<f64>,
230
231 #[serde(rename = "ASKSIZE4")]
233 #[serde(with = "string_as_float_opt")]
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub ask_size4: Option<f64>,
236
237 #[serde(rename = "ASKSIZE5")]
239 #[serde(with = "string_as_float_opt")]
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub ask_size5: Option<f64>,
242
243 #[serde(rename = "CURRENCY0")]
245 #[serde(skip_serializing_if = "Option::is_none")]
246 pub currency0: Option<String>,
247
248 #[serde(rename = "CURRENCY1")]
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub currency1: Option<String>,
252
253 #[serde(rename = "CURRENCY2")]
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub currency2: Option<String>,
257
258 #[serde(rename = "CURRENCY3")]
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub currency3: Option<String>,
262
263 #[serde(rename = "CURRENCY4")]
265 #[serde(skip_serializing_if = "Option::is_none")]
266 pub currency4: Option<String>,
267
268 #[serde(rename = "CURRENCY5")]
270 #[serde(skip_serializing_if = "Option::is_none")]
271 pub currency5: Option<String>,
272
273 #[serde(rename = "C1BIDSIZE1")]
275 #[serde(with = "string_as_float_opt")]
276 #[serde(skip_serializing_if = "Option::is_none")]
277 pub c1_bid_size_1: Option<f64>,
278
279 #[serde(rename = "C1BIDSIZE2")]
281 #[serde(with = "string_as_float_opt")]
282 #[serde(skip_serializing_if = "Option::is_none")]
283 pub c1_bid_size_2: Option<f64>,
284
285 #[serde(rename = "C1BIDSIZE3")]
287 #[serde(with = "string_as_float_opt")]
288 #[serde(skip_serializing_if = "Option::is_none")]
289 pub c1_bid_size_3: Option<f64>,
290
291 #[serde(rename = "C1BIDSIZE4")]
293 #[serde(with = "string_as_float_opt")]
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub c1_bid_size_4: Option<f64>,
296
297 #[serde(rename = "C1BIDSIZE5")]
299 #[serde(with = "string_as_float_opt")]
300 #[serde(skip_serializing_if = "Option::is_none")]
301 pub c1_bid_size_5: Option<f64>,
302
303 #[serde(rename = "C2BIDSIZE1")]
305 #[serde(with = "string_as_float_opt")]
306 #[serde(skip_serializing_if = "Option::is_none")]
307 pub c2_bid_size_1: Option<f64>,
308
309 #[serde(rename = "C2BIDSIZE2")]
311 #[serde(with = "string_as_float_opt")]
312 #[serde(skip_serializing_if = "Option::is_none")]
313 pub c2_bid_size_2: Option<f64>,
314
315 #[serde(rename = "C2BIDSIZE3")]
317 #[serde(with = "string_as_float_opt")]
318 #[serde(skip_serializing_if = "Option::is_none")]
319 pub c2_bid_size_3: Option<f64>,
320
321 #[serde(rename = "C2BIDSIZE4")]
323 #[serde(with = "string_as_float_opt")]
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub c2_bid_size_4: Option<f64>,
326
327 #[serde(rename = "C2BIDSIZE5")]
329 #[serde(with = "string_as_float_opt")]
330 #[serde(skip_serializing_if = "Option::is_none")]
331 pub c2_bid_size_5: Option<f64>,
332
333 #[serde(rename = "C3BIDSIZE1")]
335 #[serde(with = "string_as_float_opt")]
336 #[serde(skip_serializing_if = "Option::is_none")]
337 pub c3_bid_size_1: Option<f64>,
338
339 #[serde(rename = "C3BIDSIZE2")]
341 #[serde(with = "string_as_float_opt")]
342 #[serde(skip_serializing_if = "Option::is_none")]
343 pub c3_bid_size_2: Option<f64>,
344
345 #[serde(rename = "C3BIDSIZE3")]
347 #[serde(with = "string_as_float_opt")]
348 #[serde(skip_serializing_if = "Option::is_none")]
349 pub c3_bid_size_3: Option<f64>,
350
351 #[serde(rename = "C3BIDSIZE4")]
353 #[serde(with = "string_as_float_opt")]
354 #[serde(skip_serializing_if = "Option::is_none")]
355 pub c3_bid_size_4: Option<f64>,
356
357 #[serde(rename = "C3BIDSIZE5")]
359 #[serde(with = "string_as_float_opt")]
360 #[serde(skip_serializing_if = "Option::is_none")]
361 pub c3_bid_size_5: Option<f64>,
362
363 #[serde(rename = "C4BIDSIZE1")]
365 #[serde(with = "string_as_float_opt")]
366 #[serde(skip_serializing_if = "Option::is_none")]
367 pub c4_bid_size_1: Option<f64>,
368
369 #[serde(rename = "C4BIDSIZE2")]
371 #[serde(with = "string_as_float_opt")]
372 #[serde(skip_serializing_if = "Option::is_none")]
373 pub c4_bid_size_2: Option<f64>,
374
375 #[serde(rename = "C4BIDSIZE3")]
377 #[serde(with = "string_as_float_opt")]
378 #[serde(skip_serializing_if = "Option::is_none")]
379 pub c4_bid_size_3: Option<f64>,
380
381 #[serde(rename = "C4BIDSIZE4")]
383 #[serde(with = "string_as_float_opt")]
384 #[serde(skip_serializing_if = "Option::is_none")]
385 pub c4_bid_size_4: Option<f64>,
386
387 #[serde(rename = "C4BIDSIZE5")]
389 #[serde(with = "string_as_float_opt")]
390 #[serde(skip_serializing_if = "Option::is_none")]
391 pub c4_bid_size_5: Option<f64>,
392
393 #[serde(rename = "C5BIDSIZE1")]
395 #[serde(with = "string_as_float_opt")]
396 #[serde(skip_serializing_if = "Option::is_none")]
397 pub c5_bid_size_1: Option<f64>,
398
399 #[serde(rename = "C5BIDSIZE2")]
401 #[serde(with = "string_as_float_opt")]
402 #[serde(skip_serializing_if = "Option::is_none")]
403 pub c5_bid_size_2: Option<f64>,
404
405 #[serde(rename = "C5BIDSIZE3")]
407 #[serde(with = "string_as_float_opt")]
408 #[serde(skip_serializing_if = "Option::is_none")]
409 pub c5_bid_size_3: Option<f64>,
410
411 #[serde(rename = "C5BIDSIZE4")]
413 #[serde(with = "string_as_float_opt")]
414 #[serde(skip_serializing_if = "Option::is_none")]
415 pub c5_bid_size_4: Option<f64>,
416
417 #[serde(rename = "C5BIDSIZE5")]
419 #[serde(with = "string_as_float_opt")]
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub c5_bid_size_5: Option<f64>,
422
423 #[serde(rename = "C1ASKSIZE1")]
426 #[serde(with = "string_as_float_opt")]
427 #[serde(skip_serializing_if = "Option::is_none")]
428 pub c1_ask_size_1: Option<f64>,
429
430 #[serde(rename = "C1ASKSIZE2")]
432 #[serde(with = "string_as_float_opt")]
433 #[serde(skip_serializing_if = "Option::is_none")]
434 pub c1_ask_size_2: Option<f64>,
435
436 #[serde(rename = "C1ASKSIZE3")]
438 #[serde(with = "string_as_float_opt")]
439 #[serde(skip_serializing_if = "Option::is_none")]
440 pub c1_ask_size_3: Option<f64>,
441
442 #[serde(rename = "C1ASKSIZE4")]
444 #[serde(with = "string_as_float_opt")]
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub c1_ask_size_4: Option<f64>,
447
448 #[serde(rename = "C1ASKSIZE5")]
450 #[serde(with = "string_as_float_opt")]
451 #[serde(skip_serializing_if = "Option::is_none")]
452 pub c1_ask_size_5: Option<f64>,
453
454 #[serde(rename = "C2ASKSIZE1")]
456 #[serde(with = "string_as_float_opt")]
457 #[serde(skip_serializing_if = "Option::is_none")]
458 pub c2_ask_size_1: Option<f64>,
459
460 #[serde(rename = "C2ASKSIZE2")]
462 #[serde(with = "string_as_float_opt")]
463 #[serde(skip_serializing_if = "Option::is_none")]
464 pub c2_ask_size_2: Option<f64>,
465
466 #[serde(rename = "C2ASKSIZE3")]
468 #[serde(with = "string_as_float_opt")]
469 #[serde(skip_serializing_if = "Option::is_none")]
470 pub c2_ask_size_3: Option<f64>,
471
472 #[serde(rename = "C2ASKSIZE4")]
474 #[serde(with = "string_as_float_opt")]
475 #[serde(skip_serializing_if = "Option::is_none")]
476 pub c2_ask_size_4: Option<f64>,
477
478 #[serde(rename = "C2ASKSIZE5")]
480 #[serde(with = "string_as_float_opt")]
481 #[serde(skip_serializing_if = "Option::is_none")]
482 pub c2_ask_size_5: Option<f64>,
483
484 #[serde(rename = "C3ASKSIZE1")]
486 #[serde(with = "string_as_float_opt")]
487 #[serde(skip_serializing_if = "Option::is_none")]
488 pub c3_ask_size_1: Option<f64>,
489
490 #[serde(rename = "C3ASKSIZE2")]
492 #[serde(with = "string_as_float_opt")]
493 #[serde(skip_serializing_if = "Option::is_none")]
494 pub c3_ask_size_2: Option<f64>,
495
496 #[serde(rename = "C3ASKSIZE3")]
498 #[serde(with = "string_as_float_opt")]
499 #[serde(skip_serializing_if = "Option::is_none")]
500 pub c3_ask_size_3: Option<f64>,
501
502 #[serde(rename = "C3ASKSIZE4")]
504 #[serde(with = "string_as_float_opt")]
505 #[serde(skip_serializing_if = "Option::is_none")]
506 pub c3_ask_size_4: Option<f64>,
507
508 #[serde(rename = "C3ASKSIZE5")]
510 #[serde(with = "string_as_float_opt")]
511 #[serde(skip_serializing_if = "Option::is_none")]
512 pub c3_ask_size_5: Option<f64>,
513
514 #[serde(rename = "C4ASKSIZE1")]
516 #[serde(with = "string_as_float_opt")]
517 #[serde(skip_serializing_if = "Option::is_none")]
518 pub c4_ask_size_1: Option<f64>,
519
520 #[serde(rename = "C4ASKSIZE2")]
522 #[serde(with = "string_as_float_opt")]
523 #[serde(skip_serializing_if = "Option::is_none")]
524 pub c4_ask_size_2: Option<f64>,
525
526 #[serde(rename = "C4ASKSIZE3")]
528 #[serde(with = "string_as_float_opt")]
529 #[serde(skip_serializing_if = "Option::is_none")]
530 pub c4_ask_size_3: Option<f64>,
531
532 #[serde(rename = "C4ASKSIZE4")]
534 #[serde(with = "string_as_float_opt")]
535 #[serde(skip_serializing_if = "Option::is_none")]
536 pub c4_ask_size_4: Option<f64>,
537
538 #[serde(rename = "C4ASKSIZE5")]
540 #[serde(with = "string_as_float_opt")]
541 #[serde(skip_serializing_if = "Option::is_none")]
542 pub c4_ask_size_5: Option<f64>,
543
544 #[serde(rename = "C5ASKSIZE1")]
546 #[serde(with = "string_as_float_opt")]
547 #[serde(skip_serializing_if = "Option::is_none")]
548 pub c5_ask_size_1: Option<f64>,
549
550 #[serde(rename = "C5ASKSIZE2")]
552 #[serde(with = "string_as_float_opt")]
553 #[serde(skip_serializing_if = "Option::is_none")]
554 pub c5_ask_size_2: Option<f64>,
555
556 #[serde(rename = "C5ASKSIZE3")]
558 #[serde(with = "string_as_float_opt")]
559 #[serde(skip_serializing_if = "Option::is_none")]
560 pub c5_ask_size_3: Option<f64>,
561
562 #[serde(rename = "C5ASKSIZE4")]
564 #[serde(with = "string_as_float_opt")]
565 #[serde(skip_serializing_if = "Option::is_none")]
566 pub c5_ask_size_4: Option<f64>,
567
568 #[serde(rename = "C5ASKSIZE5")]
570 #[serde(with = "string_as_float_opt")]
571 #[serde(skip_serializing_if = "Option::is_none")]
572 pub c5_ask_size_5: Option<f64>,
573
574 #[serde(rename = "TIMESTAMP")]
576 #[serde(with = "string_as_float_opt")]
577 #[serde(skip_serializing_if = "Option::is_none")]
578 pub timestamp: Option<f64>,
579
580 #[serde(rename = "DLG_FLAG")]
582 #[serde(skip_serializing_if = "Option::is_none")]
583 pub dealing_flag: Option<DealingFlag>,
584}
585
586impl PriceData {
587 pub fn from_item_update(item_update: &ItemUpdate) -> Result<Self, String> {
597 let item_name = item_update.item_name.clone().unwrap_or_default();
599
600 let item_pos = item_update.item_pos as i32;
602
603 let is_snapshot = item_update.is_snapshot;
605
606 let fields = Self::create_price_fields(&item_update.fields)?;
608
609 let mut changed_fields_map: HashMap<String, Option<String>> = HashMap::new();
611 for (key, value) in &item_update.changed_fields {
612 changed_fields_map.insert(key.clone(), Some(value.clone()));
613 }
614 let changed_fields = Self::create_price_fields(&changed_fields_map)?;
615
616 Ok(PriceData {
617 item_name,
618 item_pos,
619 fields,
620 changed_fields,
621 is_snapshot,
622 })
623 }
624
625 fn create_price_fields(
627 fields_map: &HashMap<String, Option<String>>,
628 ) -> Result<PriceFields, String> {
629 let get_field = |key: &str| -> Option<String> { fields_map.get(key).cloned().flatten() };
631
632 let parse_float = |key: &str| -> Result<Option<f64>, String> {
634 match get_field(key) {
635 Some(val) if !val.is_empty() => val
636 .parse::<f64>()
637 .map(Some)
638 .map_err(|_| format!("Failed to parse {key} as float: {val}")),
639 _ => Ok(None),
640 }
641 };
642
643 let dealing_flag = match get_field("DLG_FLAG")
645 .as_deref()
646 .map(|s| s.to_uppercase())
647 .as_deref()
648 {
649 Some("CLOSED") => Some(DealingFlag::Closed),
650 Some("CALL") => Some(DealingFlag::Call),
651 Some("DEAL") => Some(DealingFlag::Deal),
652 Some("EDIT") => Some(DealingFlag::Edit),
653 Some("CLOSINGONLY") => Some(DealingFlag::ClosingOnly),
654 Some("DEALNOEDIT") => Some(DealingFlag::DealNoEdit),
655 Some("AUCTION") => Some(DealingFlag::Auction),
656 Some("AUCTIONNOEDIT") => Some(DealingFlag::AuctionNoEdit),
657 Some("SUSPEND") => Some(DealingFlag::Suspend),
658 Some(unknown) => return Err(format!("Unknown dealing flag: {unknown}")),
659 None => None,
660 };
661
662 Ok(PriceFields {
663 mid_open: parse_float("MID_OPEN")?,
664 high: parse_float("HIGH")?,
665 low: parse_float("LOW")?,
666 bid: parse_float("BID")?,
667 offer: parse_float("OFFER")?,
668 change: parse_float("CHANGE")?,
669 change_pct: parse_float("CHANGE_PCT")?,
670 market_delay: parse_float("MARKET_DELAY")?,
671 market_state: get_field("MARKET_STATE"),
672 update_time: get_field("UPDATE_TIME"),
673
674 bid_quote_id: get_field("BIDQUOTEID"),
675 ask_quote_id: get_field("ASKQUOTEID"),
676
677 bid_price1: parse_float("BIDPRICE1")?,
679 bid_price2: parse_float("BIDPRICE2")?,
680 bid_price3: parse_float("BIDPRICE3")?,
681 bid_price4: parse_float("BIDPRICE4")?,
682 bid_price5: parse_float("BIDPRICE5")?,
683
684 ask_price1: parse_float("ASKPRICE1")?,
686 ask_price2: parse_float("ASKPRICE2")?,
687 ask_price3: parse_float("ASKPRICE3")?,
688 ask_price4: parse_float("ASKPRICE4")?,
689 ask_price5: parse_float("ASKPRICE5")?,
690
691 bid_size1: parse_float("BIDSIZE1")?,
693 bid_size2: parse_float("BIDSIZE2")?,
694 bid_size3: parse_float("BIDSIZE3")?,
695 bid_size4: parse_float("BIDSIZE4")?,
696 bid_size5: parse_float("BIDSIZE5")?,
697
698 ask_size1: parse_float("ASKSIZE1")?,
700 ask_size2: parse_float("ASKSIZE2")?,
701 ask_size3: parse_float("ASKSIZE3")?,
702 ask_size4: parse_float("ASKSIZE4")?,
703 ask_size5: parse_float("ASKSIZE5")?,
704
705 currency0: get_field("CURRENCY0"),
707 currency1: get_field("CURRENCY1"),
708 currency2: get_field("CURRENCY2"),
709 currency3: get_field("CURRENCY3"),
710 currency4: get_field("CURRENCY4"),
711 currency5: get_field("CURRENCY5"),
712
713 c1_bid_size_1: parse_float("C1BIDSIZE1")?,
715 c1_bid_size_2: parse_float("C1BIDSIZE2")?,
716 c1_bid_size_3: parse_float("C1BIDSIZE3")?,
717 c1_bid_size_4: parse_float("C1BIDSIZE4")?,
718 c1_bid_size_5: parse_float("C1BIDSIZE5")?,
719
720 c2_bid_size_1: parse_float("C2BIDSIZE1")?,
721 c2_bid_size_2: parse_float("C2BIDSIZE2")?,
722 c2_bid_size_3: parse_float("C2BIDSIZE3")?,
723 c2_bid_size_4: parse_float("C2BIDSIZE4")?,
724 c2_bid_size_5: parse_float("C2BIDSIZE5")?,
725
726 c3_bid_size_1: parse_float("C3BIDSIZE1")?,
727 c3_bid_size_2: parse_float("C3BIDSIZE2")?,
728 c3_bid_size_3: parse_float("C3BIDSIZE3")?,
729 c3_bid_size_4: parse_float("C3BIDSIZE4")?,
730 c3_bid_size_5: parse_float("C3BIDSIZE5")?,
731
732 c4_bid_size_1: parse_float("C4BIDSIZE1")?,
733 c4_bid_size_2: parse_float("C4BIDSIZE2")?,
734 c4_bid_size_3: parse_float("C4BIDSIZE3")?,
735 c4_bid_size_4: parse_float("C4BIDSIZE4")?,
736 c4_bid_size_5: parse_float("C4BIDSIZE5")?,
737
738 c5_bid_size_1: parse_float("C5BIDSIZE1")?,
739 c5_bid_size_2: parse_float("C5BIDSIZE2")?,
740 c5_bid_size_3: parse_float("C5BIDSIZE3")?,
741 c5_bid_size_4: parse_float("C5BIDSIZE4")?,
742 c5_bid_size_5: parse_float("C5BIDSIZE5")?,
743
744 c1_ask_size_1: parse_float("C1ASKSIZE1")?,
746 c1_ask_size_2: parse_float("C1ASKSIZE2")?,
747 c1_ask_size_3: parse_float("C1ASKSIZE3")?,
748 c1_ask_size_4: parse_float("C1ASKSIZE4")?,
749 c1_ask_size_5: parse_float("C1ASKSIZE5")?,
750
751 c2_ask_size_1: parse_float("C2ASKSIZE1")?,
752 c2_ask_size_2: parse_float("C2ASKSIZE2")?,
753 c2_ask_size_3: parse_float("C2ASKSIZE3")?,
754 c2_ask_size_4: parse_float("C2ASKSIZE4")?,
755 c2_ask_size_5: parse_float("C2ASKSIZE5")?,
756
757 c3_ask_size_1: parse_float("C3ASKSIZE1")?,
758 c3_ask_size_2: parse_float("C3ASKSIZE2")?,
759 c3_ask_size_3: parse_float("C3ASKSIZE3")?,
760 c3_ask_size_4: parse_float("C3ASKSIZE4")?,
761 c3_ask_size_5: parse_float("C3ASKSIZE5")?,
762
763 c4_ask_size_1: parse_float("C4ASKSIZE1")?,
764 c4_ask_size_2: parse_float("C4ASKSIZE2")?,
765 c4_ask_size_3: parse_float("C4ASKSIZE3")?,
766 c4_ask_size_4: parse_float("C4ASKSIZE4")?,
767 c4_ask_size_5: parse_float("C4ASKSIZE5")?,
768
769 c5_ask_size_1: parse_float("C5ASKSIZE1")?,
770 c5_ask_size_2: parse_float("C5ASKSIZE2")?,
771 c5_ask_size_3: parse_float("C5ASKSIZE3")?,
772 c5_ask_size_4: parse_float("C5ASKSIZE4")?,
773 c5_ask_size_5: parse_float("C5ASKSIZE5")?,
774
775 timestamp: parse_float("TIMESTAMP")?,
776 dealing_flag,
777 })
778 }
779}
780
781impl From<&ItemUpdate> for PriceData {
782 fn from(item_update: &ItemUpdate) -> Self {
783 PriceData::from_item_update(item_update).unwrap_or_default()
784 }
785}