OnixS C++ Eurex T7 Market and Reference Data Interface (EMDI, RDI, EOBI) Handlers  8.1.0
API documentation
EobiOrderBookHolder.cpp
Go to the documentation of this file.
1 /*
2 * Copyright Onix Solutions Limited [OnixS]. All rights reserved.
3 *
4 * This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
5 * and international copyright treaties.
6 *
7 * Access to and use of the software is governed by the terms of the applicable ONIXS Software
8 * Services Agreement (the Agreement) and Customer end user license agreements granting
9 * a non-assignable, non-transferable and non-exclusive license to use the software
10 * for it's own data processing purposes under the terms defined in the Agreement.
11 *
12 * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
13 * of this source code or associated reference material to any other location for further reproduction
14 * or redistribution, and any amendments to this copyright notice, are expressly prohibited.
15 *
16 * Any reproduction or redistribution for sale or hiring of the Software not in accordance with
17 * the terms of the Agreement is a violation of copyright law.
18 */
19 
20 #include "EobiOrderBookHolder.h"
30 
31 #include <util/String.h>
32 
33 #include <boost/foreach.hpp>
34 
35 
36 namespace OnixS {
37 namespace Eurex {
38 namespace MarketData {
39 namespace EOBI {
40 namespace Implementation {
41 
42 
43 OrderBookCreator::OrderBookCreator(size_t bookDepth, OrderBookAllocator* bookAllocator) :
44  bookDepth_(bookDepth),
45  bookAllocator_(bookAllocator)
46 {
47  BOOST_ASSERT(bookAllocator_!= nullptr);
48 }
49 
51  bookDepth_(other.bookDepth_),
52  bookAllocator_(other.bookAllocator_)
53 {
54  BOOST_ASSERT(bookAllocator_!= nullptr);
55 };
56 
57 boost::shared_ptr<OrderBookInternal> OrderBookCreator::operator()(const SecurityId& id) const
58 {
59  BOOST_ASSERT(bookAllocator_!= nullptr);
60  void* location = bookAllocator_->alloc();
61  BOOST_ASSERT(location != nullptr);
62 
63  if(location == nullptr)
64  throw std::logic_error("EOBI book memory exhausted.");
65 
66  return boost::shared_ptr<OrderBookInternal>(new(location) OrderBookInternal(id, bookDepth_, bookDepth_));
67 }
68 
70 {
71  OnixS::HandlerCore::MarketData::FullOrderDepthBookCreator<OrderBookInternal, false>::reset();
72 }
73 
74 OrderBookHolder::OrderBookHolder(const OnOrderBookUpdatedCallback& onOrderBookUpdated, OrderBookAllocator* bookAllocator, size_t bookDepth) :
75  impl_(new BookRegistry(OrderBookCreator(bookDepth, bookAllocator))),
76  onOrderBookUpdated_(onOrderBookUpdated)
77 {
78  BOOST_ASSERT(bookAllocator != nullptr);
79  BOOST_ASSERT(bookDepth > 0);
80 }
81 
83 {
84  const bool complete = message.dataSource().completionIndicator;
85 
86  BOOST_ASSERT(impl_.get() != nullptr);
87 
88  BookPtr bookPtr = impl_->get(message.securityID());
89 
90  if(!bookPtr)
91  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", message.securityID()).c_str());
92 
93  Decimal price;
94  message.price(price);
95 
96  if(message.side() == EOBI::Side::Sell)
97  {
98  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSTimePriority(), false);
99  bookPtr->askOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
100 
101  BOOST_ASSERT(bookPtr->askOrders().levels().size() <= bookPtr->depth());
102  }
103  else if(message.side() == EOBI::Side::Buy)
104  {
105  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSTimePriority(), false);
106  bookPtr->bidOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
107 
108  BOOST_ASSERT(bookPtr->bidOrders().levels().size() <= bookPtr->depth());
109  }
110  else
111  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
112 
113  books_.insert(bookPtr);
114 
115  updateBook(bookPtr, complete);
116 }
117 
118 namespace {
119  struct FindById : public std::binary_function<const Order*, UInt64, bool>
120  {
121  bool operator()(const Order* order, UInt64 id) const
122  {
123  BOOST_ASSERT(order != nullptr);
124  return (order->id_ == id);
125  }
126  };
127 }
128 
129 template <typename OrderList>
130 void OrderBookHolder::checkOrderExistence(const OrderList& list, UInt64 orderId, bool shouldExist)
131 {
132  typename OrderList::const_iterator pos = std::find_if(list.begin(), list.end(), std::bind2nd(FindById(), orderId));
133 
134  if(shouldExist)
135  if(pos == list.end())
136  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Order does not exist, %llu", orderId).c_str());
137 
138  if(!shouldExist)
139  if(pos != list.end())
140  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Order already exists, %llu", orderId).c_str());
141 }
142 
144 {
145  const bool complete = message.dataSource().completionIndicator;
146 
147  BOOST_ASSERT(impl_.get() != nullptr);
148 
149  BookPtr bookPtr = impl_->get(message.securityID());
150 
151  if(!bookPtr)
152  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", message.securityID()).c_str());
153 
154  Decimal price;
155  message.price(price);
156 
157  if(message.trdRegTSTimePriority() == 0)
158  {
159  if(message.side() == EOBI::Side::Sell)
160  {
161  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSPrevTimePriority(), true);
162  bookPtr->askOrders().update(Order(message.trdRegTSPrevTimePriority(), price, message.displayQty()));
163  }
164  else if(message.side() == EOBI::Side::Buy)
165  {
166  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSPrevTimePriority(), true);
167  bookPtr->bidOrders().update(Order(message.trdRegTSPrevTimePriority(), price, message.displayQty()));
168  }
169  else
170  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
171  }
172  else
173  {
174  if(message.side() == EOBI::Side::Sell)
175  {
176  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSPrevTimePriority(), true);
177  bookPtr->askOrders().remove(message.trdRegTSPrevTimePriority());
178  bookPtr->askOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
179  }
180  else if(message.side() == EOBI::Side::Buy)
181  {
182  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSPrevTimePriority(), true);
183  bookPtr->bidOrders().remove(message.trdRegTSPrevTimePriority());
184  bookPtr->bidOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
185  }
186  else
187  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
188  }
189 
190  updateBook(bookPtr, complete);
191 }
192 
194 {
195  const bool complete = message.dataSource().completionIndicator;
196 
197  BOOST_ASSERT(impl_.get() != nullptr);
198 
199  BookPtr bookPtr = impl_->get(message.securityID());
200 
201  if(!bookPtr)
202  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", message.securityID()).c_str());
203 
204  Decimal price;
205  message.price(price);
206 
207  if(message.side() == EOBI::Side::Sell)
208  {
209  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSTimePriority(), true);
210  bookPtr->askOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
211  }
212  else if(message.side() == EOBI::Side::Buy)
213  {
214  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSTimePriority(), true);
215  bookPtr->bidOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
216  }
217  else
218  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
219 
220  updateBook(bookPtr, complete);
221 }
222 
224 {
225  const bool complete = message.dataSource().completionIndicator;
226 
227  BOOST_ASSERT(impl_.get() != nullptr);
228 
229  BookPtr bookPtr = impl_->get(message.securityID());
230 
231  if(!bookPtr)
232  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", message.securityID()).c_str());
233 
234  if(message.side() == EOBI::Side::Sell)
235  {
236  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSTimePriority(), true);
237  bookPtr->askOrders().remove(message.trdRegTSTimePriority());
238  }
239  else if(message.side() == EOBI::Side::Buy)
240  {
241  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSTimePriority(), true);
242  bookPtr->bidOrders().remove(message.trdRegTSTimePriority());
243  }
244  else
245  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
246 
247  updateBook(bookPtr, complete);
248 }
249 
251 {
252  const bool complete = message.dataSource().completionIndicator;
253 
254  BOOST_ASSERT(impl_.get() != nullptr);
255 
256  emptyBook(message.securityID(), complete);
257 }
258 
259 void OrderBookHolder::emptyBook(SecurityId securityId, bool complete)
260 {
261  BookPtr bookPtr = impl_->get(securityId);
262 
263  if(!bookPtr)
264  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", securityId).c_str());
265 
266  bookPtr->clear();
267 
268  updateBook(bookPtr, complete);
269 }
270 
272 {
273  const bool complete = message.dataSource().completionIndicator;
274 
275  BOOST_ASSERT(impl_.get() != nullptr);
276 
277  BookPtr bookPtr = impl_->get(message.securityID());
278 
279  if(!bookPtr)
280  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", message.securityID()).c_str());
281 
282  if(message.side() == EOBI::Side::Sell)
283  {
284  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSTimePriority(), true);
285  const Order& order = bookPtr->askOrders().find(message.trdRegTSTimePriority());
286 
287  const Quantity newQuantity = order.quantity_ - message.lastQty();
288  if(newQuantity != 0)
289  bookPtr->askOrders().update(Order(message.trdRegTSTimePriority(), order.price_, newQuantity));
290  else
291  bookPtr->askOrders().remove(message.trdRegTSTimePriority());
292  }
293  else if(message.side() == EOBI::Side::Buy)
294  {
295  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSTimePriority(), true);
296  const Order& order = bookPtr->bidOrders().find(message.trdRegTSTimePriority());
297 
298  const Quantity newQuantity = order.quantity_ - message.lastQty();
299  if(newQuantity != 0)
300  bookPtr->bidOrders().update(Order(message.trdRegTSTimePriority(), order.price_, newQuantity));
301  else
302  bookPtr->bidOrders().remove(message.trdRegTSTimePriority());
303  }
304 
305  updateBook(bookPtr, complete);
306 }
307 
309 {
310  const bool complete = message.dataSource().completionIndicator;
311 
312  BOOST_ASSERT(impl_.get() != nullptr);
313 
314  BookPtr bookPtr = impl_->get(message.securityID());
315 
316  if(!bookPtr)
317  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", message.securityID()).c_str());
318 
319  if(message.side() == EOBI::Side::Sell)
320  {
321  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSTimePriority(), true);
322  bookPtr->askOrders().remove(message.trdRegTSTimePriority());
323  }
324  else if(message.side() == EOBI::Side::Buy)
325  {
326  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSTimePriority(), true);
327  bookPtr->bidOrders().remove(message.trdRegTSTimePriority());
328  }
329  else
330  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
331 
332  updateBook(bookPtr, complete);
333 }
334 
336 {
337  const bool complete = message.dataSource().completionIndicator;
338 
339  BOOST_ASSERT(impl_.get() != nullptr);
340  //BOOST_ASSERT(message.price() != Decimal(0));
341 
342  BookPtr bookPtr = impl_->get(secId);
343 
344  if(!bookPtr)
345  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown security id: %d", secId).c_str());
346 
347  Decimal price;
348  message.price(price);
349 
350  if(message.side() == EOBI::Side::Sell)
351  {
352  checkOrderExistence(bookPtr->askOrders().orders(), message.trdRegTSTimePriority(), false);
353  bookPtr->askOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
354  }
355  else if(message.side() == EOBI::Side::Buy)
356  {
357  checkOrderExistence(bookPtr->bidOrders().orders(), message.trdRegTSTimePriority(), false);
358  bookPtr->bidOrders().update(Order(message.trdRegTSTimePriority(), price, message.displayQty()));
359  }
360  else
361  throw OperationException (BOOST_CURRENT_FUNCTION, OnixS::Util::format("Unknown side, %d", message.side()).c_str());
362 
363  books_.insert(bookPtr);
364 
365  updateBook(bookPtr, complete);
366 }
367 
369 {
370  BOOST_ASSERT(impl_.get() != nullptr);
371 
372  /*
373  books_.clear();
374  impl_->clear();
375  */
376 
377  BOOST_FOREACH(BookPtr ptr, books_)
378  {
379  BOOST_ASSERT(ptr);
380  ptr->clear();
381  }
382 
383  books_.clear();
384 }
385 
386 void OrderBookHolder::onInactivity(const boost::function<void(const OrderBookInternal&)>& onOrderBookOutOfDate)
387 {
388  BOOST_FOREACH(BookPtr ptr, books_)
389  {
390  BOOST_ASSERT(ptr);
391  onOrderBookOutOfDate(*ptr);
392  }
393 }
394 
395 void OrderBookHolder::updateBook(BookPtr bookPtr, bool complete)
396 {
397  if(complete)
398  {
399  pendingChangedBooks_.insert(bookPtr);
400  updatePendingBooks();
401  }
402  else
403  pendingChangedBooks_.insert(bookPtr);
404 }
405 
406 void OrderBookHolder::updatePendingBooks()
407 {
408  while(!pendingChangedBooks_.empty())
409  {
410  BookPtr ptr = *pendingChangedBooks_.begin();
411 
412  onOrderBookUpdated_(*ptr);
413 
414  pendingChangedBooks_.erase(pendingChangedBooks_.begin());
415  }
416 }
417 
418 
419 
420 }}}}}
421 
422 
QuantityType displayQty() const
Quantity.
QuantityType displayQty() const
Quantity.
Definition: OrderModify.cpp:93
void onOrderModifySamePriority(const EOBI::OrderModifySamePriority &)
const DataSource & dataSource() const
Returns data source.
Definition: MessageBase.h:56
EOBI::Side::Enum side() const
Side of the order.
bool price(Decimal &price) const
Price.
UInt64 trdRegTSTimePriority() const
Priority timestamp.
void onPartialOrderExecution(const EOBI::PartialOrderExecution &)
UInt64 trdRegTSTimePriority() const
Priority timestamp (new)
Definition: OrderModify.cpp:73
void onInactivity(const boost::function< void(const OrderBookInternal &)> &onOrderBookOutOfDate)
QuantityType lastQty() const
Quantity executed in this fill.
UInt64 trdRegTSPrevTimePriority() const
Previous order priority timestamp.
Definition: OrderModify.cpp:68
Definition: Defines.h:30
Decimal type for better precision.
Definition: Numeric.h:63
EOBI::Side::Enum side() const
Side of the order.
Int64 SecurityId
Alias for Security Id type.
Definition: Defines.h:51
OrderBookHolder(const OnOrderBookUpdatedCallback &onOrderBookUpdated, OrderBookAllocator *bookAllocator, size_t bookDepth=DefaultBookDepth)
void onSnapshotOrder(const EOBI::SnapshotOrder &, SecurityId secId)
EOBI::Side::Enum side() const
Side of the order.
UInt64 trdRegTSTimePriority() const
Priority timestamp.
Definition: OrderDelete.cpp:68
EOBI::Side::Enum side() const
Side of the order.
Definition: OrderModify.cpp:58
UInt64 securityID() const
Unique instrument identifier.
Definition: OrderAdd.cpp:58
UInt64 securityID() const
Unique instrument identifier.
UInt64 trdRegTSTimePriority() const
Priority timestamp (new)
UInt64 securityID() const
Unique instrument identifier.
Definition: OrderDelete.cpp:58
OrderBookCreator(size_t bookDepth, OrderBookAllocator *bookAllocator)
UInt64 trdRegTSTimePriority() const
Priority timestamp.
Definition: OrderAdd.cpp:63
UInt64 trdRegTSTimePriority() const
Priority timestamp.
EOBI::Side::Enum side() const
Side of the order.
Definition: OrderAdd.cpp:73
boost::shared_ptr< OrderBookInternal > operator()(const SecurityId &id) const
UInt64 securityID() const
Unique instrument identifier.
UInt64 securityID() const
Unique instrument identifier.
bool price(Decimal &price) const
Price.
Definition: OrderAdd.cpp:83
OrderBookRegistry< SecurityId, OrderBookInternal, OrderBookCreator > BookRegistry
boost::function< void(const OrderBookInternal &)> OnOrderBookUpdatedCallback
EOBI::Side::Enum side() const
Side of the order.
Definition: OrderDelete.cpp:78
UInt64 Quantity
Alias for Quantity type.
Definition: Defines.h:54
EOBI::Side::Enum side() const
Side of the order. Value Description: 1 Buy, 2 Sell.
QuantityType displayQty() const
Quantity.
Definition: OrderAdd.cpp:68
UInt64 securityID() const
Unique instrument identifier.
Definition: OrderModify.cpp:53
bool price(Decimal &price) const
Price.
UInt64 securityID() const
Unique instrument identifier.