···
1
1
target/
2
2
+
pricing-engine.code-workspace/
···
43
43
]
44
44
45
45
[[package]]
46
46
+
name = "dtoa"
47
47
+
version = "0.4.3"
48
48
+
source = "registry+https://github.com/rust-lang/crates.io-index"
49
49
+
50
50
+
[[package]]
46
51
name = "env_logger"
47
52
version = "0.5.11"
48
53
source = "registry+https://github.com/rust-lang/crates.io-index"
···
75
80
dependencies = [
76
81
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
77
82
]
83
83
+
84
84
+
[[package]]
85
85
+
name = "itoa"
86
86
+
version = "0.4.2"
87
87
+
source = "registry+https://github.com/rust-lang/crates.io-index"
78
88
79
89
[[package]]
80
90
name = "lazy_static"
···
119
129
"log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
120
130
"pretty_env_logger 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
121
131
"rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
132
132
+
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
133
133
+
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
134
134
+
"serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
135
135
+
]
136
136
+
137
137
+
[[package]]
138
138
+
name = "proc-macro2"
139
139
+
version = "0.4.9"
140
140
+
source = "registry+https://github.com/rust-lang/crates.io-index"
141
141
+
dependencies = [
142
142
+
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
122
143
]
123
144
124
145
[[package]]
125
146
name = "quick-error"
126
147
version = "1.2.2"
127
148
source = "registry+https://github.com/rust-lang/crates.io-index"
149
149
+
150
150
+
[[package]]
151
151
+
name = "quote"
152
152
+
version = "0.6.4"
153
153
+
source = "registry+https://github.com/rust-lang/crates.io-index"
154
154
+
dependencies = [
155
155
+
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
156
156
+
]
128
157
129
158
[[package]]
130
159
name = "rand"
···
177
206
]
178
207
179
208
[[package]]
209
209
+
name = "serde"
210
210
+
version = "1.0.70"
211
211
+
source = "registry+https://github.com/rust-lang/crates.io-index"
212
212
+
213
213
+
[[package]]
214
214
+
name = "serde_derive"
215
215
+
version = "1.0.70"
216
216
+
source = "registry+https://github.com/rust-lang/crates.io-index"
217
217
+
dependencies = [
218
218
+
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
219
219
+
"quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
220
220
+
"syn 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)",
221
221
+
]
222
222
+
223
223
+
[[package]]
224
224
+
name = "serde_json"
225
225
+
version = "1.0.24"
226
226
+
source = "registry+https://github.com/rust-lang/crates.io-index"
227
227
+
dependencies = [
228
228
+
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
229
229
+
"itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
230
230
+
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
231
231
+
]
232
232
+
233
233
+
[[package]]
234
234
+
name = "syn"
235
235
+
version = "0.14.5"
236
236
+
source = "registry+https://github.com/rust-lang/crates.io-index"
237
237
+
dependencies = [
238
238
+
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
239
239
+
"quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
240
240
+
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
241
241
+
]
242
242
+
243
243
+
[[package]]
180
244
name = "termcolor"
181
245
version = "1.0.1"
182
246
source = "registry+https://github.com/rust-lang/crates.io-index"
···
206
270
[[package]]
207
271
name = "ucd-util"
208
272
version = "0.1.1"
273
273
+
source = "registry+https://github.com/rust-lang/crates.io-index"
274
274
+
275
275
+
[[package]]
276
276
+
name = "unicode-xid"
277
277
+
version = "0.1.0"
209
278
source = "registry+https://github.com/rust-lang/crates.io-index"
210
279
211
280
[[package]]
···
260
329
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
261
330
"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e"
262
331
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
332
332
+
"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
263
333
"checksum env_logger 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7873e292d20e8778f951278972596b3df36ac72a65c5b406f6d4961070a870c1"
264
334
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
265
335
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
266
336
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
337
337
+
"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606"
267
338
"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3"
268
339
"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1"
269
340
"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2"
270
341
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
271
342
"checksum pretty_env_logger 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ae1b463255bf6613ad435f8997cb57f5d045ef35eb255f5a3d6085be936bd79"
343
343
+
"checksum proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "cccdc7557a98fe98453030f077df7f3a042052fae465bb61d2c2c41435cfd9b6"
272
344
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
345
345
+
"checksum quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b71f9f575d55555aa9c06188be9d4e2bfc83ed02537948ac0d520c24d0419f1a"
273
346
"checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea"
274
347
"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
275
348
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
276
349
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
277
350
"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814"
278
351
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
352
352
+
"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920"
353
353
+
"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124"
354
354
+
"checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2"
355
355
+
"checksum syn 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4bad7abdf6633f07c7046b90484f1d9dc055eca39f8c991177b1046ce61dba9a"
279
356
"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836"
280
357
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
281
358
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
282
359
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
360
360
+
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
283
361
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
284
362
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
285
363
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
···
7
7
rand = "0.5"
8
8
log = "0.4"
9
9
pretty_env_logger = "0.2.4"
10
10
+
serde_json = "1.0"
11
11
+
serde_derive = "1.0"
12
12
+
serde = "1.0"
13
13
+
···
1
1
+
{
2
2
+
"folders": [
3
3
+
{
4
4
+
"path": "."
5
5
+
}
6
6
+
],
7
7
+
"settings": {
8
8
+
"git.ignoreLimitWarning": true
9
9
+
}
10
10
+
}
···
1
1
#[macro_use]
2
2
extern crate log;
3
3
4
4
+
#[macro_use]
5
5
+
extern crate serde_derive;
6
6
+
extern crate serde_json;
7
7
+
4
8
pub mod orderbook;
5
9
pub mod testing;
6
10
···
1
1
+
extern crate serde;
2
2
+
extern crate serde_json;
3
3
+
1
4
pub mod orderbook;
2
5
pub mod pricelevel;
3
6
pub mod orders;
···
1
1
extern crate pretty_env_logger;
2
2
+
2
3
use orderbook::orders::Order;
3
4
use orderbook::orders::Ordertype;
4
5
use orderbook::pricelevel::PriceLevel;
5
6
use std::collections::HashMap;
7
7
+
use std::f64;
8
8
+
use serde_json;
6
9
7
10
pub struct Orderbook{
8
8
-
// Describes an orderbook.
11
11
+
// Describes an orderbook
9
12
name: String, // A currency pair, ticker, whatever.
13
13
+
automatch: bool, // Whether or not to match trades
10
14
11
11
-
// Price levels.
15
15
+
// Price levels
12
16
buys: HashMap<String, PriceLevel>,
13
13
-
sells: HashMap<String, PriceLevel>
17
17
+
sells: HashMap<String, PriceLevel>,
18
18
+
19
19
+
// Bests
20
20
+
best_buy: (String, f64),
21
21
+
best_sell: (String, f64),
14
22
}
15
23
16
24
impl Orderbook {
17
25
pub fn new(name: String) -> Orderbook{
18
26
return Orderbook{
19
27
name,
28
28
+
automatch: false,
20
29
buys: HashMap::new(),
21
30
sells: HashMap::new(),
31
31
+
best_buy: (String::default(), f64::MIN),
32
32
+
best_sell: (String::default(), f64::MAX),
22
33
}
23
34
}
24
35
···
26
37
let pl = PriceLevel::new(&new_buy);
27
38
match self.buys.contains_key(&new_buy.price_string) {
28
39
true => {
29
29
-
self.buys.entry(new_buy.price_string).or_insert(pl);
40
40
+
let price = new_buy.price_string;
41
41
+
if verbose {
42
42
+
info!("Inserting new buy level {} at {}",
43
43
+
&price,
44
44
+
pl.quantity)
45
45
+
}
46
46
+
self.buys.entry(price).or_insert(pl);
30
47
},
31
48
false => {
32
32
-
let entry = self.buys.entry(new_buy.price_string).or_default();
49
49
+
let price = new_buy.price_string;
50
50
+
let entry = self.buys.entry(price.clone()).or_default();
33
51
34
52
if new_buy.additive {
53
53
+
if verbose {
54
54
+
info!("Adjusting buy level {} by {}",
55
55
+
price,
56
56
+
pl.quantity)
57
57
+
}
58
58
+
35
59
(*entry).merge(pl);
36
60
} else {
37
61
*entry = pl;
···
44
68
let pl = PriceLevel::new(&new_sell);
45
69
match self.sells.contains_key(&new_sell.price_string) {
46
70
true => {
47
47
-
self.sells.entry(new_sell.price_string).or_insert(pl);
71
71
+
let price = new_sell.price_string;
72
72
+
if verbose {
73
73
+
info!("Inserting new sell level {} at {}",
74
74
+
&price,
75
75
+
pl.quantity)
76
76
+
}
77
77
+
self.sells.entry(price).or_insert(pl);
48
78
},
49
79
false => {
50
50
-
let entry = self.sells.entry(new_sell.price_string).or_default();
51
51
-
*entry = pl;
80
80
+
let price = new_sell.price_string;
81
81
+
let entry = self.sells.entry(price.clone()).or_default();
82
82
+
83
83
+
if new_sell.additive {
84
84
+
if verbose {
85
85
+
info!("Adjusting sell level {} by {}",
86
86
+
price,
87
87
+
pl.quantity)
88
88
+
}
89
89
+
90
90
+
(*entry).merge(pl);
91
91
+
} else {
92
92
+
*entry = pl;
93
93
+
}
52
94
}
53
95
}
54
96
}
55
97
56
98
pub fn insert(&mut self, new_order: Order, verbose: bool){
99
99
+
self.update_best(&new_order, verbose);
57
100
match new_order.order_type {
58
58
-
Ordertype::Buy => self.update_buy(new_order, verbose),
101
101
+
Ordertype::Buy => self.update_buy(new_order, verbose),
59
102
Ordertype::Sell => self.update_sell(new_order, verbose)
60
103
};
104
104
+
}
105
105
+
106
106
+
pub fn insert_from_json(&mut self, order_string: String, verbose: bool) {
107
107
+
let new_order: Order = match serde_json::from_str(&order_string) {
108
108
+
Ok(o) => o,
109
109
+
Err(e) => {
110
110
+
print!("Serializing string: {:?}", e);
111
111
+
return ();
112
112
+
}
113
113
+
};
114
114
+
115
115
+
if verbose {
116
116
+
info!("Received JSON string:");
117
117
+
info!("{}", order_string);
118
118
+
}
119
119
+
120
120
+
self.insert(new_order, verbose);
121
121
+
}
122
122
+
123
123
+
pub fn update_best(&mut self, new_order: &Order, _verbose: bool) {
124
124
+
match new_order.order_type {
125
125
+
Ordertype::Buy => {
126
126
+
if new_order.price > self.best_buy.1 {
127
127
+
self.best_buy = (new_order.price_string.clone(), new_order.price.clone())
128
128
+
}
129
129
+
},
130
130
+
Ordertype::Sell => {
131
131
+
if new_order.price < self.best_sell.1 {
132
132
+
self.best_sell = (new_order.price_string.clone(), new_order.price.clone())
133
133
+
}
134
134
+
}
135
135
+
}
136
136
+
}
137
137
+
138
138
+
pub fn summary(&self) {
139
139
+
let name = &self.name;
140
140
+
let num_buys = self.buys.len();
141
141
+
let num_sells = self.sells.len();
142
142
+
let best_buy = &self.best_buy.0;
143
143
+
let best_sell = &self.best_sell.0;
144
144
+
145
145
+
println!("Name: {}
146
146
+
Buy count: {}
147
147
+
Sell count: {}
148
148
+
149
149
+
Best buy: {}
150
150
+
Best sell: {}",
151
151
+
name, num_buys, num_sells, best_buy, best_sell);
61
152
}
62
153
}
···
1
1
-
#[derive(PartialEq, Eq, Debug)]
1
1
+
extern crate serde_json;
2
2
+
3
3
+
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
2
4
pub enum Ordertype{
3
5
Buy = 1,
4
6
Sell = -1
5
7
}
6
8
7
7
-
#[derive(Debug)]
9
9
+
#[derive(Serialize, Deserialize, Debug)]
8
10
pub struct Order {
9
11
pub order_type: Ordertype,
10
12
pub price_string: String,
···
1
1
use orderbook::orders::Order;
2
2
-
use std::ops::Add;
3
2
4
3
#[derive(Default)]
5
4
pub struct PriceLevel {
···
11
10
return PriceLevel {quantity: order.amount}
12
11
}
13
12
14
14
-
pub fn merge(&self, other: PriceLevel) {
13
13
+
pub fn merge(&mut self, other: PriceLevel) {
15
14
self.quantity += other.quantity;
16
15
}
17
16
}
···
1
1
extern crate rand;
2
2
extern crate pretty_env_logger;
3
3
+
extern crate serde_json;
3
4
4
4
-
use testing::rand::prelude::random;
5
5
+
use testing::rand::ThreadRng;
6
6
+
use testing::rand::random;
7
7
+
use testing::rand::distributions::Uniform;
8
8
+
use testing::rand::{Rng, thread_rng};
5
9
use orderbook::orderbook::Orderbook;
6
10
use orderbook::orders::*;
7
11
···
11
15
let mut ob = Orderbook::new(name);
12
16
let cumulative = true;
13
17
18
18
+
let mut rng = thread_rng();
19
19
+
let price_range = Uniform::new(1, 100);
20
20
+
let amount_range = Uniform::new(1, 1000000);
21
21
+
14
22
for _ in 1..50 {
15
15
-
let new_order = random_order(cumulative);
23
23
+
let new_order = random_order(cumulative, &mut rng, &price_range, &amount_range);
16
24
// info!("{:?}", &new_order);
17
25
ob.insert(new_order, true);
18
26
}
27
27
+
28
28
+
// Test string insertion
29
29
+
for _ in 1..50 {
30
30
+
let new_str = random_order_string(cumulative, &mut rng, &price_range, &amount_range);
31
31
+
ob.insert_from_json(new_str, true);
32
32
+
}
33
33
+
34
34
+
ob.summary();
19
35
}
20
36
21
21
-
pub fn random_order(cumulative: bool) -> Order {
22
22
-
let price: f64 = random();
23
23
-
let amount: f64 = random();
37
37
+
pub fn random_order(cumulative: bool,
38
38
+
rng: &mut ThreadRng,
39
39
+
price_range: &Uniform<i32>,
40
40
+
amount_range: &Uniform<i32>) -> Order {
41
41
+
let price: i32 = rng.sample(price_range);
42
42
+
let amount: i32 = rng.sample(amount_range);
43
43
+
44
44
+
if random() {
45
45
+
return Order::sell(price.into(), amount.into(), cumulative);
46
46
+
} else {
47
47
+
return Order::buy(price.into(), amount.into(), cumulative);
48
48
+
}
49
49
+
}
24
50
25
25
-
if random() {
26
26
-
return Order::sell(price - 0.5, amount, cumulative);
27
27
-
} else {
28
28
-
return Order::buy(price - 0.5, amount, cumulative);
29
29
-
}
51
51
+
pub fn random_order_string(cumulative: bool,
52
52
+
rng: &mut ThreadRng,
53
53
+
price_range: &Uniform<i32>,
54
54
+
amount_range: &Uniform<i32>) -> String {
55
55
+
let new_order = random_order(cumulative, rng, &price_range, &amount_range);
56
56
+
return serde_json::to_string_pretty(&new_order).unwrap();
30
57
}