From 08fb35b8ff00182d536e251074e6df6b1b26f953 Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 12:48:10 -0600 Subject: [PATCH 1/8] wip --- orderbook/Cargo.lock | 284 +++++++++++++++++++++++++++++++++++++++++++ orderbook/Cargo.toml | 4 +- orderbook/src/lib.rs | 33 ++--- 3 files changed, 304 insertions(+), 17 deletions(-) create mode 100644 orderbook/Cargo.lock diff --git a/orderbook/Cargo.lock b/orderbook/Cargo.lock new file mode 100644 index 0000000..0720382 --- /dev/null +++ b/orderbook/Cargo.lock @@ -0,0 +1,284 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async-trait" +version = "0.1.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bounded-vec-deque" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2225b558afc76c596898f5f1b3fc35cfce0eb1b13635cbd7d1b2a7177dc10ccd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "orderbook" +version = "0.1.0" +dependencies = [ + "async-trait", + "bounded-vec-deque", + "crossbeam-channel", + "futures", + "ordered-float", + "rustc-hash", + "tracing", + "typed-arena", +] + +[[package]] +name = "ordered-float" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213" +dependencies = [ + "num-traits", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro2" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "syn" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" diff --git a/orderbook/Cargo.toml b/orderbook/Cargo.toml index 54ded79..ac70b06 100644 --- a/orderbook/Cargo.toml +++ b/orderbook/Cargo.toml @@ -6,9 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ring-buffer = { path = "../ring-buffer"} -market-object = { path = "../market-object"} -config = { path = "../config"} crossbeam-channel = "0.5.8" tracing = "0.1.37" rustc-hash = "1.1.0" @@ -16,3 +13,4 @@ async-trait = "0.1.68" futures = "0.3.28" ordered-float = "3.7.0" bounded-vec-deque = "0.1.1" +typed-arena = "2.0.2" diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index ee7bb28..9870547 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -2,10 +2,6 @@ use crossbeam_channel::Sender; use rustc_hash::FxHashMap; use tracing::info; -use config::OrderbookConfig; -use market_object::DepthUpdate; -use ring_buffer::RingBuffer; - use ordered_float::OrderedFloat; use bounded_vec_deque::BoundedVecDeque; @@ -74,13 +70,13 @@ impl Drop for Stack { } } -pub struct OrderBook<'a> { +struct OrderBook<'a> { asks: FxHashMap, Stack>>, bids: FxHashMap, Stack>>, } impl<'a> OrderBook<'a> { - pub fn new(exchange_count: usize, depth: usize, current_price: usize) -> OrderBook<'a> { + fn new(exchange_count: usize, depth: usize, current_price: usize) -> OrderBook<'a> { let ask_level_range: usize = current_price + depth; let mut asks = FxHashMap::, Stack>>::default(); for i in current_price..ask_level_range { @@ -109,19 +105,28 @@ impl<'a> OrderBook<'a> { } bids.insert(OrderedFloat(level), volume_nodes); } - let orderbook_allocation: Arena = Arena::::new(); - let orderbook: OrderBook<'a> = Box::new(OrderBook { + let orderbook: OrderBook<'a> = OrderBook { asks: asks, bids: bids, - }); + }; return orderbook; } + fn update_book(depth_update: DepthUpdate) {} } -#[cfg(test)] -mod tests { - #[test] - fn test_default_order_book() { - let order_book: OrderBook = Default::default(); +pub struct Coordinator<'a> { + order_book: &'a mut OrderBook<'a>, // quote_producer: Receiver, + // depth_update_consumer: Sender, +} + +/* +impl<'a> Coordinator<'a> { + fn new() -> Coordinator<'a> { + let order_book_allocation: &'a mut OrderBook = + Arena::new().alloc(OrderBook::new(2, 5000, 27000)); + Coordinator { + order_book: order_book_allocation, + } } } +*/ From 8ba46c4d55e3d8932e8840076e8019c76961d7cd Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 14:56:23 -0600 Subject: [PATCH 2/8] adds sorting to the orderbook for one side --- orderbook/src/lib.rs | 67 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index 9870547..a727626 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -10,9 +10,13 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; use std::{hint, thread}; +use market_object::DepthUpdate; use std::marker::PhantomData; +use tracing::error; use typed_arena::Arena; +use std::f64::NAN; + pub struct Stack { head: Link, } @@ -26,7 +30,7 @@ struct Node { struct VolumeNode<'a> { volume: f64, - location: f64, + location: u8, _phantom: PhantomData<&'a ()>, } @@ -43,7 +47,6 @@ impl Stack { self.head = Some(new_node); } - pub fn pop(&mut self) -> Option { self.head.take().map(|node| { let node = *node; @@ -51,11 +54,9 @@ impl Stack { node.elem }) } - pub fn peek(&self) -> Option<&T> { self.head.as_ref().map(|node| &node.elem) } - pub fn peek_mut(&mut self) -> Option<&mut T> { self.head.as_mut().map(|node| &mut node.elem) } @@ -71,6 +72,7 @@ impl Drop for Stack { } struct OrderBook<'a> { + exchange_count: usize, asks: FxHashMap, Stack>>, bids: FxHashMap, Stack>>, } @@ -85,7 +87,7 @@ impl<'a> OrderBook<'a> { for _ in 0..exchange_count { volume_nodes.push(VolumeNode { volume: 0.0, - location: 0.0, + location: 0, _phantom: PhantomData, }); } @@ -99,25 +101,74 @@ impl<'a> OrderBook<'a> { for _ in 0..exchange_count { volume_nodes.push(VolumeNode { volume: 0.0, - location: 0.0, + location: 0, _phantom: PhantomData, }); } bids.insert(OrderedFloat(level), volume_nodes); } let orderbook: OrderBook<'a> = OrderBook { + exchange_count: exchange_count, asks: asks, bids: bids, }; return orderbook; } - fn update_book(depth_update: DepthUpdate) {} + fn update_book(&mut self, depth_update: DepthUpdate) { + match depth_update.k { + 0 => { + let mut current_seek: usize = 0; + let max_seek = self.exchange_count; + let level_list = self.asks.get_mut(&OrderedFloat(depth_update.p)).unwrap(); + let mut current_volume = 0.0; + let mut to_insert_volume = depth_update.q; + while current_seek < max_seek + 1 { + match level_list.peek_mut().unwrap().volume > to_insert_volume { + // our incoming depth update is greater then the first volume + // node update it then update the rest of the list + true => { + current_volume = level_list.peek().unwrap().volume; + if to_insert_volume > current_volume { + // to insert is greater then current depth. insert + // then record then update the to insert depth + level_list.peek_mut().unwrap().volume = to_insert_volume; + to_insert_volume = current_volume; + current_seek = current_seek + 1; + } else { + // current insert is not greater then the current + // depth keep pop to the next node in the linked + // list + _ = level_list.pop().unwrap(); + current_seek = current_seek + 1; + } + } + // our incoming depth update is greater then the first. update + // the node. record the the previous volume then go to the next node for + // sorting + false => { + to_insert_volume = level_list.peek_mut().unwrap().volume; + level_list.peek_mut().unwrap().volume = depth_update.q; + _ = level_list.pop().unwrap(); + current_seek = current_seek + 1; + } + } + } + } + 1 => {} + _ => { + error!("undefined depth object received") + } + } + } } +/* pub struct Coordinator<'a> { - order_book: &'a mut OrderBook<'a>, // quote_producer: Receiver, + order_boo +}k: &'a mut OrderBook<'a>, // quote_producer: Receiver, // depth_update_consumer: Sender, } +*/ /* impl<'a> Coordinator<'a> { From f80c85d30afa2c0d088e212fb90a2d54f97d1661 Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 15:06:52 -0600 Subject: [PATCH 3/8] adds location update & bids sorting --- orderbook/Cargo.lock | 846 +++++++++++++++++++++++++++++++++++++++++++ orderbook/Cargo.toml | 1 + orderbook/src/lib.rs | 53 ++- 3 files changed, 899 insertions(+), 1 deletion(-) diff --git a/orderbook/Cargo.lock b/orderbook/Cargo.lock index 0720382..06354f4 100644 --- a/orderbook/Cargo.lock +++ b/orderbook/Cargo.lock @@ -19,18 +19,76 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bounded-vec-deque" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2225b558afc76c596898f5f1b3fc35cfce0eb1b13635cbd7d1b2a7177dc10ccd" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +dependencies = [ + "libc", +] + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -50,6 +108,92 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures" version = "0.3.28" @@ -139,12 +283,161 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "market-object" +version = "0.1.0" +dependencies = [ + "serde", + "serde-this-or-that", + "serde_json", + "smallvec", + "tokio-tungstenite", + "tungstenite", +] + [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -160,6 +453,50 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "openssl" +version = "0.10.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "orderbook" version = "0.1.0" @@ -168,6 +505,7 @@ dependencies = [ "bounded-vec-deque", "crossbeam-channel", "futures", + "market-object", "ordered-float", "rustc-hash", "tracing", @@ -183,6 +521,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -195,6 +539,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.58" @@ -213,12 +569,154 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "0.37.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-this-or-that" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634c5a3cb041e56cc2964386151c67d520f845445789da3bd46bfb1c94f5e3bb" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "slab" version = "0.4.8" @@ -228,6 +726,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "syn" version = "2.0.16" @@ -239,6 +753,93 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +dependencies = [ + "autocfg", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" +dependencies = [ + "futures-util", + "log", + "native-tls", + "tokio", + "tokio-native-tls", + "tungstenite", +] + [[package]] name = "tracing" version = "0.1.37" @@ -271,14 +872,259 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tungstenite" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "native-tls", + "rand", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "typed-arena" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/orderbook/Cargo.toml b/orderbook/Cargo.toml index ac70b06..4a47a59 100644 --- a/orderbook/Cargo.toml +++ b/orderbook/Cargo.toml @@ -14,3 +14,4 @@ futures = "0.3.28" ordered-float = "3.7.0" bounded-vec-deque = "0.1.1" typed-arena = "2.0.2" +market-object = { path = "../market-object"} diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index a727626..63aba76 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -116,11 +116,14 @@ impl<'a> OrderBook<'a> { } fn update_book(&mut self, depth_update: DepthUpdate) { match depth_update.k { + // best deals are defined by how much liquidity at an exchange 0 => { let mut current_seek: usize = 0; let max_seek = self.exchange_count; let level_list = self.asks.get_mut(&OrderedFloat(depth_update.p)).unwrap(); let mut current_volume = 0.0; + let mut current_location = 0; + let mut to_insert_location = 0; let mut to_insert_volume = depth_update.q; while current_seek < max_seek + 1 { match level_list.peek_mut().unwrap().volume > to_insert_volume { @@ -128,11 +131,14 @@ impl<'a> OrderBook<'a> { // node update it then update the rest of the list true => { current_volume = level_list.peek().unwrap().volume; + current_location = level_list.peek_mut().unwrap().location; if to_insert_volume > current_volume { // to insert is greater then current depth. insert // then record then update the to insert depth level_list.peek_mut().unwrap().volume = to_insert_volume; + level_list.peek_mut().unwrap().location = to_insert_location; to_insert_volume = current_volume; + to_insert_location = current_location; current_seek = current_seek + 1; } else { // current insert is not greater then the current @@ -147,6 +153,7 @@ impl<'a> OrderBook<'a> { // sorting false => { to_insert_volume = level_list.peek_mut().unwrap().volume; + to_insert_location = level_list.peek_mut().unwrap().location; level_list.peek_mut().unwrap().volume = depth_update.q; _ = level_list.pop().unwrap(); current_seek = current_seek + 1; @@ -154,7 +161,51 @@ impl<'a> OrderBook<'a> { } } } - 1 => {} + 1 => { + let mut current_seek: usize = 0; + let max_seek = self.exchange_count; + let level_list = self.bids.get_mut(&OrderedFloat(depth_update.p)).unwrap(); + let mut current_volume = 0.0; + let mut current_location = 0; + let mut to_insert_location = 0; + let mut to_insert_volume = depth_update.q; + while current_seek < max_seek + 1 { + match level_list.peek_mut().unwrap().volume > to_insert_volume { + // our incoming depth update is greater then the first volume + // node update it then update the rest of the list + true => { + current_volume = level_list.peek().unwrap().volume; + current_location = level_list.peek_mut().unwrap().location; + if to_insert_volume > current_volume { + // to insert is greater then current depth. insert + // then record then update the to insert depth + level_list.peek_mut().unwrap().volume = to_insert_volume; + level_list.peek_mut().unwrap().location = to_insert_location; + to_insert_volume = current_volume; + to_insert_location = current_location; + current_seek = current_seek + 1; + } else { + // current insert is not greater then the current + // depth keep pop to the next node in the linked + // list + _ = level_list.pop().unwrap(); + current_seek = current_seek + 1; + } + } + // our incoming depth update is greater then the first. update + // the node. record the the previous volume then go to the next node for + // sorting + false => { + to_insert_volume = level_list.peek_mut().unwrap().volume; + to_insert_location = level_list.peek_mut().unwrap().location; + level_list.peek_mut().unwrap().volume = depth_update.q; + _ = level_list.pop().unwrap(); + current_seek = current_seek + 1; + } + } + } + } + _ => { error!("undefined depth object received") } From 4d4f90e57281f023032b3c9cc7001dc8f70d4d5b Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 15:17:34 -0600 Subject: [PATCH 4/8] keep track of closest spread values for quote publishing --- orderbook/src/lib.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index 63aba76..f8a05d3 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -73,6 +73,8 @@ impl Drop for Stack { struct OrderBook<'a> { exchange_count: usize, + best_deal_bids_level: f64, + best_deal_asks_level: f64, asks: FxHashMap, Stack>>, bids: FxHashMap, Stack>>, } @@ -109,6 +111,8 @@ impl<'a> OrderBook<'a> { } let orderbook: OrderBook<'a> = OrderBook { exchange_count: exchange_count, + best_deal_bids_level: 0.0, + best_deal_asks_level: 0.0, asks: asks, bids: bids, }; @@ -116,8 +120,11 @@ impl<'a> OrderBook<'a> { } fn update_book(&mut self, depth_update: DepthUpdate) { match depth_update.k { - // best deals are defined by how much liquidity at an exchange 0 => { + // we want the highest value on the bid side -- this value is closer to the spread + if depth_update.p > self.best_deal_asks_level { + self.best_deal_asks_level = depth_update.p + } let mut current_seek: usize = 0; let max_seek = self.exchange_count; let level_list = self.asks.get_mut(&OrderedFloat(depth_update.p)).unwrap(); @@ -162,6 +169,10 @@ impl<'a> OrderBook<'a> { } } 1 => { + // we want the lowest value on the asks side -- this value is closer to the spread + if depth_update.p < self.best_deal_bids_level { + self.best_deal_asks_level = depth_update.p + } let mut current_seek: usize = 0; let max_seek = self.exchange_count; let level_list = self.bids.get_mut(&OrderedFloat(depth_update.p)).unwrap(); From 8269fda54ea9c5e5a6e2e431c2e5b09ed82eaf6f Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 15:22:08 -0600 Subject: [PATCH 5/8] wip --- orderbook/src/lib.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index f8a05d3..4d428e5 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -118,7 +118,7 @@ impl<'a> OrderBook<'a> { }; return orderbook; } - fn update_book(&mut self, depth_update: DepthUpdate) { + fn update_book(&mut self, depth_update: DepthUpdate) -> Result<(), Error match depth_update.k { 0 => { // we want the highest value on the bid side -- this value is closer to the spread @@ -222,6 +222,15 @@ impl<'a> OrderBook<'a> { } } } + fn publish_quote(&self) { + // move downward on bid side + // move updated on ask side + // subtract lowest ask with highest bid + } + // should be ran in its own thread + fn get_quotes_bid(&self) {} + // should be ran its own thread + fn get_quotes_ask(&self) {} } /* From 83bf3b5ad0c466655b4b3eeb2f9d537a3002df26 Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 15:32:33 -0600 Subject: [PATCH 6/8] error handling for the orderbook --- orderbook/Cargo.toml | 1 + orderbook/src/lib.rs | 21 +++++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/orderbook/Cargo.toml b/orderbook/Cargo.toml index 4a47a59..f35826c 100644 --- a/orderbook/Cargo.toml +++ b/orderbook/Cargo.toml @@ -15,3 +15,4 @@ ordered-float = "3.7.0" bounded-vec-deque = "0.1.1" typed-arena = "2.0.2" market-object = { path = "../market-object"} +quoter-errors = { path = "../quoter-errors"} diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index 4d428e5..18bd9e7 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -10,13 +10,15 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; use std::{hint, thread}; -use market_object::DepthUpdate; use std::marker::PhantomData; use tracing::error; use typed_arena::Arena; use std::f64::NAN; +use market_object::DepthUpdate; +use quoter_errors::ErrorHotPath; + pub struct Stack { head: Link, } @@ -118,7 +120,7 @@ impl<'a> OrderBook<'a> { }; return orderbook; } - fn update_book(&mut self, depth_update: DepthUpdate) -> Result<(), Error + fn update_book(&mut self, depth_update: DepthUpdate) -> Result<(), ErrorHotPath> { match depth_update.k { 0 => { // we want the highest value on the bid side -- this value is closer to the spread @@ -167,6 +169,7 @@ impl<'a> OrderBook<'a> { } } } + Ok(()) } 1 => { // we want the lowest value on the asks side -- this value is closer to the spread @@ -215,22 +218,12 @@ impl<'a> OrderBook<'a> { } } } + Ok(()) } - _ => { - error!("undefined depth object received") - } + _ => Err(ErrorHotPath::OrderBook), } } - fn publish_quote(&self) { - // move downward on bid side - // move updated on ask side - // subtract lowest ask with highest bid - } - // should be ran in its own thread - fn get_quotes_bid(&self) {} - // should be ran its own thread - fn get_quotes_ask(&self) {} } /* From 2e115cef69078ea4799ec552e19bfdc5ac0c86c1 Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 16:52:13 -0600 Subject: [PATCH 7/8] adds quoting from orderbook --- orderbook/Cargo.lock | 361 ++++++++++++++++++++++++++++++++++++++++++- orderbook/Cargo.toml | 1 + orderbook/src/lib.rs | 118 +++++++++++++- 3 files changed, 475 insertions(+), 5 deletions(-) diff --git a/orderbook/Cargo.lock b/orderbook/Cargo.lock index 06354f4..2f1320a 100644 --- a/orderbook/Cargo.lock +++ b/orderbook/Cargo.lock @@ -19,6 +19,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" + [[package]] name = "bitflags" version = "1.3.2" @@ -40,6 +52,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2225b558afc76c596898f5f1b3fc35cfce0eb1b13635cbd7d1b2a7177dc10ccd" +[[package]] +name = "bumpalo" +version = "3.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" + [[package]] name = "byteorder" version = "1.4.3" @@ -134,6 +152,15 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + [[package]] name = "errno" version = "0.3.1" @@ -304,6 +331,31 @@ dependencies = [ "wasi", ] +[[package]] +name = "h2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hermit-abi" version = "0.3.1" @@ -321,12 +373,66 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "idna" version = "0.3.0" @@ -337,6 +443,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.12" @@ -357,12 +473,27 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + [[package]] name = "itoa" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +[[package]] +name = "js-sys" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -398,8 +529,8 @@ dependencies = [ "serde-this-or-that", "serde_json", "smallvec", - "tokio-tungstenite", - "tungstenite", + "tokio-tungstenite 0.19.0", + "tungstenite 0.19.0", ] [[package]] @@ -408,6 +539,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "mio" version = "0.8.6" @@ -507,7 +644,9 @@ dependencies = [ "futures", "market-object", "ordered-float", + "quoter-errors", "rustc-hash", + "thin-vec", "tracing", "typed-arena", ] @@ -569,6 +708,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "quoter-errors" +version = "0.1.0" +dependencies = [ + "reqwest", + "thiserror", + "tokio-tungstenite 0.18.0", +] + [[package]] name = "rand" version = "0.8.5" @@ -608,6 +756,43 @@ dependencies = [ "bitflags", ] +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64 0.21.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -706,6 +891,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha1" version = "0.10.5" @@ -766,6 +963,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "thin-vec" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" + [[package]] name = "thiserror" version = "1.0.40" @@ -826,6 +1029,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.18.0", +] + [[package]] name = "tokio-tungstenite" version = "0.19.0" @@ -837,9 +1052,29 @@ dependencies = [ "native-tls", "tokio", "tokio-native-tls", - "tungstenite", + "tungstenite 0.19.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.37" @@ -872,6 +1107,31 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +dependencies = [ + "base64 0.13.1", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "tungstenite" version = "0.19.0" @@ -954,12 +1214,98 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" + +[[package]] +name = "web-sys" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1128,3 +1474,12 @@ name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] diff --git a/orderbook/Cargo.toml b/orderbook/Cargo.toml index f35826c..c4e8167 100644 --- a/orderbook/Cargo.toml +++ b/orderbook/Cargo.toml @@ -16,3 +16,4 @@ bounded-vec-deque = "0.1.1" typed-arena = "2.0.2" market-object = { path = "../market-object"} quoter-errors = { path = "../quoter-errors"} +thin-vec = "0.2.12" diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index 18bd9e7..199acce 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -16,6 +16,8 @@ use typed_arena::Arena; use std::f64::NAN; +use thin_vec::ThinVec; + use market_object::DepthUpdate; use quoter_errors::ErrorHotPath; @@ -75,14 +77,16 @@ impl Drop for Stack { struct OrderBook<'a> { exchange_count: usize, + level_increment: f64, // level increment is the basis points for each of each depth difference + // for this asset best_deal_bids_level: f64, best_deal_asks_level: f64, asks: FxHashMap, Stack>>, - bids: FxHashMap, Stack>>, + pub bids: FxHashMap, Stack>>, } impl<'a> OrderBook<'a> { - fn new(exchange_count: usize, depth: usize, current_price: usize) -> OrderBook<'a> { + pub fn new(exchange_count: usize, depth: usize, current_price: usize) -> OrderBook<'a> { let ask_level_range: usize = current_price + depth; let mut asks = FxHashMap::, Stack>>::default(); for i in current_price..ask_level_range { @@ -113,6 +117,7 @@ impl<'a> OrderBook<'a> { } let orderbook: OrderBook<'a> = OrderBook { exchange_count: exchange_count, + level_increment: 0.0, best_deal_bids_level: 0.0, best_deal_asks_level: 0.0, asks: asks, @@ -224,6 +229,115 @@ impl<'a> OrderBook<'a> { _ => Err(ErrorHotPath::OrderBook), } } + pub fn get_quotes_bids(&mut self) -> ThinVec { + let mut deals = ThinVec::new(); + let mut current_seek: usize = 0; + let mut current_level = self.best_deal_asks_level; + let mut current_deal_index = 0; + while current_seek < self.exchange_count { + let node = self + .bids + .get(&OrderedFloat(current_level)) + .unwrap() + .peek() + .unwrap(); + // check if volume node in list is not dedicated to an exchange if so bump our + // current level + if node.location == 0 { + let _ = self + .bids + .get_mut(&OrderedFloat(self.best_deal_asks_level)) + .unwrap() + .pop(); + // update to the next level to check for deals. for the bid side we seek down the + // orderbook + current_level = current_level - self.level_increment; + continue; + } + deals.insert( + current_deal_index, + Deal { + volume: node.volume, + location: node.location, + price: current_level, + }, + ); + current_deal_index = current_deal_index + 1; + current_seek = current_seek + 1; + _ = self + .bids + .get_mut(&OrderedFloat(self.best_deal_asks_level)) + .unwrap() + .pop() + } + return deals; + } + pub fn get_quotes_asks(&mut self) -> ThinVec { + let mut deals = ThinVec::new(); + let mut current_seek: usize = 0; + let mut current_level = self.best_deal_asks_level; + let mut current_deal_index = 0; + while current_seek < self.exchange_count { + let node = self + .bids + .get(&OrderedFloat(current_level)) + .unwrap() + .peek() + .unwrap(); + // check if volume node in list is not dedicated to an exchange if so bump our + // current level + if node.location == 0 { + let _ = self + .bids + .get_mut(&OrderedFloat(self.best_deal_asks_level)) + .unwrap() + .pop(); + // update to the next level to check for deals. for asks side we seek up the + // orderbook + current_level = current_level + self.level_increment; + continue; + } + deals.insert( + current_deal_index, + Deal { + volume: node.volume, + location: node.location, + price: current_level, + }, + ); + current_deal_index = current_deal_index + 1; + current_seek = current_seek + 1; + _ = self + .bids + .get_mut(&OrderedFloat(self.best_deal_asks_level)) + .unwrap() + .pop() + } + return deals; + } + // TODO: get_quotes_$side should be ran in their own thread. + pub fn get_quote_bids(&mut self) -> Quotes { + let ask_deals = self.get_quotes_asks(); + let bid_deals = self.get_quotes_bids(); + // ask_deals should always be higher then bid deals. if not we have a problem + Quotes { + spread: ask_deals.get(0).unwrap().price - bid_deals.get(0).unwrap().price, + best_asks: ask_deals, + best_bids: bid_deals, + } + } +} + +pub struct Deal { + volume: f64, + price: f64, + location: u8, +} + +pub struct Quotes { + pub spread: f64, + pub best_bids: ThinVec, + pub best_asks: ThinVec, } /* From 5f91320811c6b6b21674303cd41bcaa04c9510fc Mon Sep 17 00:00:00 2001 From: Ryan Vacek Date: Mon, 22 May 2023 17:43:59 -0600 Subject: [PATCH 8/8] integrate ring buffer, adds tokio quote sender, fixes up upstream config its for orderbook construction --- config/Cargo.toml | 2 +- config/src/lib.rs | 5 +-- orderbook/Cargo.lock | 39 ++++++++++++++++++++ orderbook/Cargo.toml | 3 ++ orderbook/src/lib.rs | 84 +++++++++++++++++++++++--------------------- 5 files changed, 90 insertions(+), 43 deletions(-) diff --git a/config/Cargo.toml b/config/Cargo.toml index e78a408..da0c39f 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] serde = { version = "1.0", features = ["derive"] } -serde_yaml.workspace = true +serde_yaml = "0.9.21" diff --git a/config/src/lib.rs b/config/src/lib.rs index 3bc764f..95b7e05 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -16,9 +16,10 @@ pub struct Config { #[derive(Debug, Deserialize)] pub struct OrderbookConfig { pub ring_buffer: RingBufferConfig, - pub asset_price_floor: f64, - pub asset_price_ceiling: f64, pub price_point_array_size: usize, + pub exchange_count: i64, + pub depth: i64, + pub mid_price: i64, } #[derive(Debug, Deserialize)] diff --git a/orderbook/Cargo.lock b/orderbook/Cargo.lock index 2f1320a..013efbd 100644 --- a/orderbook/Cargo.lock +++ b/orderbook/Cargo.lock @@ -82,6 +82,14 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "config" +version = "0.1.0" +dependencies = [ + "serde", + "serde_yaml", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -640,13 +648,16 @@ version = "0.1.0" dependencies = [ "async-trait", "bounded-vec-deque", + "config", "crossbeam-channel", "futures", "market-object", "ordered-float", "quoter-errors", + "ring-buffer", "rustc-hash", "thin-vec", + "tokio", "tracing", "typed-arena", ] @@ -793,6 +804,15 @@ dependencies = [ "winreg", ] +[[package]] +name = "ring-buffer" +version = "0.1.0" +dependencies = [ + "config", + "crossbeam-channel", + "market-object", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -903,6 +923,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.5" @@ -1185,6 +1218,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" + [[package]] name = "url" version = "2.3.1" diff --git a/orderbook/Cargo.toml b/orderbook/Cargo.toml index c4e8167..8675189 100644 --- a/orderbook/Cargo.toml +++ b/orderbook/Cargo.toml @@ -16,4 +16,7 @@ bounded-vec-deque = "0.1.1" typed-arena = "2.0.2" market-object = { path = "../market-object"} quoter-errors = { path = "../quoter-errors"} +ring-buffer = { path = "../ring-buffer"} +config = { path = "../config"} thin-vec = "0.2.12" +tokio = "1.28.1" diff --git a/orderbook/src/lib.rs b/orderbook/src/lib.rs index 199acce..ef81be5 100644 --- a/orderbook/src/lib.rs +++ b/orderbook/src/lib.rs @@ -1,5 +1,6 @@ use crossbeam_channel::Sender; use rustc_hash::FxHashMap; +use tokio::sync::mpsc::Sender as TokioSender; use tracing::info; use ordered_float::OrderedFloat; @@ -18,8 +19,10 @@ use std::f64::NAN; use thin_vec::ThinVec; +use config::OrderbookConfig; use market_object::DepthUpdate; use quoter_errors::ErrorHotPath; +use ring_buffer::RingBuffer; pub struct Stack { head: Link, @@ -76,37 +79,42 @@ impl Drop for Stack { } struct OrderBook<'a> { - exchange_count: usize, + exchange_count: f64, level_increment: f64, // level increment is the basis points for each of each depth difference // for this asset + ring_buffer: RingBuffer, best_deal_bids_level: f64, best_deal_asks_level: f64, asks: FxHashMap, Stack>>, - pub bids: FxHashMap, Stack>>, + bids: FxHashMap, Stack>>, + quote_producer: TokioSender, } impl<'a> OrderBook<'a> { - pub fn new(exchange_count: usize, depth: usize, current_price: usize) -> OrderBook<'a> { - let ask_level_range: usize = current_price + depth; + pub fn new( + quote_producer: TokioSender, + config: OrderbookConfig, + ) -> (OrderBook<'a>, Sender) { + let ask_level_range: i64 = (config.mid_price + config.depth) as i64; let mut asks = FxHashMap::, Stack>>::default(); - for i in current_price..ask_level_range { - let level: f64 = i as f64; + for i in config.mid_price..ask_level_range { + let level: i64 = i as i64; let mut volume_nodes: Stack> = Stack::new(); - for _ in 0..exchange_count { + for _ in 0..config.exchange_count { volume_nodes.push(VolumeNode { volume: 0.0, location: 0, _phantom: PhantomData, }); } - asks.insert(OrderedFloat(level), volume_nodes); + asks.insert(OrderedFloat(level as f64), volume_nodes); } - let bid_level_range: usize = current_price - depth; + let bid_level_range: i64 = config.mid_price - config.depth; let mut bids = FxHashMap::, Stack>>::default(); - for j in bid_level_range..current_price { + for j in bid_level_range..config.mid_price { let level: f64 = j as f64; let mut volume_nodes: Stack> = Stack::new(); - for _ in 0..exchange_count { + for _ in 0..config.exchange_count { volume_nodes.push(VolumeNode { volume: 0.0, location: 0, @@ -115,15 +123,29 @@ impl<'a> OrderBook<'a> { } bids.insert(OrderedFloat(level), volume_nodes); } + let (ring_buffer, depth_producers) = RingBuffer::new(config.ring_buffer); let orderbook: OrderBook<'a> = OrderBook { - exchange_count: exchange_count, + ring_buffer: ring_buffer, + exchange_count: config.exchange_count as f64, level_increment: 0.0, best_deal_bids_level: 0.0, best_deal_asks_level: 0.0, asks: asks, bids: bids, + quote_producer: quote_producer, }; - return orderbook; + (orderbook, depth_producers) + } + fn consume_depths(&mut self) { + self.ring_buffer.consume(); + } + fn receive_depths(&mut self) { + while let Some(depth_update) = self.ring_buffer.pop_depth() { + // TODO: insert simple locking for now. + if let Ok(_) = self.update_book(depth_update) { + self.quote(); + } + } } fn update_book(&mut self, depth_update: DepthUpdate) -> Result<(), ErrorHotPath> { match depth_update.k { @@ -133,7 +155,7 @@ impl<'a> OrderBook<'a> { self.best_deal_asks_level = depth_update.p } let mut current_seek: usize = 0; - let max_seek = self.exchange_count; + let max_seek = self.exchange_count as usize; let level_list = self.asks.get_mut(&OrderedFloat(depth_update.p)).unwrap(); let mut current_volume = 0.0; let mut current_location = 0; @@ -182,7 +204,7 @@ impl<'a> OrderBook<'a> { self.best_deal_asks_level = depth_update.p } let mut current_seek: usize = 0; - let max_seek = self.exchange_count; + let max_seek = self.exchange_count as usize; let level_list = self.bids.get_mut(&OrderedFloat(depth_update.p)).unwrap(); let mut current_volume = 0.0; let mut current_location = 0; @@ -234,7 +256,7 @@ impl<'a> OrderBook<'a> { let mut current_seek: usize = 0; let mut current_level = self.best_deal_asks_level; let mut current_deal_index = 0; - while current_seek < self.exchange_count { + while current_seek < self.exchange_count as usize { let node = self .bids .get(&OrderedFloat(current_level)) @@ -277,7 +299,7 @@ impl<'a> OrderBook<'a> { let mut current_seek: usize = 0; let mut current_level = self.best_deal_asks_level; let mut current_deal_index = 0; - while current_seek < self.exchange_count { + while current_seek < self.exchange_count as usize { let node = self .bids .get(&OrderedFloat(current_level)) @@ -316,15 +338,17 @@ impl<'a> OrderBook<'a> { return deals; } // TODO: get_quotes_$side should be ran in their own thread. - pub fn get_quote_bids(&mut self) -> Quotes { + // TODO: handle channel errors + pub async fn quote(&mut self) -> Result<(), ErrorHotPath> { let ask_deals = self.get_quotes_asks(); let bid_deals = self.get_quotes_bids(); // ask_deals should always be higher then bid deals. if not we have a problem - Quotes { + self.quote_producer.send(Quotes { spread: ask_deals.get(0).unwrap().price - bid_deals.get(0).unwrap().price, best_asks: ask_deals, best_bids: bid_deals, - } + }); + Ok(()) } } @@ -339,23 +363,3 @@ pub struct Quotes { pub best_bids: ThinVec, pub best_asks: ThinVec, } - -/* -pub struct Coordinator<'a> { - order_boo -}k: &'a mut OrderBook<'a>, // quote_producer: Receiver, - // depth_update_consumer: Sender, -} -*/ - -/* -impl<'a> Coordinator<'a> { - fn new() -> Coordinator<'a> { - let order_book_allocation: &'a mut OrderBook = - Arena::new().alloc(OrderBook::new(2, 5000, 27000)); - Coordinator { - order_book: order_book_allocation, - } - } -} -*/