ninjabook/
fixed_orderbook.rs

1use std::{hint::unreachable_unchecked, mem::replace};
2
3use crate::{event::Event, level::Level};
4
5/// Implementation of an orderbook with fixed size to use as a benchmark
6/// This has no use other than benchmarking.
7#[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}