CppTrader  1.0.4.0
C++ Trader
order_book.cpp
Go to the documentation of this file.
1 
11 
12 namespace CppTrader {
13 namespace Matching {
14 
15 OrderBook::OrderBook(MarketManager& manager, const Symbol& symbol)
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 
66 LevelNode* 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 
98 LevelNode* 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 
128 LevelUpdate 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 
157 LevelUpdate OrderBook::ReduceOrder(OrderNode* order_ptr, uint64_t quantity, uint64_t hidden, uint64_t visible)
158 {
159  // Find the price level for the order
160  LevelNode* level_ptr = order_ptr->Level;
161 
162  // Update the price level volume
163  level_ptr->TotalVolume -= quantity;
164  level_ptr->HiddenVolume -= hidden;
165  level_ptr->VisibleVolume -= visible;
166 
167  // Unlink the empty order from the orders list of the price level
168  if (order_ptr->LeavesQuantity == 0)
169  {
170  level_ptr->OrderList.pop_current(*order_ptr);
171  --level_ptr->Orders;
172  }
173 
174  Level level(*level_ptr);
175 
176  // Delete the empty price level
178  if (level_ptr->TotalVolume == 0)
179  {
180  // Clear the price level cache in the given order
181  order_ptr->Level = DeleteLevel(order_ptr);
182  update = UpdateType::DELETE;
183  }
184 
185  // Price level was changed. Return top of the book modification flag.
186  return LevelUpdate(update, level, ((order_ptr->Level == nullptr) || (order_ptr->Level == (order_ptr->IsBuy() ? _best_bid : _best_ask))));
187 }
188 
189 LevelUpdate OrderBook::DeleteOrder(OrderNode* order_ptr)
190 {
191  // Find the price level for the order
192  LevelNode* level_ptr = order_ptr->Level;
193 
194  // Update the price level volume
195  level_ptr->TotalVolume -= order_ptr->LeavesQuantity;
196  level_ptr->HiddenVolume -= order_ptr->HiddenQuantity();
197  level_ptr->VisibleVolume -= order_ptr->VisibleQuantity();
198 
199  // Unlink the empty order from the orders list of the price level
200  level_ptr->OrderList.pop_current(*order_ptr);
201  --level_ptr->Orders;
202 
203  Level level(*level_ptr);
204 
205  // Delete the empty price level
207  if (level_ptr->TotalVolume == 0)
208  {
209  // Clear the price level cache in the given order
210  order_ptr->Level = DeleteLevel(order_ptr);
211  update = UpdateType::DELETE;
212  }
213 
214  // Price level was changed. Return top of the book modification flag.
215  return LevelUpdate(update, level, ((order_ptr->Level == nullptr) || (order_ptr->Level == (order_ptr->IsBuy() ? _best_bid : _best_ask))));
216 }
217 
218 LevelNode* OrderBook::AddStopLevel(OrderNode* order_ptr)
219 {
220  LevelNode* level_ptr = nullptr;
221 
222  if (order_ptr->IsBuy())
223  {
224  // Create a new price level
225  level_ptr = _manager._level_pool.Create(LevelType::ASK, order_ptr->StopPrice);
226 
227  // Insert the price level into the buy stop orders collection
228  _buy_stop.insert(*level_ptr);
229 
230  // Update the best buy stop order price level
231  if ((_best_buy_stop == nullptr) || (level_ptr->Price < _best_buy_stop->Price))
232  _best_buy_stop = level_ptr;
233  }
234  else
235  {
236  // Create a new price level
237  level_ptr = _manager._level_pool.Create(LevelType::BID, order_ptr->StopPrice);
238 
239  // Insert the price level into the sell stop orders collection
240  _sell_stop.insert(*level_ptr);
241 
242  // Update the best sell stop order price level
243  if ((_best_sell_stop == nullptr) || (level_ptr->Price > _best_sell_stop->Price))
244  _best_sell_stop = level_ptr;
245  }
246 
247  return level_ptr;
248 }
249 
250 LevelNode* OrderBook::DeleteStopLevel(OrderNode* order_ptr)
251 {
252  // Find the price level for the order
253  LevelNode* level_ptr = order_ptr->Level;
254 
255  if (order_ptr->IsBuy())
256  {
257  // Update the best buy stop order price level
258  if (level_ptr == _best_buy_stop)
259  _best_buy_stop = (_best_buy_stop->right != nullptr) ? _best_buy_stop->right : _best_buy_stop->parent;
260 
261  // Erase the price level from the buy stop orders collection
262  _buy_stop.erase(Levels::iterator(&_buy_stop, level_ptr));
263  }
264  else
265  {
266  // Update the best sell stop order price level
267  if (level_ptr == _best_sell_stop)
268  _best_sell_stop = (_best_sell_stop->left != nullptr) ? _best_sell_stop->left : _best_sell_stop->parent;
269 
270  // Erase the price level from the sell stop orders collection
271  _sell_stop.erase(Levels::iterator(&_sell_stop, level_ptr));
272  }
273 
274  // Release the price level
275  _manager._level_pool.Release(level_ptr);
276 
277  return nullptr;
278 }
279 
280 void OrderBook::AddStopOrder(OrderNode* order_ptr)
281 {
282  // Find the price level for the order
283  LevelNode* level_ptr = order_ptr->IsBuy() ? (LevelNode*)GetBuyStopLevel(order_ptr->StopPrice) : (LevelNode*)GetSellStopLevel(order_ptr->StopPrice);
284 
285  // Create a new price level if no one found
286  if (level_ptr == nullptr)
287  level_ptr = AddStopLevel(order_ptr);
288 
289  // Update the price level volume
290  level_ptr->TotalVolume += order_ptr->LeavesQuantity;
291  level_ptr->HiddenVolume += order_ptr->HiddenQuantity();
292  level_ptr->VisibleVolume += order_ptr->VisibleQuantity();
293 
294  // Link the new order to the orders list of the price level
295  level_ptr->OrderList.push_back(*order_ptr);
296  ++level_ptr->Orders;
297 
298  // Cache the price level in the given order
299  order_ptr->Level = level_ptr;
300 }
301 
302 void OrderBook::ReduceStopOrder(OrderNode* order_ptr, uint64_t quantity, uint64_t hidden, uint64_t visible)
303 {
304  // Find the price level for the order
305  LevelNode* level_ptr = order_ptr->Level;
306 
307  // Update the price level volume
308  level_ptr->TotalVolume -= quantity;
309  level_ptr->HiddenVolume -= hidden;
310  level_ptr->VisibleVolume -= visible;
311 
312  // Unlink the empty order from the orders list of the price level
313  if (order_ptr->LeavesQuantity == 0)
314  {
315  level_ptr->OrderList.pop_current(*order_ptr);
316  --level_ptr->Orders;
317  }
318 
319  // Delete the empty price level
320  if (level_ptr->TotalVolume == 0)
321  {
322  // Clear the price level cache in the given order
323  order_ptr->Level = DeleteStopLevel(order_ptr);
324  }
325 }
326 
327 void OrderBook::DeleteStopOrder(OrderNode* order_ptr)
328 {
329  // Find the price level for the order
330  LevelNode* level_ptr = order_ptr->Level;
331 
332  // Update the price level volume
333  level_ptr->TotalVolume -= order_ptr->LeavesQuantity;
334  level_ptr->HiddenVolume -= order_ptr->HiddenQuantity();
335  level_ptr->VisibleVolume -= order_ptr->VisibleQuantity();
336 
337  // Unlink the empty order from the orders list of the price level
338  level_ptr->OrderList.pop_current(*order_ptr);
339  --level_ptr->Orders;
340 
341  // Delete the empty price level
342  if (level_ptr->TotalVolume == 0)
343  {
344  // Clear the price level cache in the given order
345  order_ptr->Level = DeleteStopLevel(order_ptr);
346  }
347 }
348 
349 LevelNode* OrderBook::AddTrailingStopLevel(OrderNode* order_ptr)
350 {
351  LevelNode* level_ptr = nullptr;
352 
353  if (order_ptr->IsBuy())
354  {
355  // Create a new price level
356  level_ptr = _manager._level_pool.Create(LevelType::ASK, order_ptr->StopPrice);
357 
358  // Insert the price level into the trailing buy stop orders collection
359  _trailing_buy_stop.insert(*level_ptr);
360 
361  // Update the best trailing buy stop order price level
362  if ((_best_trailing_buy_stop == nullptr) || (level_ptr->Price < _best_trailing_buy_stop->Price))
363  _best_trailing_buy_stop = level_ptr;
364  }
365  else
366  {
367  // Create a new price level
368  level_ptr = _manager._level_pool.Create(LevelType::BID, order_ptr->StopPrice);
369 
370  // Insert the price level into the trailing sell stop orders collection
371  _trailing_sell_stop.insert(*level_ptr);
372 
373  // Update the best trailing sell stop order price level
374  if ((_best_trailing_sell_stop == nullptr) || (level_ptr->Price > _best_trailing_sell_stop->Price))
375  _best_trailing_sell_stop = level_ptr;
376  }
377 
378  return level_ptr;
379 }
380 
381 LevelNode* OrderBook::DeleteTrailingStopLevel(OrderNode* order_ptr)
382 {
383  // Find the price level for the order
384  LevelNode* level_ptr = order_ptr->Level;
385 
386  if (order_ptr->IsBuy())
387  {
388  // Update the best trailing buy stop order price level
389  if (level_ptr == _best_trailing_buy_stop)
390  _best_trailing_buy_stop = (_best_trailing_buy_stop->right != nullptr) ? _best_trailing_buy_stop->right : _best_trailing_buy_stop->parent;
391 
392  // Erase the price level from the trailing buy stop orders collection
393  _trailing_buy_stop.erase(Levels::iterator(&_trailing_buy_stop, level_ptr));
394  }
395  else
396  {
397  // Update the best trailing sell stop order price level
398  if (level_ptr == _best_trailing_sell_stop)
399  _best_trailing_sell_stop = (_best_trailing_sell_stop->left != nullptr) ? _best_trailing_sell_stop->left : _best_trailing_sell_stop->parent;
400 
401  // Erase the price level from the trailing sell stop orders collection
402  _trailing_sell_stop.erase(Levels::iterator(&_trailing_sell_stop, level_ptr));
403  }
404 
405  // Release the price level
406  _manager._level_pool.Release(level_ptr);
407 
408  return nullptr;
409 }
410 
411 void OrderBook::AddTrailingStopOrder(OrderNode* order_ptr)
412 {
413  // Find the price level for the order
414  LevelNode* level_ptr = order_ptr->IsBuy() ? (LevelNode*)GetTrailingBuyStopLevel(order_ptr->StopPrice) : (LevelNode*)GetTrailingSellStopLevel(order_ptr->StopPrice);
415 
416  // Create a new price level if no one found
417  if (level_ptr == nullptr)
418  level_ptr = AddTrailingStopLevel(order_ptr);
419 
420  // Update the price level volume
421  level_ptr->TotalVolume += order_ptr->LeavesQuantity;
422  level_ptr->HiddenVolume += order_ptr->HiddenQuantity();
423  level_ptr->VisibleVolume += order_ptr->VisibleQuantity();
424 
425  // Link the new order to the orders list of the price level
426  level_ptr->OrderList.push_back(*order_ptr);
427  ++level_ptr->Orders;
428 
429  // Cache the price level in the given order
430  order_ptr->Level = level_ptr;
431 }
432 
433 void OrderBook::ReduceTrailingStopOrder(OrderNode* order_ptr, uint64_t quantity, uint64_t hidden, uint64_t visible)
434 {
435  // Find the price level for the order
436  LevelNode* level_ptr = order_ptr->Level;
437 
438  // Update the price level volume
439  level_ptr->TotalVolume -= quantity;
440  level_ptr->HiddenVolume -= hidden;
441  level_ptr->VisibleVolume -= visible;
442 
443  // Unlink the empty order from the orders list of the price level
444  if (order_ptr->LeavesQuantity == 0)
445  {
446  level_ptr->OrderList.pop_current(*order_ptr);
447  --level_ptr->Orders;
448  }
449 
450  // Delete the empty price level
451  if (level_ptr->TotalVolume == 0)
452  {
453  // Clear the price level cache in the given order
454  order_ptr->Level = DeleteTrailingStopLevel(order_ptr);
455  }
456 }
457 
458 void OrderBook::DeleteTrailingStopOrder(OrderNode* order_ptr)
459 {
460  // Find the price level for the order
461  LevelNode* level_ptr = order_ptr->Level;
462 
463  // Update the price level volume
464  level_ptr->TotalVolume -= order_ptr->LeavesQuantity;
465  level_ptr->HiddenVolume -= order_ptr->HiddenQuantity();
466  level_ptr->VisibleVolume -= order_ptr->VisibleQuantity();
467 
468  // Unlink the empty order from the orders list of the price level
469  level_ptr->OrderList.pop_current(*order_ptr);
470  --level_ptr->Orders;
471 
472  // Delete the empty price level
473  if (level_ptr->TotalVolume == 0)
474  {
475  // Clear the price level cache in the given order
476  order_ptr->Level = DeleteTrailingStopLevel(order_ptr);
477  }
478 }
479 
480 uint64_t OrderBook::CalculateTrailingStopPrice(const Order& order) const noexcept
481 {
482  // Get the current market price
483  uint64_t market_price = order.IsBuy() ? GetMarketTrailingStopPriceAsk() : GetMarketTrailingStopPriceBid();
484  int64_t trailing_distance = order.TrailingDistance;
485  int64_t trailing_step = order.TrailingStep;
486 
487  // Convert percentage trailing values into absolute ones
488  if (trailing_distance < 0)
489  {
490  trailing_distance = (int64_t)((-trailing_distance * market_price) / 10000);
491  trailing_step = (int64_t)((-trailing_step * market_price) / 10000);
492  }
493 
494  uint64_t old_price = order.StopPrice;
495 
496  if (order.IsBuy())
497  {
498  // Calculate a new stop price
499  uint64_t new_price = (market_price < (std::numeric_limits<uint64_t>::max() - trailing_distance)) ? (market_price + trailing_distance) : std::numeric_limits<uint64_t>::max();
500 
501  // If the new price is better and we get through the trailing step
502  if (new_price < old_price)
503  if ((old_price - new_price) >= (uint64_t)trailing_step)
504  return new_price;
505  }
506  else
507  {
508  // Calculate a new stop price
509  uint64_t new_price = (market_price > (uint64_t)trailing_distance) ? (market_price - trailing_distance) : 0;
510 
511  // If the new price is better and we get through the trailing step
512  if (new_price > old_price)
513  if ((new_price - old_price) >= (uint64_t)trailing_step)
514  return new_price;
515  }
516 
517  return old_price;
518 }
519 
520 } // namespace Matching
521 } // namespace CppTrader
const LevelNode * GetAsk(uint64_t price) const noexcept
Get the order book ask price level with the given price.
Definition: order_book.inl:32
OrderBook(MarketManager &manager, const Symbol &symbol)
Definition: order_book.cpp:15
const Levels & trailing_buy_stop() const noexcept
Get the order book trailing buy stop orders container.
Definition: order_book.h:82
const LevelNode * GetTrailingBuyStopLevel(uint64_t price) const noexcept
Get the order book trailing buy stop level with the given price.
Definition: order_book.inl:50
const Levels & buy_stop() const noexcept
Get the order book buy stop orders container.
Definition: order_book.h:72
const LevelNode * GetBid(uint64_t price) const noexcept
Get the order book bid price level with the given price.
Definition: order_book.inl:26
const LevelNode * GetSellStopLevel(uint64_t price) const noexcept
Get the order book sell stop level with the given price.
Definition: order_book.inl:44
const Levels & trailing_sell_stop() const noexcept
Get the order book trailing sell stop orders container.
Definition: order_book.h:84
const LevelNode * GetTrailingSellStopLevel(uint64_t price) const noexcept
Get the order book trailing sell stop level with the given price.
Definition: order_book.inl:56
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.
Definition: order_book.inl:38
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