nautilus_model/ffi/orderbook/
book.rs1use std::{
17 ffi::c_char,
18 ops::{Deref, DerefMut},
19};
20
21use nautilus_core::ffi::{cvec::CVec, string::str_to_cstr};
22
23use super::level::BookLevel_API;
24use crate::{
25 data::{
26 BookOrder, OrderBookDelta, OrderBookDeltas_API, OrderBookDepth10, QuoteTick, TradeTick,
27 },
28 enums::{BookType, OrderSide},
29 identifiers::InstrumentId,
30 orderbook::{OrderBook, analysis::book_check_integrity},
31 types::{Price, Quantity},
32};
33
34#[repr(C)]
43#[derive(Debug)]
44#[allow(non_camel_case_types)]
45pub struct OrderBook_API(Box<OrderBook>);
46
47impl Deref for OrderBook_API {
48 type Target = OrderBook;
49
50 fn deref(&self) -> &Self::Target {
51 &self.0
52 }
53}
54
55impl DerefMut for OrderBook_API {
56 fn deref_mut(&mut self) -> &mut Self::Target {
57 &mut self.0
58 }
59}
60
61#[unsafe(no_mangle)]
62pub extern "C" fn orderbook_new(instrument_id: InstrumentId, book_type: BookType) -> OrderBook_API {
63 OrderBook_API(Box::new(OrderBook::new(instrument_id, book_type)))
64}
65
66#[unsafe(no_mangle)]
67pub extern "C" fn orderbook_drop(book: OrderBook_API) {
68 drop(book); }
70
71#[unsafe(no_mangle)]
72pub extern "C" fn orderbook_reset(book: &mut OrderBook_API) {
73 book.reset();
74}
75
76#[unsafe(no_mangle)]
77pub extern "C" fn orderbook_instrument_id(book: &OrderBook_API) -> InstrumentId {
78 book.instrument_id
79}
80
81#[unsafe(no_mangle)]
82pub extern "C" fn orderbook_book_type(book: &OrderBook_API) -> BookType {
83 book.book_type
84}
85
86#[unsafe(no_mangle)]
87pub extern "C" fn orderbook_sequence(book: &OrderBook_API) -> u64 {
88 book.sequence
89}
90
91#[unsafe(no_mangle)]
92pub extern "C" fn orderbook_ts_last(book: &OrderBook_API) -> u64 {
93 book.ts_last.into()
94}
95
96#[unsafe(no_mangle)]
97pub extern "C" fn orderbook_update_count(book: &OrderBook_API) -> u64 {
98 book.update_count
99}
100
101#[unsafe(no_mangle)]
102#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
103pub extern "C" fn orderbook_add(
104 book: &mut OrderBook_API,
105 order: BookOrder,
106 flags: u8,
107 sequence: u64,
108 ts_event: u64,
109) {
110 book.add(order, flags, sequence, ts_event.into());
111}
112
113#[unsafe(no_mangle)]
114#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
115pub extern "C" fn orderbook_update(
116 book: &mut OrderBook_API,
117 order: BookOrder,
118 flags: u8,
119 sequence: u64,
120 ts_event: u64,
121) {
122 book.update(order, flags, sequence, ts_event.into());
123}
124
125#[unsafe(no_mangle)]
126#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
127pub extern "C" fn orderbook_delete(
128 book: &mut OrderBook_API,
129 order: BookOrder,
130 flags: u8,
131 sequence: u64,
132 ts_event: u64,
133) {
134 book.delete(order, flags, sequence, ts_event.into());
135}
136
137#[unsafe(no_mangle)]
138pub extern "C" fn orderbook_clear(book: &mut OrderBook_API, sequence: u64, ts_event: u64) {
139 book.clear(sequence, ts_event.into());
140}
141
142#[unsafe(no_mangle)]
143pub extern "C" fn orderbook_clear_bids(book: &mut OrderBook_API, sequence: u64, ts_event: u64) {
144 book.clear_bids(sequence, ts_event.into());
145}
146
147#[unsafe(no_mangle)]
148pub extern "C" fn orderbook_clear_asks(book: &mut OrderBook_API, sequence: u64, ts_event: u64) {
149 book.clear_asks(sequence, ts_event.into());
150}
151
152#[unsafe(no_mangle)]
153pub extern "C" fn orderbook_apply_delta(book: &mut OrderBook_API, delta: &OrderBookDelta) {
154 if let Err(e) = book.apply_delta_unchecked(delta) {
155 log::error!("Failed to apply order book delta: {e}");
156 }
157}
158
159#[unsafe(no_mangle)]
160pub extern "C" fn orderbook_apply_deltas(book: &mut OrderBook_API, deltas: &OrderBookDeltas_API) {
161 if let Err(e) = book.apply_deltas_unchecked(deltas.deref()) {
163 log::error!("Failed to apply order book deltas: {e}");
164 }
165}
166
167#[unsafe(no_mangle)]
183pub extern "C" fn orderbook_to_snapshot_deltas(
184 book: &OrderBook_API,
185 ts_event: u64,
186 ts_init: u64,
187) -> OrderBookDeltas_API {
188 use nautilus_core::UnixNanos;
189 OrderBookDeltas_API::new(book.to_deltas(UnixNanos::from(ts_event), UnixNanos::from(ts_init)))
190}
191
192#[unsafe(no_mangle)]
193pub extern "C" fn orderbook_apply_depth(book: &mut OrderBook_API, depth: &OrderBookDepth10) {
194 if let Err(e) = book.apply_depth_unchecked(depth) {
195 log::error!("Failed to apply order book depth: {e}");
196 }
197}
198
199#[unsafe(no_mangle)]
200pub extern "C" fn orderbook_bids(book: &mut OrderBook_API) -> CVec {
201 book.bids
202 .levels
203 .values()
204 .map(|level| BookLevel_API::new(level.clone()))
205 .collect::<Vec<BookLevel_API>>()
206 .into()
207}
208
209#[unsafe(no_mangle)]
210pub extern "C" fn orderbook_asks(book: &mut OrderBook_API) -> CVec {
211 book.asks
212 .levels
213 .values()
214 .map(|level| BookLevel_API::new(level.clone()))
215 .collect::<Vec<BookLevel_API>>()
216 .into()
217}
218
219#[unsafe(no_mangle)]
220pub extern "C" fn orderbook_has_bid(book: &mut OrderBook_API) -> u8 {
221 u8::from(book.has_bid())
222}
223
224#[unsafe(no_mangle)]
225pub extern "C" fn orderbook_has_ask(book: &mut OrderBook_API) -> u8 {
226 u8::from(book.has_ask())
227}
228
229#[unsafe(no_mangle)]
233#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
234pub extern "C" fn orderbook_best_bid_price(book: &mut OrderBook_API) -> Price {
235 book.best_bid_price()
236 .expect("Error: No bid orders for best bid price")
237}
238
239#[unsafe(no_mangle)]
243#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
244pub extern "C" fn orderbook_best_ask_price(book: &mut OrderBook_API) -> Price {
245 book.best_ask_price()
246 .expect("Error: No ask orders for best ask price")
247}
248
249#[unsafe(no_mangle)]
253#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
254pub extern "C" fn orderbook_best_bid_size(book: &mut OrderBook_API) -> Quantity {
255 book.best_bid_size()
256 .expect("Error: No bid orders for best bid size")
257}
258
259#[unsafe(no_mangle)]
263#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
264pub extern "C" fn orderbook_best_ask_size(book: &mut OrderBook_API) -> Quantity {
265 book.best_ask_size()
266 .expect("Error: No ask orders for best ask size")
267}
268
269#[unsafe(no_mangle)]
273pub extern "C" fn orderbook_spread(book: &mut OrderBook_API) -> f64 {
274 book.spread()
275 .expect("Error: Unable to calculate `spread` (no bid or ask)")
276}
277
278#[unsafe(no_mangle)]
282pub extern "C" fn orderbook_midpoint(book: &mut OrderBook_API) -> f64 {
283 book.midpoint()
284 .expect("Error: Unable to calculate `midpoint` (no bid or ask)")
285}
286
287#[unsafe(no_mangle)]
288#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
289pub extern "C" fn orderbook_get_avg_px_for_quantity(
290 book: &mut OrderBook_API,
291 qty: Quantity,
292 order_side: OrderSide,
293) -> f64 {
294 book.get_avg_px_for_quantity(qty, order_side)
295}
296
297#[unsafe(no_mangle)]
298#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
299pub extern "C" fn orderbook_get_quantity_for_price(
300 book: &mut OrderBook_API,
301 price: Price,
302 order_side: OrderSide,
303) -> f64 {
304 book.get_quantity_for_price(price, order_side)
305}
306
307#[unsafe(no_mangle)]
308#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
309pub extern "C" fn orderbook_get_quantity_at_level(
310 book: &OrderBook_API,
311 price: Price,
312 order_side: OrderSide,
313 size_precision: u8,
314) -> Quantity {
315 book.get_quantity_at_level(price, order_side, size_precision)
316}
317
318#[unsafe(no_mangle)]
324pub extern "C" fn orderbook_update_quote_tick(book: &mut OrderBook_API, quote: &QuoteTick) {
325 book.update_quote_tick(quote).unwrap();
326}
327
328#[unsafe(no_mangle)]
334pub extern "C" fn orderbook_update_trade_tick(book: &mut OrderBook_API, trade: &TradeTick) {
335 book.update_trade_tick(trade).unwrap();
336}
337
338#[unsafe(no_mangle)]
339#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
340pub extern "C" fn orderbook_simulate_fills(book: &OrderBook_API, order: BookOrder) -> CVec {
341 book.simulate_fills(&order).into()
342}
343
344#[unsafe(no_mangle)]
345#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
346pub extern "C" fn orderbook_get_all_crossed_levels(
347 book: &OrderBook_API,
348 order_side: OrderSide,
349 price: Price,
350 size_precision: u8,
351) -> CVec {
352 book.get_all_crossed_levels(order_side, price, size_precision)
353 .into()
354}
355
356#[unsafe(no_mangle)]
357pub extern "C" fn orderbook_check_integrity(book: &OrderBook_API) -> u8 {
358 u8::from(book_check_integrity(book).is_ok())
359}
360
361#[unsafe(no_mangle)]
362pub extern "C" fn vec_drop_fills(v: CVec) {
363 if v.ptr.is_null() {
364 return;
365 }
366
367 let CVec { ptr, len, cap } = v;
368 let data: Vec<(Price, Quantity)> =
369 unsafe { Vec::from_raw_parts(ptr.cast::<(Price, Quantity)>(), len, cap) };
370 drop(data); }
372
373#[unsafe(no_mangle)]
375pub extern "C" fn orderbook_pprint_to_cstr(
376 book: &OrderBook_API,
377 num_levels: usize,
378) -> *const c_char {
379 str_to_cstr(&book.pprint(num_levels, None))
380}