nautilus_model/orderbook/
display.rs1use tabled::{Table, Tabled, settings::Style};
19
20use super::{
21 BookLevel, BookPrice,
22 own::{OwnBookLadder, OwnBookLevel},
23};
24use crate::orderbook::ladder::BookLadder;
25
26#[derive(Tabled)]
27struct BookLevelDisplay {
28 bids: String,
29 price: String,
30 asks: String,
31}
32
33#[must_use]
35pub(crate) fn pprint_book(bids: &BookLadder, asks: &BookLadder, num_levels: usize) -> String {
36 let ask_levels: Vec<(&BookPrice, &BookLevel)> =
37 asks.levels.iter().take(num_levels).rev().collect();
38 let bid_levels: Vec<(&BookPrice, &BookLevel)> = bids.levels.iter().take(num_levels).collect();
39 let levels: Vec<(&BookPrice, &BookLevel)> = ask_levels.into_iter().chain(bid_levels).collect();
40
41 let data: Vec<BookLevelDisplay> = levels
42 .iter()
43 .map(|(book_price, level)| {
44 let is_bid_level = bids.levels.contains_key(book_price);
45 let is_ask_level = asks.levels.contains_key(book_price);
46
47 let bid_sizes: Vec<String> = level
48 .orders
49 .iter()
50 .filter(|_| is_bid_level)
51 .map(|order| format!("{}", order.1.size))
52 .collect();
53
54 let ask_sizes: Vec<String> = level
55 .orders
56 .iter()
57 .filter(|_| is_ask_level)
58 .map(|order| format!("{}", order.1.size))
59 .collect();
60
61 BookLevelDisplay {
62 bids: if bid_sizes.is_empty() {
63 String::new()
64 } else {
65 format!("[{}]", bid_sizes.join(", "))
66 },
67 price: format!("{}", level.price),
68 asks: if ask_sizes.is_empty() {
69 String::new()
70 } else {
71 format!("[{}]", ask_sizes.join(", "))
72 },
73 }
74 })
75 .collect();
76
77 let table = Table::new(data).with(Style::rounded()).to_string();
78
79 let header = format!(
80 "bid_levels: {}\nask_levels: {}",
81 bids.levels.len(),
82 asks.levels.len()
83 );
84
85 format!("{}\n{}", header, table)
86}
87
88#[must_use]
91pub(crate) fn pprint_own_book(
92 bids: &OwnBookLadder,
93 asks: &OwnBookLadder,
94 num_levels: usize,
95) -> String {
96 let ask_levels: Vec<(&BookPrice, &OwnBookLevel)> =
97 asks.levels.iter().take(num_levels).rev().collect();
98 let bid_levels: Vec<(&BookPrice, &OwnBookLevel)> =
99 bids.levels.iter().take(num_levels).collect();
100 let levels: Vec<(&BookPrice, &OwnBookLevel)> =
101 ask_levels.into_iter().chain(bid_levels).collect();
102
103 let data: Vec<BookLevelDisplay> = levels
104 .iter()
105 .map(|(book_price, level)| {
106 let is_bid_level = bids.levels.contains_key(book_price);
107 let is_ask_level = asks.levels.contains_key(book_price);
108
109 let bid_sizes: Vec<String> = level
110 .orders
111 .iter()
112 .filter(|_| is_bid_level)
113 .map(|order| format!("{}", order.1.size))
114 .collect();
115
116 let ask_sizes: Vec<String> = level
117 .orders
118 .iter()
119 .filter(|_| is_ask_level)
120 .map(|order| format!("{}", order.1.size))
121 .collect();
122
123 BookLevelDisplay {
124 bids: if bid_sizes.is_empty() {
125 String::new()
126 } else {
127 format!("[{}]", bid_sizes.join(", "))
128 },
129 price: format!("{}", level.price),
130 asks: if ask_sizes.is_empty() {
131 String::new()
132 } else {
133 format!("[{}]", ask_sizes.join(", "))
134 },
135 }
136 })
137 .collect();
138
139 let table = Table::new(data).with(Style::rounded()).to_string();
140
141 let header = format!(
142 "bid_levels: {}\nask_levels: {}",
143 bids.levels.len(),
144 asks.levels.len()
145 );
146
147 format!("{}\n{}", header, table)
148}