CppTrader 1.0.5.0
C++ Trader
Loading...
Searching...
No Matches
order_book.cpp
Go to the documentation of this file.
1
11
12namespace CppTrader {
13namespace Matching {
14
16 : _manager(manager),
17 _symbol(symbol),
18 _best_bid(nullptr),
19 _best_ask(nullptr),
20 _best_buy_stop(nullptr),
21 _best_sell_stop(nullptr),
22 _best_trailing_buy_stop(nullptr),
23 _best_trailing_sell_stop(nullptr),
24 _last_bid_price(0),
25 _last_ask_price(std::numeric_limits<uint64_t>::max()),
26 _matching_bid_price(0),
27 _matching_ask_price(std::numeric_limits<uint64_t>::max()),
28 _trailing_bid_price(0),
29 _trailing_ask_price(std::numeric_limits<uint64_t>::max())
30{
31}
32
34{
35 // Release bid price levels
36 for (auto& bid : _bids)
37 _manager._level_pool.Release(&bid);
38 _bids.clear();
39
40 // Release ask price levels
41 for (auto& ask : _asks)
42 _manager._level_pool.Release(&ask);
43 _asks.clear();
44
45 // Release buy stop orders levels
46 for (auto& buy_stop : _buy_stop)
47 _manager._level_pool.Release(&buy_stop);
48 _buy_stop.clear();
49
50 // Release sell stop orders levels
51 for (auto& sell_stop : _sell_stop)
52 _manager._level_pool.Release(&sell_stop);
53 _sell_stop.clear();
54
55 // Release trailing buy stop orders levels
56 for (auto& trailing_buy_stop : _trailing_buy_stop)
57 _manager._level_pool.Release(&trailing_buy_stop);
58 _trailing_buy_stop.clear();
59
60 // Release trailing sell stop orders levels
61 for (auto& trailing_sell_stop : _trailing_sell_stop)
62 _manager._level_pool.Release(&trailing_sell_stop);
63 _trailing_sell_stop.clear();
64}
65
66LevelNode* OrderBook::AddLevel(OrderNode* order_ptr)
67{
68 LevelNode* level_ptr = nullptr;
69
70 if (order_ptr->IsBuy())
71 {
72 // Create a new price level
73 level_ptr = _manager._level_pool.Create(LevelType::BID, order_ptr->Price);
74
75 // Insert the price level into the bid collection
76 _bids.insert(*level_ptr);
77
78 // Update the best bid price level
79 if ((_best_bid == nullptr) || (level_ptr->Price > _best_bid->Price))
80 _best_bid = level_ptr;
81 }
82 else
83 {
84 // Create a new price level
85 level_ptr = _manager._level_pool.Create(LevelType::ASK, order_ptr->Price);
86
87 // Insert the price level into the ask collection
88 _asks.insert(*level_ptr);
89
90 // Update the best ask price level
91 if ((_best_ask == nullptr) || (level_ptr->Price < _best_ask->Price))
92 _best_ask = level_ptr;
93 }
94
95 return level_ptr;
96}
97
98LevelNode* OrderBook::DeleteLevel(OrderNode* order_ptr)
99{
100 // Find the price level for the order
101 LevelNode* level_ptr = order_ptr->Level;
102
103 if (order_ptr->IsBuy())
104 {
105 // Update the best bid price level
106 if (level_ptr == _best_bid)
107 _best_bid = (_best_bid->left != nullptr) ? _best_bid->left : ((_best_bid->parent != nullptr) ? _best_bid->parent : _best_bid->right);
108
109 // Erase the price level from the bid collection
110 _bids.erase(Levels::iterator(&_bids, level_ptr));
111 }
112 else
113 {
114 // Update the best ask price level
115 if (level_ptr == _best_ask)
116 _best_ask = (_best_ask->right != nullptr) ? _best_ask->right : ((_best_ask->parent != nullptr) ? _best_ask->parent : _best_ask->left);
117
118 // Erase the price level from the ask collection
119 _asks.erase(Levels::iterator(&_asks, level_ptr));
120 }
121
122 // Release the price level
123 _manager._level_pool.Release(level_ptr);
124
125 return nullptr;
126}
127
128LevelUpdate OrderBook::AddOrder(OrderNode* order_ptr)
129{
130 // Find the price level for the order
131 LevelNode* level_ptr = order_ptr->IsBuy() ? (LevelNode*)GetBid(order_ptr->Price) : (LevelNode*)GetAsk(order_ptr->Price);
132
133 // Create a new price level if no one found
135 if (level_ptr == nullptr)
136 {
137 level_ptr = AddLevel(order_ptr);
138 update = UpdateType::ADD;
139 }
140
141 // Update the price level volume
142 level_ptr->TotalVolume += order_ptr->LeavesQuantity;
143 level_ptr->HiddenVolume += order_ptr->HiddenQuantity();
144 level_ptr->VisibleVolume += order_ptr->VisibleQuantity();
145
146 // Link the new order to the orders list of the price level
147 level_ptr->OrderList.push_back(*order_ptr);
148 ++level_ptr->Orders;
149
150 // Cache the price level in the given order
151 order_ptr->Level = level_ptr;
152
153 // Price level was changed. Return top of the book modification flag.
154 return LevelUpdate(update, *order_ptr->Level, (order_ptr->Level == (order_ptr->IsBuy() ? _best_bid : _best_ask)));
155}
156
157LevelUpdate OrderBook::ReduceOrder(OrderNode* order_ptr, uint64_t quantity, uint64_t hidden, uint64_t visible)
158{
159 bool top = (order_ptr->Level == (order_ptr->IsBuy() ? _best_bid : _best_ask));
160
161 // Find the price level for the order
162 LevelNode* level_ptr = order_ptr->Level;
163
164 // Update the price level volume
165 level_ptr->TotalVolume -= quantity;
166 level_ptr->HiddenVolume -= hidden;
167 level_ptr->VisibleVolume -= visible;
168
169 // Unlink the empty order from the orders list of the price level
170 if (order_ptr->LeavesQuantity == 0)
171 {
172 level_ptr->OrderList.pop_current(*order_ptr);
173 --level_ptr->Orders;
174 }
175
176 Level level(*level_ptr);
177
178 // Delete the empty price level
180 if (level_ptr->TotalVolume == 0)
181 {
182 // Clear the price level cache in the given order
183 order_ptr->Level = DeleteLevel(order_ptr);
184 update = UpdateType::DELETE;
185 }
186
187 // Price level was changed. Return top of the book modification flag.
188 return LevelUpdate(update, level, top);
189}
190
191LevelUpdate OrderBook::DeleteOrder(OrderNode* order_ptr)
192{
193 bool top = (order_ptr->Level == (order_ptr->IsBuy() ? _best_bid : _best_ask));
194
195 // Find the price level for the order
196 LevelNode* level_ptr = order_ptr->Level;
197
198 // Update the price level volume
199 level_ptr->TotalVolume -= order_ptr->LeavesQuantity;
200 level_ptr->HiddenVolume -= order_ptr->HiddenQuantity();
201 level_ptr->VisibleVolume -= order_ptr->VisibleQuantity();
202
203 // Unlink the empty order from the orders list of the price level
204 level_ptr->OrderList.pop_current(*order_ptr);
205 --level_ptr->Orders;
206
207 Level level(*level_ptr);
208
209 // Delete the empty price level
211 if (level_ptr->TotalVolume == 0)
212 {
213 // Clear the price level cache in the given order
214 order_ptr->Level = DeleteLevel(order_ptr);
215 update = UpdateType::DELETE;
216 }
217
218 // Price level was changed. Return top of the book modification flag.
219 return LevelUpdate(update, level, top);
220}
221
222LevelNode* OrderBook::AddStopLevel(OrderNode* order_ptr)
223{
224 LevelNode* level_ptr = nullptr;
225
226 if (order_ptr->IsBuy())
227 {
228 // Create a new price level
229 level_ptr = _manager._level_pool.Create(LevelType::ASK, order_ptr->StopPrice);
230
231 // Insert the price level into the buy stop orders collection
232 _buy_stop.insert(*level_ptr);
233
234 // Update the best buy stop order price level
235 if ((_best_buy_stop == nullptr) || (level_ptr->Price < _best_buy_stop->Price))
236 _best_buy_stop = level_ptr;
237 }
238 else
239 {
240 // Create a new price level
241 level_ptr = _manager._level_pool.Create(LevelType::BID, order_ptr->StopPrice);
242
243 // Insert the price level into the sell stop orders collection
244 _sell_stop.insert(*level_ptr);
245
246 // Update the best sell stop order price level
247 if ((_best_sell_stop == nullptr) || (level_ptr->Price > _best_sell_stop->Price))
248 _best_sell_stop = level_ptr;
249 }
250
251 return level_ptr;
252}
253
254LevelNode* OrderBook::DeleteStopLevel(OrderNode* order_ptr)
255{
256 // Find the price level for the order
257 LevelNode* level_ptr = order_ptr->Level;
258
259 if (order_ptr->IsBuy())
260 {
261 // Update the best buy stop order price level
262 if (level_ptr == _best_buy_stop)
263 _best_buy_stop = (_best_buy_stop->right != nullptr) ? _best_buy_stop->right : _best_buy_stop->parent;
264
265 // Erase the price level from the buy stop orders collection
266 _buy_stop.erase(Levels::iterator(&_buy_stop, level_ptr));
267 }
268 else
269 {
270 // Update the best sell stop order price level
271 if (level_ptr == _best_sell_stop)
272 _best_sell_stop = (_best_sell_stop->left != nullptr) ? _best_sell_stop->left : _best_sell_stop->parent;
273
274 // Erase the price level from the sell stop orders collection
275 _sell_stop.erase(Levels::iterator(&_sell_stop, level_ptr));
276 }
277
278 // Release the price level
279 _manager._level_pool.Release(level_ptr);
280
281 return nullptr;
282}
283
284void OrderBook::AddStopOrder(OrderNode* order_ptr)
285{
286 // Find the price level for the order
287 LevelNode* level_ptr = order_ptr->IsBuy() ? (LevelNode*)GetBuyStopLevel(order_ptr->StopPrice) : (LevelNode*)GetSellStopLevel(order_ptr->StopPrice);
288
289 // Create a new price level if no one found
290 if (level_ptr == nullptr)
291 level_ptr = AddStopLevel(order_ptr);
292
293 // Update the price level volume
294 level_ptr->TotalVolume += order_ptr->LeavesQuantity;
295 level_ptr->HiddenVolume += order_ptr->HiddenQuantity();
296 level_ptr->VisibleVolume += order_ptr->VisibleQuantity();
297
298 // Link the new order to the orders list of the price level
299 level_ptr->OrderList.push_back(*order_ptr);
300 ++level_ptr->Orders;
301
302 // Cache the price level in the given order
303 order_ptr->Level = level_ptr;
304}
305
306void OrderBook::ReduceStopOrder(OrderNode* order_ptr, uint64_t quantity, uint64_t hidden, uint64_t visible)
307{
308 // Find the price level for the order
309 LevelNode* level_ptr = order_ptr->Level;
310
311 // Update the price level volume
312 level_ptr->TotalVolume -= quantity;
313 level_ptr->HiddenVolume -= hidden;
314 level_ptr->VisibleVolume -= visible;
315
316 // Unlink the empty order from the orders list of the price level
317 if (order_ptr->LeavesQuantity == 0)
318 {
319 level_ptr->OrderList.pop_current(*order_ptr);
320 --level_ptr->Orders;
321 }
322
323 // Delete the empty price level
324 if (level_ptr->TotalVolume == 0)
325 {
326 // Clear the price level cache in the given order
327 order_ptr->Level = DeleteStopLevel(order_ptr);
328 }
329}
330
331void OrderBook::DeleteStopOrder(OrderNode* order_ptr)
332{
333 // Find the price level for the order
334 LevelNode* level_ptr = order_ptr->Level;
335
336 // Update the price level volume
337 level_ptr->TotalVolume -= order_ptr->LeavesQuantity;
338 level_ptr->HiddenVolume -= order_ptr->HiddenQuantity();
339 level_ptr->VisibleVolume -= order_ptr->VisibleQuantity();
340
341 // Unlink the empty order from the orders list of the price level
342 level_ptr->OrderList.pop_current(*order_ptr);
343 --level_ptr->Orders;
344
345 // Delete the empty price level
346 if (level_ptr->TotalVolume == 0)
347 {
348 // Clear the price level cache in the given order
349 order_ptr->Level = DeleteStopLevel(order_ptr);
350 }
351}
352
353LevelNode* OrderBook::AddTrailingStopLevel(OrderNode* order_ptr)
354{
355 LevelNode* level_ptr = nullptr;
356
357 if (order_ptr->IsBuy())
358 {
359 // Create a new price level
360 level_ptr = _manager._level_pool.Create(LevelType::ASK, order_ptr->StopPrice);
361
362 // Insert the price level into the trailing buy stop orders collection
363 _trailing_buy_stop.insert(*level_ptr);
364
365 // Update the best trailing buy stop order price level
366 if ((_best_trailing_buy_stop == nullptr) || (level_ptr->Price < _best_trailing_buy_stop->Price))
367 _best_trailing_buy_stop = level_ptr;
368 }
369 else
370 {
371 // Create a new price level
372 level_ptr = _manager._level_pool.Create(LevelType::BID, order_ptr->StopPrice);
373
374 // Insert the price level into the trailing sell stop orders collection
375 _trailing_sell_stop.insert(*level_ptr);
376
377 // Update the best trailing sell stop order price level
378 if ((_best_trailing_sell_stop == nullptr) || (level_ptr->Price > _best_trailing_sell_stop->Price))
379 _best_trailing_sell_stop = level_ptr;
380 }
381
382 return level_ptr;
383}
384
385LevelNode* OrderBook::DeleteTrailingStopLevel(OrderNode* order_ptr)
386{
387 // Find the price level for the order
388 LevelNode* level_ptr = order_ptr->Level;
389
390 if (order_ptr->IsBuy())
391 {
392 // Update the best trailing buy stop order price level
393 if (level_ptr == _best_trailing_buy_stop)
394 _best_trailing_buy_stop = (_best_trailing_buy_stop->right != nullptr) ? _best_trailing_buy_stop->right : _best_trailing_buy_stop->parent;
395
396 // Erase the price level from the trailing buy stop orders collection
397 _trailing_buy_stop.erase(Levels::iterator(&_trailing_buy_stop, level_ptr));
398 }
399 else
400 {
401 // Update the best trailing sell stop order price level
402 if (level_ptr == _best_trailing_sell_stop)
403 _best_trailing_sell_stop = (_best_trailing_sell_stop->left != nullptr) ? _best_trailing_sell_stop->left : _best_trailing_sell_stop->parent;
404
405 // Erase the price level from the trailing sell stop orders collection
406 _trailing_sell_stop.erase(Levels::iterator(&_trailing_sell_stop, level_ptr));
407 }
408
409 // Release the price level
410 _manager._level_pool.Release(level_ptr);
411
412 return nullptr;
413}
414
415void OrderBook::AddTrailingStopOrder(OrderNode* order_ptr)
416{
417 // Find the price level for the order
418 LevelNode* level_ptr = order_ptr->IsBuy() ? (LevelNode*)GetTrailingBuyStopLevel(order_ptr->StopPrice) : (LevelNode*)GetTrailingSellStopLevel(order_ptr->StopPrice);
419
420 // Create a new price level if no one found
421 if (level_ptr == nullptr)
422 level_ptr = AddTrailingStopLevel(order_ptr);
423
424 // Update the price level volume
425 level_ptr->TotalVolume += order_ptr->LeavesQuantity;
426 level_ptr->HiddenVolume += order_ptr->HiddenQuantity();
427 level_ptr->VisibleVolume += order_ptr->VisibleQuantity();
428
429 // Link the new order to the orders list of the price level
430 level_ptr->OrderList.push_back(*order_ptr);
431 ++level_ptr->Orders;
432
433 // Cache the price level in the given order
434 order_ptr->Level = level_ptr;
435}
436
437void OrderBook::ReduceTrailingStopOrder(OrderNode* order_ptr, uint64_t quantity, uint64_t hidden, uint64_t visible)
438{
439 // Find the price level for the order
440 LevelNode* level_ptr = order_ptr->Level;
441
442 // Update the price level volume
443 level_ptr->TotalVolume -= quantity;
444 level_ptr->HiddenVolume -= hidden;
445 level_ptr->VisibleVolume -= visible;
446
447 // Unlink the empty order from the orders list of the price level
448 if (order_ptr->LeavesQuantity == 0)
449 {
450 level_ptr->OrderList.pop_current(*order_ptr);
451 --level_ptr->Orders;
452 }
453
454 // Delete the empty price level
455 if (level_ptr->TotalVolume == 0)
456 {
457 // Clear the price level cache in the given order
458 order_ptr->Level = DeleteTrailingStopLevel(order_ptr);
459 }
460}
461
462void OrderBook::DeleteTrailingStopOrder(OrderNode* order_ptr)
463{
464 // Find the price level for the order
465 LevelNode* level_ptr = order_ptr->Level;
466
467 // Update the price level volume
468 level_ptr->TotalVolume -= order_ptr->LeavesQuantity;
469 level_ptr->HiddenVolume -= order_ptr->HiddenQuantity();
470 level_ptr->VisibleVolume -= order_ptr->VisibleQuantity();
471
472 // Unlink the empty order from the orders list of the price level
473 level_ptr->OrderList.pop_current(*order_ptr);
474 --level_ptr->Orders;
475
476 // Delete the empty price level
477 if (level_ptr->TotalVolume == 0)
478 {
479 // Clear the price level cache in the given order
480 order_ptr->Level = DeleteTrailingStopLevel(order_ptr);
481 }
482}
483
484uint64_t OrderBook::CalculateTrailingStopPrice(const Order& order) const noexcept
485{
486 // Get the current market price
487 uint64_t market_price = order.IsBuy() ? GetMarketTrailingStopPriceAsk() : GetMarketTrailingStopPriceBid();
488 int64_t trailing_distance = order.TrailingDistance;
489 int64_t trailing_step = order.TrailingStep;
490
491 // Convert percentage trailing values into absolute ones
492 if (trailing_distance < 0)
493 {
494 trailing_distance = (int64_t)((-trailing_distance * market_price) / 10000);
495 trailing_step = (int64_t)((-trailing_step * market_price) / 10000);
496 }
497
498 uint64_t old_price = order.StopPrice;
499
500 if (order.IsBuy())
501 {
502 // Calculate a new stop price
503 uint64_t new_price = (market_price < (std::numeric_limits<uint64_t>::max() - trailing_distance)) ? (market_price + trailing_distance) : std::numeric_limits<uint64_t>::max();
504
505 // If the new price is better and we get through the trailing step
506 if (new_price < old_price)
507 if ((old_price - new_price) >= (uint64_t)trailing_step)
508 return new_price;
509 }
510 else
511 {
512 // Calculate a new stop price
513 uint64_t new_price = (market_price > (uint64_t)trailing_distance) ? (market_price - trailing_distance) : 0;
514
515 // If the new price is better and we get through the trailing step
516 if (new_price > old_price)
517 if ((new_price - old_price) >= (uint64_t)trailing_step)
518 return new_price;
519 }
520
521 return old_price;
522}
523
524} // namespace Matching
525} // namespace CppTrader
const LevelNode * GetAsk(uint64_t price) const noexcept
Get the order book ask price level with the given price.
OrderBook(MarketManager &manager, const Symbol &symbol)
const Levels & trailing_sell_stop() const noexcept
Get the order book trailing sell stop orders container.
Definition order_book.h:84
const LevelNode * GetTrailingBuyStopLevel(uint64_t price) const noexcept
Get the order book trailing buy stop level with the given price.
const LevelNode * GetBid(uint64_t price) const noexcept
Get the order book bid price level with the given price.
const LevelNode * GetSellStopLevel(uint64_t price) const noexcept
Get the order book sell stop level with the given price.
const Levels & trailing_buy_stop() const noexcept
Get the order book trailing buy stop orders container.
Definition order_book.h:82
const LevelNode * GetTrailingSellStopLevel(uint64_t price) const noexcept
Get the order book trailing sell stop level with the given price.
const Levels & sell_stop() const noexcept
Get the order book sell stop orders container.
Definition order_book.h:74
const LevelNode * GetBuyStopLevel(uint64_t price) const noexcept
Get the order book buy stop level with the given price.
const Levels & buy_stop() const noexcept
Get the order book buy stop orders container.
Definition order_book.h:72
Market manager definition.
UpdateType
Update type.
Definition update.h:21
C++ Trader project definitions.
Definition errors.h:16
Order book definition.
Level(LevelType type, uint64_t price) noexcept
Definition level.inl:30
uint64_t Price
Level price.
Definition level.h:36
Price level node.
Definition level.h:79
uint64_t Price
Order price.
Definition order.h:138
bool IsBuy() const noexcept
Is the order with buy side?
Definition order.h:231