1use std::{
19 fmt::Display,
20 hash::{Hash, Hasher},
21};
22
23use nautilus_core::{
24 UnixNanos,
25 correctness::{FAILED, check_predicate_true},
26 serialization::Serializable,
27};
28use serde::{Deserialize, Serialize};
29
30use super::{HasTsInit, OrderBookDelta};
31use crate::{enums::RecordFlag, identifiers::InstrumentId};
32
33#[derive(Clone, Debug, Serialize, Deserialize)]
37#[cfg_attr(
38 feature = "python",
39 pyo3::pyclass(module = "nautilus_trader.model", from_py_object)
40)]
41#[cfg_attr(
42 feature = "python",
43 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
44)]
45pub struct OrderBookDeltas {
46 pub instrument_id: InstrumentId,
48 pub deltas: Vec<OrderBookDelta>,
50 pub flags: u8,
52 pub sequence: u64,
54 pub ts_event: UnixNanos,
56 pub ts_init: UnixNanos,
58}
59
60impl OrderBookDeltas {
61 #[must_use]
68 pub fn new(instrument_id: InstrumentId, deltas: Vec<OrderBookDelta>) -> Self {
69 Self::new_checked(instrument_id, deltas).expect(FAILED)
70 }
71
72 #[expect(
83 clippy::missing_panics_doc,
84 reason = "the unwrapped last element is guarded by the non-empty check"
85 )]
86 pub fn new_checked(
87 instrument_id: InstrumentId,
88 deltas: Vec<OrderBookDelta>,
89 ) -> anyhow::Result<Self> {
90 check_predicate_true(!deltas.is_empty(), "`deltas` cannot be empty")?;
91
92 let mismatch = deltas.iter().enumerate().find(|(_, delta)| {
93 instrument_id != delta.instrument_id
94 && (instrument_id.symbol.as_str() != delta.instrument_id.symbol.as_str()
95 || instrument_id.venue.as_str() != delta.instrument_id.venue.as_str())
96 });
97
98 if let Some((index, delta)) = mismatch {
99 check_predicate_true(
100 false,
101 &format!(
102 "`deltas` instrument IDs must match `instrument_id` {instrument_id}, but \
103 delta at index {index} of {} has {}",
104 deltas.len(),
105 delta.instrument_id,
106 ),
107 )?;
108 }
109 let last = deltas.last().expect("deltas not empty");
110 let flags = last.flags;
111 let sequence = last.sequence;
112 let ts_event = last.ts_event;
113 let ts_init = last.ts_init;
114 Ok(Self {
115 instrument_id,
116 deltas,
117 flags,
118 sequence,
119 ts_event,
120 ts_init,
121 })
122 }
123
124 #[cfg_attr(not(any(feature = "ffi", feature = "python")), allow(dead_code))]
126 #[must_use]
127 pub(crate) fn is_snapshot(&self) -> bool {
128 RecordFlag::F_SNAPSHOT.matches(self.flags)
129 }
130}
131
132impl PartialEq<Self> for OrderBookDeltas {
133 fn eq(&self, other: &Self) -> bool {
134 self.instrument_id == other.instrument_id && self.sequence == other.sequence
135 }
136}
137
138impl Eq for OrderBookDeltas {}
139
140impl Hash for OrderBookDeltas {
141 fn hash<H: Hasher>(&self, state: &mut H) {
142 self.instrument_id.hash(state);
143 self.sequence.hash(state);
144 }
145}
146
147impl Display for OrderBookDeltas {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 write!(
150 f,
151 "{},len={},flags={},sequence={},ts_event={},ts_init={}",
152 self.instrument_id,
153 self.deltas.len(),
154 self.flags,
155 self.sequence,
156 self.ts_event,
157 self.ts_init
158 )
159 }
160}
161
162impl Serializable for OrderBookDeltas {}
163
164impl HasTsInit for OrderBookDeltas {
165 fn ts_init(&self) -> UnixNanos {
166 self.ts_init
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 use std::{
173 collections::hash_map::DefaultHasher,
174 hash::{Hash, Hasher},
175 };
176
177 use nautilus_core::serialization::{
178 Serializable,
179 msgpack::{FromMsgPack, ToMsgPack},
180 };
181 use rstest::rstest;
182 use serde_json;
183
184 use super::*;
185 use crate::{
186 data::{order::BookOrder, stubs::stub_deltas},
187 enums::{BookAction, OrderSide, RecordFlag},
188 types::{Price, Quantity},
189 };
190
191 fn create_test_delta() -> OrderBookDelta {
192 let instrument_id = InstrumentId::from("EURUSD.SIM");
193 OrderBookDelta::new(
194 instrument_id,
195 BookAction::Add,
196 BookOrder::new(
197 OrderSide::Buy,
198 Price::from("1.0500"),
199 Quantity::from("100000"),
200 1,
201 ),
202 0,
203 123,
204 UnixNanos::from(1_000_000_000),
205 UnixNanos::from(2_000_000_000),
206 )
207 }
208
209 fn create_test_deltas() -> OrderBookDeltas {
210 let instrument_id = InstrumentId::from("EURUSD.SIM");
211 let flags = 32;
212 let sequence = 123;
213 let ts_event = UnixNanos::from(1_000_000_000);
214 let ts_init = UnixNanos::from(2_000_000_000);
215
216 let delta1 = OrderBookDelta::new(
217 instrument_id,
218 BookAction::Add,
219 BookOrder::new(
220 OrderSide::Sell,
221 Price::from("1.0520"),
222 Quantity::from("50000"),
223 1,
224 ),
225 flags,
226 sequence,
227 ts_event,
228 ts_init,
229 );
230 let delta2 = OrderBookDelta::new(
231 instrument_id,
232 BookAction::Add,
233 BookOrder::new(
234 OrderSide::Buy,
235 Price::from("1.0500"),
236 Quantity::from("75000"),
237 2,
238 ),
239 flags,
240 sequence,
241 ts_event,
242 ts_init,
243 );
244
245 OrderBookDeltas::new(instrument_id, vec![delta1, delta2])
246 }
247
248 fn create_test_deltas_multiple() -> OrderBookDeltas {
249 let instrument_id = InstrumentId::from("GBPUSD.SIM");
250 let flags = 16;
251 let sequence = 456;
252 let ts_event = UnixNanos::from(3_000_000_000);
253 let ts_init = UnixNanos::from(4_000_000_000);
254
255 let deltas = vec![
256 OrderBookDelta::clear(instrument_id, sequence, ts_event, ts_init),
257 OrderBookDelta::new(
258 instrument_id,
259 BookAction::Add,
260 BookOrder::new(
261 OrderSide::Sell,
262 Price::from("1.2550"),
263 Quantity::from("100000"),
264 1,
265 ),
266 flags,
267 sequence,
268 ts_event,
269 ts_init,
270 ),
271 OrderBookDelta::new(
272 instrument_id,
273 BookAction::Update,
274 BookOrder::new(
275 OrderSide::Buy,
276 Price::from("1.2530"),
277 Quantity::from("200000"),
278 2,
279 ),
280 flags,
281 sequence,
282 ts_event,
283 ts_init,
284 ),
285 OrderBookDelta::new(
286 instrument_id,
287 BookAction::Delete,
288 BookOrder::new(
289 OrderSide::Sell,
290 Price::from("1.2560"),
291 Quantity::from("0"),
292 3,
293 ),
294 flags,
295 sequence,
296 ts_event,
297 ts_init,
298 ),
299 ];
300
301 OrderBookDeltas::new(instrument_id, deltas)
302 }
303
304 fn assert_book_order_fields(expected: &BookOrder, actual: &BookOrder) {
307 assert_eq!(expected.side, actual.side);
308 assert_eq!(expected.price, actual.price);
309 assert_eq!(expected.size, actual.size);
310 assert_eq!(expected.order_id, actual.order_id);
311 }
312
313 fn assert_order_book_delta_fields(expected: &OrderBookDelta, actual: &OrderBookDelta) {
314 assert_eq!(expected.instrument_id, actual.instrument_id);
315 assert_eq!(expected.action, actual.action);
316 assert_book_order_fields(&expected.order, &actual.order);
317 assert_eq!(expected.flags, actual.flags);
318 assert_eq!(expected.sequence, actual.sequence);
319 assert_eq!(expected.ts_event, actual.ts_event);
320 assert_eq!(expected.ts_init, actual.ts_init);
321 }
322
323 fn assert_order_book_deltas_fields(expected: &OrderBookDeltas, actual: &OrderBookDeltas) {
324 assert_eq!(expected.instrument_id, actual.instrument_id);
325 assert_eq!(expected.flags, actual.flags);
326 assert_eq!(expected.sequence, actual.sequence);
327 assert_eq!(expected.ts_event, actual.ts_event);
328 assert_eq!(expected.ts_init, actual.ts_init);
329 assert_eq!(expected.deltas.len(), actual.deltas.len());
330
331 for (expected_delta, actual_delta) in expected.deltas.iter().zip(&actual.deltas) {
332 assert_order_book_delta_fields(expected_delta, actual_delta);
333 }
334 }
335
336 #[rstest]
337 fn test_order_book_deltas_new() {
338 let deltas = create_test_deltas();
339
340 assert_eq!(deltas.instrument_id, InstrumentId::from("EURUSD.SIM"));
341 assert_eq!(deltas.deltas.len(), 2);
342 assert_eq!(deltas.flags, 32);
343 assert_eq!(deltas.sequence, 123);
344 assert_eq!(deltas.ts_event, UnixNanos::from(1_000_000_000));
345 assert_eq!(deltas.ts_init, UnixNanos::from(2_000_000_000));
346 }
347
348 #[rstest]
349 fn test_order_book_deltas_new_checked_valid() {
350 let instrument_id = InstrumentId::from("EURUSD.SIM");
351 let delta = create_test_delta();
352
353 let result = OrderBookDeltas::new_checked(instrument_id, vec![delta]);
354
355 assert!(result.is_ok());
356 let deltas = result.unwrap();
357 assert_eq!(deltas.instrument_id, instrument_id);
358 assert_eq!(deltas.deltas.len(), 1);
359 }
360
361 #[rstest]
362 fn test_order_book_deltas_new_checked_accepts_homogeneous_deltas() {
363 let instrument_id = InstrumentId::from("EURUSD.SIM");
364 let delta1 = create_test_delta();
365 let mut delta2 = create_test_delta();
366 delta2.sequence = 124;
367
368 let result = OrderBookDeltas::new_checked(instrument_id, vec![delta1, delta2]);
369
370 assert!(result.is_ok());
371 assert_eq!(result.unwrap().deltas.len(), 2);
372 }
373
374 #[rstest]
375 #[case::first(0)]
376 #[case::later(1)]
377 fn test_order_book_deltas_new_checked_rejects_mismatched_instrument(
378 #[case] mismatch_index: usize,
379 ) {
380 let instrument_id = InstrumentId::from("EURUSD.SIM");
381 let mut deltas = vec![create_test_delta(), create_test_delta()];
382 deltas[mismatch_index].instrument_id = InstrumentId::from("GBPUSD.SIM");
383
384 let result = OrderBookDeltas::new_checked(instrument_id, deltas);
385
386 assert_eq!(
387 result.unwrap_err().to_string(),
388 format!(
389 "`deltas` instrument IDs must match `instrument_id` EURUSD.SIM, but delta at \
390 index {mismatch_index} of 2 has GBPUSD.SIM"
391 )
392 );
393 }
394
395 #[rstest]
396 fn test_order_book_deltas_new_checked_empty_deltas() {
397 let instrument_id = InstrumentId::from("EURUSD.SIM");
398
399 let result = OrderBookDeltas::new_checked(instrument_id, vec![]);
400
401 assert!(result.is_err());
402 assert!(
403 result
404 .unwrap_err()
405 .to_string()
406 .contains("`deltas` cannot be empty")
407 );
408 }
409
410 #[rstest]
411 #[should_panic(expected = "Condition failed")]
412 fn test_order_book_deltas_new_empty_deltas_panics() {
413 let instrument_id = InstrumentId::from("EURUSD.SIM");
414 let _ = OrderBookDeltas::new(instrument_id, vec![]);
415 }
416
417 #[rstest]
418 fn test_order_book_deltas_uses_last_delta_properties() {
419 let instrument_id = InstrumentId::from("EURUSD.SIM");
420
421 let delta1 = OrderBookDelta::new(
422 instrument_id,
423 BookAction::Add,
424 BookOrder::new(
425 OrderSide::Buy,
426 Price::from("1.0500"),
427 Quantity::from("100000"),
428 1,
429 ),
430 16, 100, UnixNanos::from(500_000_000), UnixNanos::from(1_000_000_000), );
435
436 let delta2 = OrderBookDelta::new(
437 instrument_id,
438 BookAction::Add,
439 BookOrder::new(
440 OrderSide::Sell,
441 Price::from("1.0520"),
442 Quantity::from("50000"),
443 2,
444 ),
445 32, 200, UnixNanos::from(1_500_000_000), UnixNanos::from(2_000_000_000), );
450
451 let deltas = OrderBookDeltas::new(instrument_id, vec![delta1, delta2]);
452
453 assert_eq!(deltas.flags, 32);
455 assert_eq!(deltas.sequence, 200);
456 assert_eq!(deltas.ts_event, UnixNanos::from(1_500_000_000));
457 assert_eq!(deltas.ts_init, UnixNanos::from(2_000_000_000));
458 }
459
460 #[rstest]
461 #[case::snapshot(
462 vec![(BookAction::Add, RecordFlag::F_SNAPSHOT as u8)],
463 true
464 )]
465 #[case::combined_flags(
466 vec![(
467 BookAction::Add,
468 RecordFlag::F_SNAPSHOT as u8 | RecordFlag::F_LAST as u8,
469 )],
470 true
471 )]
472 #[case::not_snapshot(vec![(BookAction::Add, RecordFlag::F_MBP as u8)], false)]
473 #[case::clear_without_snapshot(
474 vec![(BookAction::Clear, 0), (BookAction::Add, 0)],
475 false
476 )]
477 fn test_order_book_deltas_is_snapshot(
478 #[case] actions_and_flags: Vec<(BookAction, u8)>,
479 #[case] expected: bool,
480 ) {
481 let instrument_id = InstrumentId::from("EURUSD.SIM");
482 let deltas = actions_and_flags
483 .into_iter()
484 .map(|(action, flags)| {
485 let mut delta = create_test_delta();
486 delta.action = action;
487 delta.flags = flags;
488 delta
489 })
490 .collect();
491 let deltas = OrderBookDeltas::new(instrument_id, deltas);
492
493 assert_eq!(deltas.is_snapshot(), expected);
494 }
495
496 #[rstest]
497 fn test_order_book_deltas_hash_different_objects() {
498 let deltas1 = create_test_deltas();
499 let deltas2 = create_test_deltas_multiple();
500
501 let mut hasher1 = DefaultHasher::new();
502 let mut hasher2 = DefaultHasher::new();
503
504 deltas1.hash(&mut hasher1);
505 deltas2.hash(&mut hasher2);
506
507 assert_ne!(hasher1.finish(), hasher2.finish()); }
509
510 #[rstest]
511 fn test_order_book_deltas_hash_uses_instrument_id_and_sequence() {
512 let instrument_id = InstrumentId::from("EURUSD.SIM");
513 let sequence = 123u64;
514
515 let mut expected_hasher = DefaultHasher::new();
517 instrument_id.hash(&mut expected_hasher);
518 sequence.hash(&mut expected_hasher);
519 let expected_hash = expected_hasher.finish();
520
521 let delta = OrderBookDelta::new(
522 instrument_id,
523 BookAction::Add,
524 BookOrder::new(
525 OrderSide::Buy,
526 Price::from("1.0500"),
527 Quantity::from("100000"),
528 1,
529 ),
530 0,
531 sequence,
532 UnixNanos::from(1_000_000_000),
533 UnixNanos::from(2_000_000_000),
534 );
535
536 let deltas = OrderBookDeltas::new(instrument_id, vec![delta]);
537
538 let mut deltas_hasher = DefaultHasher::new();
539 deltas.hash(&mut deltas_hasher);
540
541 assert_eq!(deltas_hasher.finish(), expected_hash);
542 }
543
544 #[rstest]
545 fn test_order_book_deltas_display() {
546 let deltas = create_test_deltas();
547 let display_str = format!("{deltas}");
548
549 assert!(display_str.contains("EURUSD.SIM"));
550 assert!(display_str.contains("len=2"));
551 assert!(display_str.contains("flags=32"));
552 assert!(display_str.contains("sequence=123"));
553 assert!(display_str.contains("ts_event=1000000000"));
554 assert!(display_str.contains("ts_init=2000000000"));
555 }
556
557 #[rstest]
558 fn test_order_book_deltas_display_format() {
559 let deltas = create_test_deltas();
560 let expected =
561 "EURUSD.SIM,len=2,flags=32,sequence=123,ts_event=1000000000,ts_init=2000000000";
562
563 assert_eq!(format!("{deltas}"), expected);
564 }
565
566 #[rstest]
567 fn test_order_book_deltas_has_ts_init() {
568 let deltas = create_test_deltas();
569
570 assert_eq!(deltas.ts_init(), UnixNanos::from(2_000_000_000));
571 }
572
573 #[rstest]
574 fn test_order_book_deltas_clone() {
575 let deltas1 = create_test_deltas();
576 let deltas2 = deltas1.clone();
577
578 assert_eq!(deltas1.instrument_id, deltas2.instrument_id);
579 assert_eq!(deltas1.deltas.len(), deltas2.deltas.len());
580 assert_eq!(deltas1.flags, deltas2.flags);
581 assert_eq!(deltas1.sequence, deltas2.sequence);
582 assert_eq!(deltas1.ts_event, deltas2.ts_event);
583 assert_eq!(deltas1.ts_init, deltas2.ts_init);
584 assert_eq!(deltas1, deltas2);
585 }
586
587 #[rstest]
588 fn test_order_book_deltas_debug() {
589 let deltas = create_test_deltas();
590 let debug_str = format!("{deltas:?}");
591
592 assert!(debug_str.contains("OrderBookDeltas"));
593 assert!(debug_str.contains("EURUSD.SIM"));
594 assert!(debug_str.contains("flags: 32"));
595 assert!(debug_str.contains("sequence: 123"));
596 }
597
598 #[rstest]
599 fn test_order_book_deltas_serialization() {
600 let deltas = create_test_deltas();
601
602 let json = serde_json::to_string(&deltas).unwrap();
604 let deserialized: OrderBookDeltas = serde_json::from_str(&json).unwrap();
605
606 assert_eq!(deltas.instrument_id, deserialized.instrument_id);
607 assert_eq!(deltas.deltas.len(), deserialized.deltas.len());
608 assert_eq!(deltas.flags, deserialized.flags);
609 assert_eq!(deltas.sequence, deserialized.sequence);
610 assert_eq!(deltas.ts_event, deserialized.ts_event);
611 assert_eq!(deltas.ts_init, deserialized.ts_init);
612 }
613
614 #[rstest]
615 fn test_json_serialization(stub_deltas: OrderBookDeltas) {
616 let deltas = stub_deltas;
617 let serialized = deltas.to_json_bytes().unwrap();
618 let deserialized = OrderBookDeltas::from_json_bytes(serialized.as_ref()).unwrap();
619
620 assert_order_book_deltas_fields(&deltas, &deserialized);
621 }
622
623 #[rstest]
624 fn test_msgpack_serialization() {
625 let deltas = create_test_deltas_multiple();
626 let serialized = deltas.to_msgpack_bytes().unwrap();
627 let deserialized = OrderBookDeltas::from_msgpack_bytes(serialized.as_ref()).unwrap();
628
629 assert_order_book_deltas_fields(&deltas, &deserialized);
630 }
631
632 #[rstest]
633 fn test_order_book_deltas_single_delta() {
634 let delta = create_test_delta();
635 let instrument_id = delta.instrument_id;
636
637 let deltas = OrderBookDeltas::new(instrument_id, vec![delta]);
638
639 assert_eq!(deltas.instrument_id, instrument_id);
640 assert_eq!(deltas.deltas.len(), 1);
641 assert_eq!(deltas.flags, delta.flags);
642 assert_eq!(deltas.sequence, delta.sequence);
643 assert_eq!(deltas.ts_event, delta.ts_event);
644 assert_eq!(deltas.ts_init, delta.ts_init);
645 }
646
647 #[rstest]
648 fn test_order_book_deltas_large_number_of_deltas() {
649 let instrument_id = InstrumentId::from("ETHUSD.CRYPTO");
650 let mut delta_vec = Vec::new();
651
652 for i in 0..100 {
654 let delta = OrderBookDelta::new(
655 instrument_id,
656 BookAction::Add,
657 BookOrder::new(
658 OrderSide::Buy,
659 Price::from(&format!("1000.{i:02}")),
660 Quantity::from("1000"),
661 i as u64,
662 ),
663 0,
664 i as u64,
665 UnixNanos::from(1_000_000_000 + i as u64),
666 UnixNanos::from(2_000_000_000 + i as u64),
667 );
668 delta_vec.push(delta);
669 }
670
671 let deltas = OrderBookDeltas::new(instrument_id, delta_vec);
672
673 assert_eq!(deltas.deltas.len(), 100);
674 assert_eq!(deltas.sequence, 99); assert_eq!(deltas.ts_event, UnixNanos::from(1_000_000_000 + 99));
676 assert_eq!(deltas.ts_init, UnixNanos::from(2_000_000_000 + 99));
677 }
678
679 #[rstest]
680 fn test_order_book_deltas_different_action_types() {
681 let deltas = create_test_deltas_multiple();
682
683 assert_eq!(deltas.deltas.len(), 4);
684
685 assert_eq!(deltas.deltas[0].action, BookAction::Clear);
687 assert_eq!(deltas.deltas[1].action, BookAction::Add);
688 assert_eq!(deltas.deltas[2].action, BookAction::Update);
689 assert_eq!(deltas.deltas[3].action, BookAction::Delete);
690 }
691
692 #[rstest]
693 fn test_order_book_deltas_with_stub(stub_deltas: OrderBookDeltas) {
694 let deltas = stub_deltas;
695
696 assert_eq!(deltas.instrument_id, InstrumentId::from("AAPL.XNAS"));
697 assert_eq!(deltas.deltas.len(), 7);
698 assert_eq!(deltas.flags, 32);
699 assert_eq!(deltas.sequence, 0);
700 assert_eq!(deltas.ts_event, UnixNanos::from(1));
701 assert_eq!(deltas.ts_init, UnixNanos::from(2));
702 }
703
704 #[rstest]
705 fn test_display_with_stub(stub_deltas: OrderBookDeltas) {
706 let deltas = stub_deltas;
707 assert_eq!(
708 format!("{deltas}"),
709 "AAPL.XNAS,len=7,flags=32,sequence=0,ts_event=1,ts_init=2".to_string()
710 );
711 }
712
713 #[rstest]
714 fn test_order_book_deltas_zero_sequence() {
715 let instrument_id = InstrumentId::from("ZERO.TEST");
716 let delta = OrderBookDelta::new(
717 instrument_id,
718 BookAction::Add,
719 BookOrder::new(
720 OrderSide::Buy,
721 Price::from("100.0"),
722 Quantity::from("1000"),
723 1,
724 ),
725 0,
726 0, UnixNanos::from(0), UnixNanos::from(0),
729 );
730
731 let deltas = OrderBookDeltas::new(instrument_id, vec![delta]);
732
733 assert_eq!(deltas.sequence, 0);
734 assert_eq!(deltas.ts_event, UnixNanos::from(0));
735 assert_eq!(deltas.ts_init, UnixNanos::from(0));
736 }
737
738 #[rstest]
739 fn test_order_book_deltas_max_values() {
740 let instrument_id = InstrumentId::from("MAX.TEST");
741 let delta = OrderBookDelta::new(
742 instrument_id,
743 BookAction::Add,
744 BookOrder::new(
745 OrderSide::Buy,
746 Price::from("999999.99"),
747 Quantity::from("999999999"),
748 u64::MAX,
749 ),
750 u8::MAX,
751 u64::MAX,
752 UnixNanos::from(u64::MAX),
753 UnixNanos::from(u64::MAX),
754 );
755
756 let deltas = OrderBookDeltas::new(instrument_id, vec![delta]);
757
758 assert_eq!(deltas.flags, u8::MAX);
759 assert_eq!(deltas.sequence, u64::MAX);
760 assert_eq!(deltas.ts_event, UnixNanos::from(u64::MAX));
761 assert_eq!(deltas.ts_init, UnixNanos::from(u64::MAX));
762 }
763
764 #[rstest]
765 fn test_new() {
766 let instrument_id = InstrumentId::from("AAPL.XNAS");
767 let flags = 32; let sequence = 0;
769 let ts_event = 1;
770 let ts_init = 2;
771
772 let delta0 =
773 OrderBookDelta::clear(instrument_id, sequence, ts_event.into(), ts_init.into());
774 let delta1 = OrderBookDelta::new(
775 instrument_id,
776 BookAction::Add,
777 BookOrder::new(
778 OrderSide::Sell,
779 Price::from("102.00"),
780 Quantity::from("300"),
781 1,
782 ),
783 flags,
784 sequence,
785 ts_event.into(),
786 ts_init.into(),
787 );
788 let delta2 = OrderBookDelta::new(
789 instrument_id,
790 BookAction::Add,
791 BookOrder::new(
792 OrderSide::Sell,
793 Price::from("101.00"),
794 Quantity::from("200"),
795 2,
796 ),
797 flags,
798 sequence,
799 ts_event.into(),
800 ts_init.into(),
801 );
802 let delta3 = OrderBookDelta::new(
803 instrument_id,
804 BookAction::Add,
805 BookOrder::new(
806 OrderSide::Sell,
807 Price::from("100.00"),
808 Quantity::from("100"),
809 3,
810 ),
811 flags,
812 sequence,
813 ts_event.into(),
814 ts_init.into(),
815 );
816 let delta4 = OrderBookDelta::new(
817 instrument_id,
818 BookAction::Add,
819 BookOrder::new(
820 OrderSide::Buy,
821 Price::from("99.00"),
822 Quantity::from("100"),
823 4,
824 ),
825 flags,
826 sequence,
827 ts_event.into(),
828 ts_init.into(),
829 );
830 let delta5 = OrderBookDelta::new(
831 instrument_id,
832 BookAction::Add,
833 BookOrder::new(
834 OrderSide::Buy,
835 Price::from("98.00"),
836 Quantity::from("200"),
837 5,
838 ),
839 flags,
840 sequence,
841 ts_event.into(),
842 ts_init.into(),
843 );
844 let delta6 = OrderBookDelta::new(
845 instrument_id,
846 BookAction::Add,
847 BookOrder::new(
848 OrderSide::Buy,
849 Price::from("97.00"),
850 Quantity::from("300"),
851 6,
852 ),
853 flags,
854 sequence,
855 ts_event.into(),
856 ts_init.into(),
857 );
858
859 let deltas = OrderBookDeltas::new(
860 instrument_id,
861 vec![delta0, delta1, delta2, delta3, delta4, delta5, delta6],
862 );
863
864 assert_eq!(deltas.instrument_id, instrument_id);
865 assert_eq!(deltas.deltas.len(), 7);
866 assert_eq!(deltas.flags, flags);
867 assert_eq!(deltas.sequence, sequence);
868 assert_eq!(deltas.ts_event, ts_event);
869 assert_eq!(deltas.ts_init, ts_init);
870 }
871}