OnixS C++ Eurex T7 Market and Reference Data Interface (EMDI, RDI, EOBI) Handlers  8.1.0
API documentation
BookSanityChecker.h
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 #pragma once
20 
21 #include <boost/current_function.hpp>
22 
26 
27 
28 namespace OnixS {
29 namespace Eurex {
30 namespace MarketData {
31 namespace Implementation
32 {
34 
35 template<typename OderBook>
37 {
38 public:
39  explicit
40  SanityChecker(const OderBook &book) : book_(book)
41  {
42  }
43 
44  void checkSanity() const
45  {
46  checkAsksSanity();
47  checkBidsSanity();
48  }
49 
51  {
52  bool hasBestAsk = false;
53  Decimal bestAskPrice;
54 
55  if (!book_.asks().empty())
56  {
57  QuantityType bestAskQuantity = 0;
58 
59  hasBestAsk = book_.bestAsk(bestAskPrice, bestAskQuantity);
60 
61  if (!hasBestAsk)
62  throw OperationException(BOOST_CURRENT_FUNCTION, "best ask does not exist");
63 
64  if (bestAskQuantity == 0)
65  throw OperationException(BOOST_CURRENT_FUNCTION, "bestAskQuantity is zero");
66  }
67 
68 
69  bool hasBestBid = false;
70  Decimal bestBidPrice;
71 
72  if (!book_.bids().empty())
73  {
74  QuantityType bestBidQuantity = 0;
75  hasBestBid = book_.bestBid(bestBidPrice, bestBidQuantity);
76 
77  if (!hasBestBid)
78  throw OperationException(BOOST_CURRENT_FUNCTION, "best bid does not exist");
79 
80  if (bestBidQuantity == 0)
81  throw OperationException(BOOST_CURRENT_FUNCTION, "bestBidQuantity is zero");
82  }
83 
84  if ((hasBestAsk && hasBestBid) && !(bestBidPrice < bestAskPrice))
85  throw OperationException(BOOST_CURRENT_FUNCTION, "bid is not less than ask");
86  }
87 
88 private:
89  void checkAsksSanity() const
90  {
91  const typename OderBook::PriceLevelsType &asksLevels = book_.asks();
92 
93  if (asksLevels.empty())
94  return;
95 
96  if (asksLevels.size() > book_.depth())
97  throw OperationException(BOOST_CURRENT_FUNCTION, "asks size exceed book depth");
98 
99 
100  for (typename OderBook::PriceLevelsType::const_iterator pos = asksLevels.begin(), end = asksLevels.end(); pos != end; ++pos)
101  {
102  if (pos->quantity() <= 0)
103  throw OperationException(BOOST_CURRENT_FUNCTION, "quantity is not a positive number");
104  }
105 
106  for (size_t i = 1; i < asksLevels.size(); ++i)
107  {
108  if (!isValid(asksLevels.at(i)))
109  throw OperationException(BOOST_CURRENT_FUNCTION, "invalid price level");
110  }
111 
112  for (size_t i = 1; i < asksLevels.size(); ++i)
113  {
114  if (asksLevels.at(i).price() != Decimal(0))
115  {
116  if (asksLevels.at(i - 1).price() >= asksLevels.at(i).price())
117  throw OperationException(BOOST_CURRENT_FUNCTION, "wrong price level order");
118  }
119  }
120  }
121 
122  void checkBidsSanity() const
123  {
124  const typename OderBook::PriceLevelsType &bidsLevels = book_.bids();
125 
126  if (bidsLevels.empty())
127  return;
128 
129  if (bidsLevels.size() > book_.depth())
130  throw OperationException(BOOST_CURRENT_FUNCTION, "bids size exceed book depth");
131 
132  for (typename OderBook::PriceLevelsType::const_iterator pos = bidsLevels.begin(), end = bidsLevels.end(); pos != end; ++pos)
133  {
134  if (pos->quantity() <= 0)
135  throw OperationException(BOOST_CURRENT_FUNCTION, "quantity is not a positive number");
136  }
137 
138  for (size_t i = 1; i < bidsLevels.size(); ++i)
139  {
140  if (!isValid(bidsLevels.at(i)))
141  throw OperationException(BOOST_CURRENT_FUNCTION, "invalid price level");
142  }
143 
144  for (size_t i = 1; i < bidsLevels.size(); ++i)
145  {
146  if (bidsLevels.at(i).price() != Decimal(0.0f, 0u))
147  {
148  if (bidsLevels.at(i - 1).price() <= bidsLevels.at(i).price())
149  throw OperationException(BOOST_CURRENT_FUNCTION, "wrong price level order");
150  }
151  }
152  }
153 
154 private:
155  const OderBook &book_;
156 };
157 
158 
159 }}}}
Definition: Defines.h:30
Decimal type for better precision.
Definition: Numeric.h:63
bool isValid(const PriceLevel &level)
Definition: OrderBook.cpp:63