Skip to content

Commit 6b52088

Browse files
committed
feat: add benchmark
1 parent 97ddb62 commit 6b52088

File tree

6 files changed

+691
-746
lines changed

6 files changed

+691
-746
lines changed

README.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,18 @@
1212

1313
:star: Star me on GitHub — it motivates me a lot!
1414

15-
Improved matching engine written in Javascript
15+
Ultra-fast matching engine written in Javascript
1616

1717
## Features
1818

1919
- Standard price-time priority
2020
- Supports both market and limit orders
2121
- Supports order cancelling
22+
- **High performance (above 300k trades per second)**
23+
24+
**Machine:** ASUS ExpertBook, 11th Gen Intel(R) Core(TM) i7-1165G7, 2.80Ghz, 16GB RAM, Node.js v18.4.0.
25+
26+
<img src="https://user-images.githubusercontent.com/1219087/181792292-8619ee25-bf75-4871-a06c-bd6c82157f33.png" alt="hft-limit-order-book-benchmark" title="hft-limit-order-book benchmark" />
2227

2328
## Installation
2429

@@ -196,6 +201,40 @@ quantityLeft - 4
196201
197202
```
198203

204+
## Development
205+
206+
### Build
207+
208+
Build production (distribution) files in your dist folder:
209+
210+
```sh
211+
npm run build
212+
```
213+
214+
### Testing
215+
216+
To run all the unit-test
217+
218+
```sh
219+
npm run test
220+
```
221+
222+
### Coverage
223+
224+
Run testing coverage
225+
226+
```sh
227+
npm run test:cov
228+
```
229+
230+
### Benchmarking
231+
232+
Before running benchmark, be sure to have builded the source code with 'npm run build'
233+
234+
```sh
235+
npm run bench
236+
```
237+
199238
## Contributing
200239

201240
I would greatly appreciate any contributions to make this project better. Please make sure to follow the below guidelines before getting your hands dirty.

benchmarks/benchmark_lob.js

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/* eslint-disable @typescript-eslint/no-var-requires */
2+
const bench = require('nanobench')
3+
const hft = require('../dist/cjs/index.js')
4+
const gaussian = require('gaussian')
5+
6+
/* New Limits */
7+
function spamLimitOrders(book, count) {
8+
for (let i = 0; i < count; i++) {
9+
book.processLimitOrder('buy', i.toString(), 50, i)
10+
}
11+
}
12+
13+
bench('Spam 1 new Limits', function (b) {
14+
const book = new hft.OrderBook()
15+
b.start()
16+
spamLimitOrders(book, 1)
17+
b.end()
18+
})
19+
20+
bench('Spam 10 new Limits', function (b) {
21+
const book = new hft.OrderBook()
22+
b.start()
23+
spamLimitOrders(book, 10)
24+
b.end()
25+
})
26+
27+
bench('Spam 100 new Limits', function (b) {
28+
const book = new hft.OrderBook()
29+
b.start()
30+
spamLimitOrders(book, 100)
31+
b.end()
32+
})
33+
34+
bench('Spam 1000 new Limits', function (b) {
35+
const book = new hft.OrderBook()
36+
b.start()
37+
spamLimitOrders(book, 1000)
38+
b.end()
39+
})
40+
41+
bench('Spam 100000 new Limits', function (b) {
42+
const book = new hft.OrderBook()
43+
b.start()
44+
spamLimitOrders(book, 100000)
45+
b.end()
46+
})
47+
48+
bench('Spam 300000 new Limits', function (b) {
49+
const book = new hft.OrderBook()
50+
b.start()
51+
spamLimitOrders(book, 300000)
52+
b.end()
53+
})
54+
55+
/* New Orders */
56+
function spamOrders(book, count, variance = 5) {
57+
for (let i = 0; i < count; i++) {
58+
book.processLimitOrder('buy', i.toString(), 50, i % variance)
59+
}
60+
}
61+
62+
bench('Spam 1 new Orders', function (b) {
63+
const book = new hft.OrderBook()
64+
b.start()
65+
spamOrders(book, 1)
66+
b.end()
67+
})
68+
69+
bench('Spam 10 new Orders', function (b) {
70+
const book = new hft.OrderBook()
71+
b.start()
72+
spamOrders(book, 10)
73+
b.end()
74+
})
75+
76+
bench('Spam 100 new Orders', function (b) {
77+
const book = new hft.OrderBook()
78+
b.start()
79+
spamOrders(book, 100)
80+
b.end()
81+
})
82+
83+
bench('Spam 1000 new Orders', function (b) {
84+
const book = new hft.OrderBook()
85+
b.start()
86+
spamOrders(book, 1000)
87+
b.end()
88+
})
89+
90+
/* Random submission and cancellation */
91+
function spamOrdersRandomCancels(
92+
book,
93+
count,
94+
mean = 500,
95+
variance = 30,
96+
cancel_every = 5
97+
) {
98+
const price_distribution = gaussian(mean, variance)
99+
book.processLimitOrder('buy', '0', 50, price_distribution.ppf(Math.random()))
100+
for (let i = 1; i < count; i++) {
101+
book.processLimitOrder(
102+
'buy',
103+
i.toString(),
104+
50,
105+
price_distribution.ppf(Math.random())
106+
)
107+
if (i % cancel_every == 0) book.cancelOrder((i - cancel_every).toString())
108+
}
109+
}
110+
111+
bench('Spam 10 orders and randomly cancel orders', function (b) {
112+
const book = new hft.OrderBook()
113+
b.start()
114+
spamOrdersRandomCancels(book, 10)
115+
b.end()
116+
})
117+
118+
bench('Spam 100 orders and randomly cancel orders', function (b) {
119+
const book = new hft.OrderBook()
120+
b.start()
121+
spamOrdersRandomCancels(book, 100)
122+
b.end()
123+
})
124+
125+
bench('Spam 1000 orders and randomly cancel orders', function (b) {
126+
const book = new hft.OrderBook()
127+
b.start()
128+
spamOrdersRandomCancels(book, 1000)
129+
b.end()
130+
})
131+
132+
bench('Spam 10000 orders and randomly cancel orders', function (b) {
133+
const book = new hft.OrderBook()
134+
b.start()
135+
spamOrdersRandomCancels(book, 10000)
136+
b.end()
137+
})
138+
139+
/* Random submission, cancellation, and market orders */
140+
function spamLimitRandomOrders(
141+
book,
142+
count,
143+
price_mean = 500,
144+
price_variance = 20,
145+
quantity_mean = 100,
146+
quantity_variance = 10,
147+
order_every = 100
148+
) {
149+
const price = gaussian(price_mean, price_variance)
150+
const quantity = gaussian(quantity_mean, quantity_variance)
151+
for (let i = 1; i < count; i++) {
152+
const price_ = price.ppf(Math.random())
153+
const quantity_ = quantity.ppf(Math.random())
154+
book.processLimitOrder('buy', i.toString(), 100, price_)
155+
if (i % order_every == 0)
156+
// random submit a market order
157+
book.processMarketOrder('sell', quantity_)
158+
}
159+
}
160+
161+
bench('Spam 1000 limit orders and occasional market orders', function (b) {
162+
const book = new hft.OrderBook()
163+
b.start()
164+
spamLimitRandomOrders(book, 1000)
165+
b.end()
166+
})
167+
168+
bench('Spam 10000 limit orders and occasional market orders', function (b) {
169+
const book = new hft.OrderBook()
170+
b.start()
171+
spamLimitRandomOrders(book, 10000)
172+
b.end()
173+
})
174+
175+
bench('Spam 100000 limit orders and occasional market orders', function (b) {
176+
const book = new hft.OrderBook()
177+
b.start()
178+
spamLimitRandomOrders(book, 100000)
179+
b.end()
180+
})
181+
182+
function spamLimitManyMarketOrders(
183+
book,
184+
count,
185+
price_mean = 500,
186+
price_variance = 20,
187+
quantity_mean = 50,
188+
quantity_variance = 10
189+
) {
190+
const price = gaussian(price_mean, price_variance)
191+
const quantity = gaussian(quantity_mean, quantity_variance)
192+
193+
for (let i = 1; i < count; i++) {
194+
const price_ = price.ppf(Math.random())
195+
const quantity_ = quantity.ppf(Math.random())
196+
book.processLimitOrder('buy', i.toString(), 100, price_)
197+
book.processMarketOrder('sell', quantity_)
198+
}
199+
}
200+
201+
bench('Spam 10 limit orders and constant market orders', function (b) {
202+
const book = new hft.OrderBook()
203+
b.start()
204+
spamLimitManyMarketOrders(book, 10)
205+
b.end()
206+
})
207+
208+
bench('Spam 100 limit orders and constant market orders', function (b) {
209+
const book = new hft.OrderBook()
210+
b.start()
211+
spamLimitManyMarketOrders(book, 100)
212+
b.end()
213+
})
214+
215+
bench('Spam 1000 limit orders and constant market orders', function (b) {
216+
const book = new hft.OrderBook()
217+
b.start()
218+
spamLimitManyMarketOrders(book, 1000)
219+
b.end()
220+
})
221+
222+
bench('Spam 10000 limit orders and constant market orders', function (b) {
223+
const book = new hft.OrderBook()
224+
b.start()
225+
spamLimitManyMarketOrders(book, 10000)
226+
b.end()
227+
})

benchmarks/lob.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

benchmarks/server.js

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)