1use std::{hint::unreachable_unchecked, mem::replace};
2
3use crate::{event::Event, level::Level};
4
5#[derive(Debug, Clone)]
8pub struct Orderbook {
9 best_bid: Option<Level>,
10 best_ask: Option<Level>,
11 bids: Buffer,
12 asks: Buffer,
13 last_updated: u64,
14 last_sequence: u64,
15}
16
17impl Default for Orderbook {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl Orderbook {
24 pub fn new() -> Self {
25 Self {
26 best_bid: None,
27 best_ask: None,
28 bids: Buffer::new(true),
29 asks: Buffer::new(false),
30 last_updated: 0,
31 last_sequence: 0,
32 }
33 }
34
35 #[inline]
36 pub fn process(&mut self, event: Event) {
37 if event.timestamp < self.last_updated || event.seq < self.last_sequence {
38 return;
39 }
40
41 match event.is_trade {
42 true => self.process_trade(event),
43 false => self.process_lvl2(event),
44 };
45
46 self.last_updated = event.timestamp;
47 self.last_sequence = event.seq;
48 }
49
50 #[inline]
51 pub fn process_stream_bbo(&mut self, event: Event) -> Option<(Option<Level>, Option<Level>)> {
52 let old_bid = self.best_bid;
53 let old_ask = self.best_ask;
54
55 self.process(event);
56
57 let new_bid = self.best_bid;
58 let new_ask = self.best_ask;
59
60 if old_bid != new_bid || old_ask != new_ask {
61 Some((new_bid, new_ask))
62 } else {
63 None
64 }
65 }
66
67 #[inline]
68 fn process_lvl2(&mut self, event: Event) {
69 match event.is_buy {
70 true => {
71 if event.size == 0.0 {
72 if let Ok(to_remove) = self.bids.find_index_bids(event.price) {
73 let removed = self.bids.remove(to_remove);
74 if let Some(best_bid) = self.best_bid {
75 if removed == best_bid.price {
76 self.best_bid = self.bids.first();
77 }
78 }
79 }
80 } else {
81 match self.bids.find_index_bids(event.price) {
82 Ok(to_modify) => self.bids.modify(to_modify, event.size),
83 Err(to_insert) => self.bids.insert(to_insert, Level::from(event)),
84 }
85
86 self.best_bid = self.bids.first();
87 }
88 }
89 false => {
90 if event.size == 0.0 {
91 if let Ok(to_remove) = self.asks.find_index_asks(event.price) {
92 let removed = self.asks.remove(to_remove);
93 if let Some(best_ask) = self.best_ask {
94 if removed == best_ask.price {
95 self.best_ask = self.asks.first();
96 }
97 }
98 }
99 } else {
100 match self.asks.find_index_asks(event.price) {
101 Ok(to_modify) => self.asks.modify(to_modify, event.size),
102 Err(to_insert) => self.asks.insert(to_insert, Level::from(event)),
103 }
104 self.best_ask = self.asks.first();
105 }
106 }
107 }
108 }
109
110 #[inline]
111 fn process_trade(&mut self, event: Event) {
112 if event.is_buy {
113 if let Ok(index) = self.bids.find_index_bids(event.price) {
114 let level = self.bids.get_mut(index);
115 if event.size >= level.size {
116 self.bids.remove(index);
117 } else {
118 level.size -= event.size;
119 }
120 };
121 } else if let Ok(index) = self.asks.find_index_asks(event.price) {
122 let level = self.asks.get_mut(index);
123 if event.size >= level.size {
124 self.asks.remove(index);
125 } else {
126 level.size -= event.size;
127 }
128 };
129 }
130
131 pub fn best_bid(&self) -> Option<Level> {
132 self.best_bid
133 }
134
135 pub fn best_ask(&self) -> Option<Level> {
136 self.best_ask
137 }
138
139 #[inline]
140 pub fn top_bids(&self, n: usize) -> Vec<Level> {
141 let mut result = Vec::with_capacity(n);
142
143 for level in self.bids.buf.iter() {
144 if result.len() == n {
145 break;
146 }
147 if level.price != self.bids.limit {
148 result.push(*level);
149 }
150 }
151
152 result
153 }
154
155 #[inline]
156 pub fn top_asks(&self, n: usize) -> Vec<Level> {
157 let mut result = Vec::with_capacity(n);
158
159 for level in self.asks.buf.iter() {
160 if result.len() == n {
161 break;
162 }
163 if level.price != self.asks.limit {
164 result.push(*level);
165 }
166 }
167
168 result
169 }
170
171 #[inline]
172 pub fn midprice(&self) -> Option<f64> {
173 if let (Some(best_bid), Some(best_ask)) = (self.best_bid, self.best_ask) {
174 return Some((best_bid.price + best_ask.price) / 2.0);
175 }
176
177 None
178 }
179
180 #[inline]
181 pub fn weighted_midprice(&self) -> Option<f64> {
182 if let (Some(best_bid), Some(best_ask)) = (self.best_bid, self.best_ask) {
183 let num = best_bid.size * best_ask.price + best_bid.price * best_ask.size;
184 let den = best_bid.size + best_ask.size;
185 return Some(num / den);
186 }
187
188 None
189 }
190}
191
192#[derive(Debug, Clone)]
193pub struct Buffer {
194 buf: [Level; 500],
195 limit: f64,
196}
197
198impl Buffer {
199 pub fn new(is_bid: bool) -> Self {
200 Self {
201 buf: if is_bid {
202 [Level::minimum(); 500]
203 } else {
204 [Level::maximum(); 500]
205 },
206 limit: if is_bid { f64::MIN } else { f64::MAX },
207 }
208 }
209
210 #[inline]
211 pub fn find_index_bids(&self, target: f64) -> Result<usize, usize> {
212 let mut size = self.buf.len();
213 let mut left = 0;
214 let mut right = size;
215
216 while left < right {
217 let mid = left + size / 4;
218 let cur = self.get(mid);
219
220 if target > cur.price || cur.price == self.limit {
221 right = mid;
222 } else if target < cur.price {
223 left = mid + 1;
224 } else {
225 if mid >= self.buf.len() {
226 unsafe { unreachable_unchecked() }
227 }
228 return Ok(mid);
229 }
230
231 size = right - left;
232 }
233 if left > self.buf.len() {
234 unsafe { unreachable_unchecked() }
235 }
236 Err(left)
237 }
238
239 #[inline]
240 pub fn find_index_asks(&self, target: f64) -> Result<usize, usize> {
241 let mut size = self.buf.len();
242 let mut left = 0;
243 let mut right = size;
244
245 while left < right {
246 let mid = left + size / 4;
247 let cur = self.get(mid);
248
249 if target < cur.price || cur.price == self.limit {
250 right = mid;
251 } else if target > cur.price {
252 left = mid + 1;
253 } else {
254 if mid >= self.buf.len() {
255 unsafe { unreachable_unchecked() }
256 }
257 return Ok(mid);
258 }
259
260 size = right - left;
261 }
262 if left > self.buf.len() {
263 unsafe { unreachable_unchecked() }
264 }
265 Err(left)
266 }
267
268 #[inline]
269 fn move_back(&mut self, start: usize) {
270 let mut next = start + 1;
271
272 while next < self.buf.len() {
273 let lvl = self.get(next);
274 if lvl.price == self.limit {
275 break;
276 }
277 self.buf.swap(next - 1, next);
278
279 next += 1;
280 }
281 }
282
283 #[inline]
284 pub fn remove(&mut self, index: usize) -> f64 {
285 let na = self.limit;
286 let level = self.get_mut(index);
287 let removed = level.price;
288 level.price = na;
289 level.size = 0.0;
290
291 self.move_back(index);
292
293 removed
294 }
295
296 pub fn first(&self) -> Option<Level> {
297 self.buf
298 .into_iter()
299 .find(|&level| level.price != self.limit)
300 }
301
302 pub fn get(&self, index: usize) -> &Level {
303 unsafe { self.buf.get_unchecked(index) }
304 }
305
306 pub fn get_mut(&mut self, index: usize) -> &mut Level {
307 unsafe { self.buf.get_unchecked_mut(index) }
308 }
309
310 pub fn insert(&mut self, index: usize, level: Level) {
311 if index >= self.buf.len() {
312 return;
313 }
314 let to_replace = self.get_mut(index);
315 let mut replaced = replace(to_replace, level);
316 if replaced.price == self.limit {
317 return;
318 }
319 let mut next = index + 1;
320
321 while next < self.buf.len() {
322 if replaced.price == self.limit {
323 break;
324 }
325
326 replaced = replace(self.get_mut(next), replaced);
327
328 next += 1;
329 }
330 }
331
332 pub fn modify(&mut self, index: usize, size: f64) {
333 if index >= self.buf.len() {
334 return;
335 }
336 let level = self.get_mut(index);
337 level.size = size;
338 }
339}
340
341#[cfg(test)]
342mod tests {
343 use super::*;
344
345 #[test]
346 fn process_lvl2_bids() {
347 let mut ob = Orderbook::new();
348
349 let event = Event {
350 timestamp: 0,
351 seq: 0,
352 is_trade: false,
353 is_buy: true,
354 price: 16.0,
355 size: 1.0,
356 };
357
358 ob.process(event);
359
360 assert_eq!(
361 ob.top_bids(5),
362 [Level {
363 price: 16.0,
364 size: 1.0
365 },]
366 );
367
368 let event = Event {
369 timestamp: 0,
370 seq: 0,
371 is_trade: false,
372 is_buy: true,
373 price: 7.0,
374 size: 1.0,
375 };
376 ob.process(event);
377
378 assert_eq!(
379 ob.top_bids(5),
380 [
381 Level {
382 price: 16.0,
383 size: 1.0
384 },
385 Level {
386 price: 7.0,
387 size: 1.0
388 },
389 ]
390 );
391
392 let event = Event {
393 timestamp: 0,
394 seq: 0,
395 is_trade: false,
396 is_buy: true,
397 price: 10.0,
398 size: 1.0,
399 };
400 ob.process(event);
401
402 assert_eq!(
403 ob.top_bids(5),
404 [
405 Level {
406 price: 16.0,
407 size: 1.0
408 },
409 Level {
410 price: 10.0,
411 size: 1.0
412 },
413 Level {
414 price: 7.0,
415 size: 1.0
416 },
417 ]
418 );
419
420 let event = Event {
421 timestamp: 0,
422 seq: 0,
423 is_trade: false,
424 is_buy: true,
425 price: 8.0,
426 size: 1.0,
427 };
428 ob.process(event);
429
430 assert_eq!(
431 ob.top_bids(5),
432 [
433 Level {
434 price: 16.0,
435 size: 1.0
436 },
437 Level {
438 price: 10.0,
439 size: 1.0
440 },
441 Level {
442 price: 8.0,
443 size: 1.0
444 },
445 Level {
446 price: 7.0,
447 size: 1.0
448 },
449 ]
450 );
451
452 let event = Event {
453 timestamp: 0,
454 seq: 0,
455 is_trade: false,
456 is_buy: true,
457 price: 8.0,
458 size: 2.0,
459 };
460 ob.process(event);
461
462 assert_eq!(
463 ob.top_bids(5),
464 [
465 Level {
466 price: 16.0,
467 size: 1.0
468 },
469 Level {
470 price: 10.0,
471 size: 1.0
472 },
473 Level {
474 price: 8.0,
475 size: 2.0
476 },
477 Level {
478 price: 7.0,
479 size: 1.0
480 },
481 ]
482 );
483
484 let event = Event {
485 timestamp: 0,
486 seq: 0,
487 is_trade: false,
488 is_buy: true,
489 price: 12.0,
490 size: 1.0,
491 };
492 ob.process(event);
493
494 assert_eq!(
495 ob.top_bids(5),
496 [
497 Level {
498 price: 16.0,
499 size: 1.0
500 },
501 Level {
502 price: 12.0,
503 size: 1.0
504 },
505 Level {
506 price: 10.0,
507 size: 1.0
508 },
509 Level {
510 price: 8.0,
511 size: 2.0
512 },
513 Level {
514 price: 7.0,
515 size: 1.0
516 },
517 ]
518 );
519
520 let event = Event {
521 timestamp: 0,
522 seq: 0,
523 is_trade: false,
524 is_buy: true,
525 price: 21.0,
526 size: 1.0,
527 };
528 ob.process(event);
529
530 assert_eq!(
531 ob.top_bids(5),
532 [
533 Level {
534 price: 21.0,
535 size: 1.0
536 },
537 Level {
538 price: 16.0,
539 size: 1.0
540 },
541 Level {
542 price: 12.0,
543 size: 1.0
544 },
545 Level {
546 price: 10.0,
547 size: 1.0
548 },
549 Level {
550 price: 8.0,
551 size: 2.0
552 },
553 ]
554 );
555
556 let event = Event {
557 timestamp: 0,
558 seq: 0,
559 is_trade: false,
560 is_buy: true,
561 price: 8.0,
562 size: 0.0,
563 };
564 ob.process(event);
565
566 assert_eq!(
567 ob.top_bids(5),
568 [
569 Level {
570 price: 21.0,
571 size: 1.0
572 },
573 Level {
574 price: 16.0,
575 size: 1.0
576 },
577 Level {
578 price: 12.0,
579 size: 1.0
580 },
581 Level {
582 price: 10.0,
583 size: 1.0
584 },
585 Level {
586 price: 7.0,
587 size: 1.0
588 },
589 ]
590 );
591
592 let event = Event {
593 timestamp: 0,
594 seq: 0,
595 is_trade: false,
596 is_buy: true,
597 price: 8.0,
598 size: 10.0,
599 };
600 ob.process(event);
601
602 assert_eq!(
603 ob.top_bids(5),
604 [
605 Level {
606 price: 21.0,
607 size: 1.0
608 },
609 Level {
610 price: 16.0,
611 size: 1.0
612 },
613 Level {
614 price: 12.0,
615 size: 1.0
616 },
617 Level {
618 price: 10.0,
619 size: 1.0
620 },
621 Level {
622 price: 8.0,
623 size: 10.0
624 },
625 ]
626 );
627
628 let event = Event {
629 timestamp: 0,
630 seq: 0,
631 is_trade: false,
632 is_buy: true,
633 price: 21.0,
634 size: 0.0,
635 };
636 ob.process(event);
637
638 assert_eq!(
639 ob.top_bids(5),
640 [
641 Level {
642 price: 16.0,
643 size: 1.0
644 },
645 Level {
646 price: 12.0,
647 size: 1.0
648 },
649 Level {
650 price: 10.0,
651 size: 1.0
652 },
653 Level {
654 price: 8.0,
655 size: 10.0
656 },
657 Level {
658 price: 7.0,
659 size: 1.0
660 },
661 ]
662 );
663 }
664
665 #[test]
666 fn process_lvl2_asks() {
667 let mut ob = Orderbook::new();
668
669 let event = Event {
670 timestamp: 0,
671 seq: 0,
672 is_trade: false,
673 is_buy: false,
674 price: 16.0,
675 size: 1.0,
676 };
677 ob.process(event);
678
679 assert_eq!(
680 ob.top_asks(5),
681 [Level {
682 price: 16.0,
683 size: 1.0
684 },]
685 );
686
687 let event = Event {
688 timestamp: 0,
689 seq: 0,
690 is_trade: false,
691 is_buy: false,
692 price: 7.0,
693 size: 1.0,
694 };
695 ob.process(event);
696
697 assert_eq!(
698 ob.top_asks(5),
699 [
700 Level {
701 price: 7.0,
702 size: 1.0
703 },
704 Level {
705 price: 16.0,
706 size: 1.0
707 },
708 ]
709 );
710
711 let event = Event {
712 timestamp: 0,
713 seq: 0,
714 is_trade: false,
715 is_buy: false,
716 price: 10.0,
717 size: 1.0,
718 };
719 ob.process(event);
720
721 assert_eq!(
722 ob.top_asks(5),
723 [
724 Level {
725 price: 7.0,
726 size: 1.0
727 },
728 Level {
729 price: 10.0,
730 size: 1.0
731 },
732 Level {
733 price: 16.0,
734 size: 1.0
735 },
736 ]
737 );
738
739 let event = Event {
740 timestamp: 0,
741 seq: 0,
742 is_trade: false,
743 is_buy: false,
744 price: 6.0,
745 size: 1.0,
746 };
747 ob.process(event);
748
749 assert_eq!(
750 ob.top_asks(5),
751 [
752 Level {
753 price: 6.0,
754 size: 1.0
755 },
756 Level {
757 price: 7.0,
758 size: 1.0
759 },
760 Level {
761 price: 10.0,
762 size: 1.0
763 },
764 Level {
765 price: 16.0,
766 size: 1.0
767 },
768 ]
769 );
770
771 let event = Event {
772 timestamp: 0,
773 seq: 0,
774 is_trade: false,
775 is_buy: false,
776 price: 8.0,
777 size: 2.0,
778 };
779 ob.process(event);
780
781 assert_eq!(
782 ob.top_asks(5),
783 [
784 Level {
785 price: 6.0,
786 size: 1.0
787 },
788 Level {
789 price: 7.0,
790 size: 1.0
791 },
792 Level {
793 price: 8.0,
794 size: 2.0
795 },
796 Level {
797 price: 10.0,
798 size: 1.0
799 },
800 Level {
801 price: 16.0,
802 size: 1.0
803 },
804 ]
805 );
806
807 let event = Event {
808 timestamp: 0,
809 seq: 0,
810 is_trade: false,
811 is_buy: false,
812 price: 50.0,
813 size: 1.0,
814 };
815 ob.process(event);
816
817 assert_eq!(
818 ob.top_asks(5),
819 [
820 Level {
821 price: 6.0,
822 size: 1.0
823 },
824 Level {
825 price: 7.0,
826 size: 1.0
827 },
828 Level {
829 price: 8.0,
830 size: 2.0
831 },
832 Level {
833 price: 10.0,
834 size: 1.0
835 },
836 Level {
837 price: 16.0,
838 size: 1.0
839 },
840 ]
841 );
842
843 let event = Event {
844 timestamp: 0,
845 seq: 0,
846 is_trade: false,
847 is_buy: false,
848 price: 6.0,
849 size: 0.0,
850 };
851 ob.process(event);
852
853 assert_eq!(
854 ob.top_asks(5),
855 [
856 Level {
857 price: 7.0,
858 size: 1.0
859 },
860 Level {
861 price: 8.0,
862 size: 2.0
863 },
864 Level {
865 price: 10.0,
866 size: 1.0
867 },
868 Level {
869 price: 16.0,
870 size: 1.0
871 },
872 Level {
873 price: 50.0,
874 size: 1.0
875 },
876 ]
877 );
878
879 let event = Event {
880 timestamp: 0,
881 seq: 0,
882 is_trade: false,
883 is_buy: false,
884 price: 8.0,
885 size: 0.0,
886 };
887 ob.process(event);
888
889 assert_eq!(
890 ob.top_asks(5),
891 [
892 Level {
893 price: 7.0,
894 size: 1.0
895 },
896 Level {
897 price: 10.0,
898 size: 1.0
899 },
900 Level {
901 price: 16.0,
902 size: 1.0
903 },
904 Level {
905 price: 50.0,
906 size: 1.0
907 },
908 ]
909 );
910 }
911
912 #[test]
913 fn process_all_asks() {
914 let mut ob = Orderbook::new();
915
916 let event = Event {
917 timestamp: 0,
918 seq: 0,
919 is_trade: false,
920 is_buy: false,
921 price: 11.0,
922 size: 1.0,
923 };
924 ob.process(event);
925
926 let event = Event {
927 timestamp: 0,
928 seq: 0,
929 is_trade: false,
930 is_buy: false,
931 price: 10.0,
932 size: 1.0,
933 };
934 ob.process(event);
935
936 let event = Event {
937 timestamp: 0,
938 seq: 0,
939 is_trade: false,
940 is_buy: false,
941 price: 9.0,
942 size: 1.0,
943 };
944 ob.process(event);
945
946 let event = Event {
947 timestamp: 0,
948 seq: 0,
949 is_trade: true,
950 is_buy: false,
951 price: 9.0,
952 size: 0.5,
953 };
954 ob.process(event);
955
956 assert_eq!(
957 ob.top_asks(3),
958 [
959 Level {
960 price: 9.0,
961 size: 0.5
962 },
963 Level {
964 price: 10.0,
965 size: 1.0
966 },
967 Level {
968 price: 11.0,
969 size: 1.0
970 },
971 ]
972 );
973
974 let event = Event {
975 timestamp: 0,
976 seq: 0,
977 is_trade: true,
978 is_buy: false,
979 price: 9.0,
980 size: 0.9,
981 };
982 ob.process(event);
983
984 assert_eq!(
985 ob.top_asks(3),
986 [
987 Level {
988 price: 10.0,
989 size: 1.0
990 },
991 Level {
992 price: 11.0,
993 size: 1.0
994 },
995 ]
996 );
997 }
998
999 #[test]
1000 fn old_event() {
1001 let mut ob = Orderbook::new();
1002
1003 let event = Event {
1004 timestamp: 0,
1005 seq: 0,
1006 is_trade: false,
1007 is_buy: false,
1008 price: 11.0,
1009 size: 1.0,
1010 };
1011 ob.process(event);
1012
1013 let event = Event {
1014 timestamp: 1,
1015 seq: 0,
1016 is_trade: false,
1017 is_buy: false,
1018 price: 10.0,
1019 size: 1.0,
1020 };
1021 ob.process(event);
1022
1023 let event = Event {
1024 timestamp: 0,
1025 seq: 0,
1026 is_trade: false,
1027 is_buy: false,
1028 price: 9.0,
1029 size: 1.0,
1030 };
1031 ob.process(event);
1032
1033 let event = Event {
1034 timestamp: 0,
1035 seq: 0,
1036 is_trade: true,
1037 is_buy: false,
1038 price: 8.0,
1039 size: 1.0,
1040 };
1041 ob.process(event);
1042
1043 assert_eq!(
1044 ob.best_ask.unwrap(),
1045 Level {
1046 price: 10.0,
1047 size: 1.0
1048 }
1049 )
1050 }
1051
1052 #[test]
1053 fn process_stream_bbo() {
1054 let mut ob = Orderbook::new();
1055
1056 let event = Event {
1057 timestamp: 0,
1058 seq: 0,
1059 is_trade: false,
1060 is_buy: true,
1061 price: 16.0,
1062 size: 1.0,
1063 };
1064
1065 ob.process(event);
1066
1067 let event = Event {
1068 timestamp: 0,
1069 seq: 0,
1070 is_trade: false,
1071 is_buy: true,
1072 price: 20.0,
1073 size: 1.0,
1074 };
1075
1076 ob.process(event);
1077
1078 let event = Event {
1079 timestamp: 0,
1080 seq: 0,
1081 is_trade: false,
1082 is_buy: false,
1083 price: 22.0,
1084 size: 1.0,
1085 };
1086
1087 ob.process(event);
1088
1089 let event = Event {
1090 timestamp: 0,
1091 seq: 0,
1092 is_trade: false,
1093 is_buy: false,
1094 price: 21.0,
1095 size: 1.0,
1096 };
1097
1098 let (best_bid, best_ask) = ob.process_stream_bbo(event).unwrap();
1099
1100 assert_eq!(
1101 best_bid.unwrap(),
1102 Level {
1103 price: 20.0,
1104 size: 1.0
1105 }
1106 );
1107
1108 assert_eq!(
1109 best_ask.unwrap(),
1110 Level {
1111 price: 21.0,
1112 size: 1.0
1113 }
1114 );
1115
1116 let event = Event {
1117 timestamp: 0,
1118 seq: 0,
1119 is_trade: false,
1120 is_buy: false,
1121 price: 23.0,
1122 size: 1.0,
1123 };
1124
1125 assert_eq!(ob.process_stream_bbo(event), None);
1126 }
1127
1128 #[test]
1129 fn remove_non_existing_level_with_trade() {
1130 let mut ob = Orderbook::new();
1131
1132 let event = Event {
1133 timestamp: 0,
1134 seq: 0,
1135 is_trade: false,
1136 is_buy: true,
1137 price: 16.0,
1138 size: 1.0,
1139 };
1140
1141 ob.process(event);
1142
1143 let event = Event {
1144 timestamp: 0,
1145 seq: 0,
1146 is_trade: false,
1147 is_buy: false,
1148 price: 20.0,
1149 size: 1.0,
1150 };
1151
1152 ob.process(event);
1153
1154 let event = Event {
1155 timestamp: 0,
1156 seq: 0,
1157 is_trade: true,
1158 is_buy: true,
1159 price: 12.0,
1160 size: 1.0,
1161 };
1162
1163 ob.process(event);
1164
1165 let event = Event {
1166 timestamp: 0,
1167 seq: 0,
1168 is_trade: true,
1169 is_buy: false,
1170 price: 22.0,
1171 size: 1.0,
1172 };
1173
1174 ob.process(event);
1175
1176 assert_eq!(
1177 ob.best_bid().unwrap(),
1178 Level {
1179 price: 16.0,
1180 size: 1.0
1181 }
1182 );
1183
1184 assert_eq!(
1185 ob.best_ask().unwrap(),
1186 Level {
1187 price: 20.0,
1188 size: 1.0
1189 }
1190 );
1191 }
1192
1193 #[test]
1194 fn midprice() {
1195 let mut ob = Orderbook::new();
1196
1197 let event = Event {
1198 timestamp: 0,
1199 seq: 0,
1200 is_trade: false,
1201 is_buy: true,
1202 price: 16.0,
1203 size: 1.0,
1204 };
1205
1206 ob.process(event);
1207
1208 assert_eq!(ob.midprice(), None);
1209
1210 let event = Event {
1211 timestamp: 0,
1212 seq: 0,
1213 is_trade: false,
1214 is_buy: false,
1215 price: 20.0,
1216 size: 1.0,
1217 };
1218
1219 ob.process(event);
1220
1221 let midprice = ob.midprice().unwrap();
1222
1223 assert_eq!(midprice, 18.0)
1224 }
1225
1226 #[test]
1227 fn weighted_midprice() {
1228 let mut ob = Orderbook::new();
1229
1230 let event = Event {
1231 timestamp: 0,
1232 seq: 0,
1233 is_trade: false,
1234 is_buy: true,
1235 price: 16.0,
1236 size: 1.0,
1237 };
1238
1239 ob.process(event);
1240
1241 assert_eq!(ob.weighted_midprice(), None);
1242
1243 let event = Event {
1244 timestamp: 0,
1245 seq: 0,
1246 is_trade: false,
1247 is_buy: false,
1248 price: 20.0,
1249 size: 4.0,
1250 };
1251
1252 ob.process(event);
1253
1254 let weighted_midprice = ob.weighted_midprice().unwrap();
1255
1256 assert_eq!(weighted_midprice, 16.8)
1257 }
1258}