|  |  | 
 |  |  | class OrderSide(Enum): | 
 |  |  |     """Order side enum.""" | 
 |  |  |  | 
 |  |  |     Buy = 0, | 
 |  |  |     Sell = 1 | 
 |  |  |     Buy = "BUY", | 
 |  |  |     Sell = "SELL" | 
 |  |  |  | 
 |  |  |  | 
 |  |  | class ProductTypeEnum(Enum): | 
 |  |  | 
 |  |  |     side: OrderSide | 
 |  |  |     remaining_volume: int | 
 |  |  |     filled_volume: int | 
 |  |  |     timestamp: float | 
 |  |  |     id: str | 
 |  |  |  | 
 |  |  |     def __init__(self, price: decimal.Decimal(3), side: OrderSide, | 
 |  |  |                  volume: int): | 
 |  |  |                  volume: int, timestamp: float, id: str): | 
 |  |  |         """Initialise class.""" | 
 |  |  |         self.price = price | 
 |  |  |         self.side = side | 
 |  |  |         self.remaining_volume = volume | 
 |  |  |         self.filled_volume = 0 | 
 |  |  |         self.timestamp = timestamp | 
 |  |  |         self.id = id | 
 |  |  |  | 
 |  |  |  | 
 |  |  | class Level: | 
 |  |  | 
 |  |  |  | 
 |  |  |     price: decimal.Decimal | 
 |  |  |     volume: int | 
 |  |  |     side: OrderSide | 
 |  |  |     timestamp: float | 
 |  |  |     id: str | 
 |  |  |  | 
 |  |  |     def __init__(self, price: decimal.Decimal(3), volume): | 
 |  |  |     def __init__(self, order: Order): | 
 |  |  |         """Initialise class.""" | 
 |  |  |         self.priority = int(price) | 
 |  |  |         self.price = price | 
 |  |  |         self.volume = volume | 
 |  |  |         self.price = order.price | 
 |  |  |         self.volume = order.remaining_volume | 
 |  |  |         self.side = order.side | 
 |  |  |         self.timestamp = order.timestamp | 
 |  |  |         self.id = order.id | 
 |  |  |  | 
 |  |  |     def __lt__(self, other): | 
 |  |  |         """Less than comparator.""" | 
 |  |  |         if (self.price < other.price): | 
 |  |  |             return True | 
 |  |  |         if (self.side == OrderSide.Sell): | 
 |  |  |             if (self.price < other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp < other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |         else: | 
 |  |  |             return False | 
 |  |  |             if (self.price > other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp < other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |  | 
 |  |  |     def __gt__(self, other): | 
 |  |  |         """Greater than comparator.""" | 
 |  |  |         if (self.price > other.price): | 
 |  |  |             return True | 
 |  |  |         if (self.side == OrderSide.Sell): | 
 |  |  |             if (self.price > other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp < other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |         else: | 
 |  |  |             return False | 
 |  |  |             if (self.price < other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp < other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |  | 
 |  |  |     def __le__(self, other): | 
 |  |  |         """Less than or equal compatator.""" | 
 |  |  |         if (self.price <= other.price): | 
 |  |  |             return True | 
 |  |  |         if (self.side == OrderSide.Sell): | 
 |  |  |             if (self.price <= other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp <= other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |         else: | 
 |  |  |             return False | 
 |  |  |             if (self.price >= other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp <= other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |  | 
 |  |  |     def __ge__(self, other): | 
 |  |  |         """Greater than or equal comparator.""" | 
 |  |  |         if (self.price >= other.price): | 
 |  |  |             return True | 
 |  |  |         if (self.side == OrderSide.Sell): | 
 |  |  |             if (self.price >= other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp <= other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |         else: | 
 |  |  |             return False | 
 |  |  |             if (self.price <= other.price): | 
 |  |  |                 return True | 
 |  |  |             elif (self.price == other.price and | 
 |  |  |                   self.timestamp <= other.timestamp): | 
 |  |  |                 return True | 
 |  |  |             else: | 
 |  |  |                 return False | 
 |  |  |  | 
 |  |  |     def __eq__(self, other): | 
 |  |  |         """Equalty compatator.""" | 
 |  |  |         if (self.price == other.price): | 
 |  |  |         if (self.price == other.price and self.timestamp == other.timestamp): | 
 |  |  |             return True | 
 |  |  |         else: | 
 |  |  |             return False | 
 |  |  | 
 |  |  |  | 
 |  |  |     def __str__(self): | 
 |  |  |         """Turn into str for printing.""" | 
 |  |  |         return "Price: " + str(self.price) + ", volume: " + str(self.volume) | 
 |  |  |         return ("Price: " + str(self.price) + ", volume: " + str(self.volume) + | 
 |  |  |                 ", time: " + str(self.timestamp) + ", id: " + self.id) | 
 |  |  |  | 
 |  |  |  | 
 |  |  | class Side: | 
 |  |  | 
 |  |  |         """Initialise class.""" | 
 |  |  |         self.levels = [] | 
 |  |  |  | 
 |  |  |     def delete(self, orderId: str): | 
 |  |  |         """Delete order from side.""" | 
 |  |  |         for i in self.levels: | 
 |  |  |             if (i.id == orderId): | 
 |  |  |                 self.levels.remove(i) | 
 |  |  |                 heapq.heapify(self.levels) | 
 |  |  |  | 
 |  |  |  | 
 |  |  | class Book: | 
 |  |  |     """Book class.""" | 
 |  |  | 
 |  |  |     def ask(self, order: Order): | 
 |  |  |         """Add ask to book.""" | 
 |  |  |         while(len(self.bidSide.levels) > 0 and | 
 |  |  |               self.bidSide.levels[0][1].price >= order.price): | 
 |  |  |             if (self.bidSide.levels[0][1].volume > order.remaining_volume): | 
 |  |  |                 temp = self.bidSide.levels[0][1].volume | 
 |  |  |                 order.filled_volume += self.bidSide.levels[0][1].volume | 
 |  |  |                 self.bidSide.levels[0][1].volume -= order.remaining_volume | 
 |  |  |               self.bidSide.levels[0].price >= order.price): | 
 |  |  |             if (self.bidSide.levels[0].volume > order.remaining_volume): | 
 |  |  |                 temp = self.bidSide.levels[0].volume | 
 |  |  |                 order.filled_volume += self.bidSide.levels[0].volume | 
 |  |  |                 self.bidSide.levels[0].volume -= order.remaining_volume | 
 |  |  |                 order.remaining_volume -= temp | 
 |  |  |                 break | 
 |  |  |             else: | 
 |  |  |                 order.remaining_volume -= self.bidSide.levels[0][1].volume | 
 |  |  |                 order.filled_volume += self.bidSide.levels[0][1].volume | 
 |  |  |                 order.remaining_volume -= self.bidSide.levels[0].volume | 
 |  |  |                 order.filled_volume += self.bidSide.levels[0].volume | 
 |  |  |                 heapq.heappop(self.bidSide.levels) | 
 |  |  |         if (order.remaining_volume > 0): | 
 |  |  |             if (len(self.askSide.levels) > 0 and | 
 |  |  |                     self.askSide.levels[0][1].price == order.price): | 
 |  |  |                 self.askSide.levels[0][1].addVolume(order.remaining_volume) | 
 |  |  |             else: | 
 |  |  |                 heapq.heappush(self.askSide.levels, | 
 |  |  |                                (order.price, | 
 |  |  |                                 Level(order.price, order.remaining_volume))) | 
 |  |  |             heapq.heappush(self.askSide.levels, Level(order)) | 
 |  |  |  | 
 |  |  |     def bid(self, order: Order): | 
 |  |  |         """Add bid to book.""" | 
 |  |  |         while(len(self.askSide.levels) > 0 and | 
 |  |  |               self.askSide.levels[0][1].price <= order.price): | 
 |  |  |             if (self.askSide.levels[0][1].volume > order.remaining_volume): | 
 |  |  |                 temp = self.askSide.levels[0][1].volume | 
 |  |  |                 order.filled_volume += self.askSide.levels[0][1].volume | 
 |  |  |                 self.askSide.levels[0][1].volume -= order.remaining_volume | 
 |  |  |               self.askSide.levels[0].price <= order.price): | 
 |  |  |             if (self.askSide.levels[0].volume > order.remaining_volume): | 
 |  |  |                 temp = self.askSide.levels[0].volume | 
 |  |  |                 order.filled_volume += self.askSide.levels[0].volume | 
 |  |  |                 self.askSide.levels[0].volume -= order.remaining_volume | 
 |  |  |                 order.remaining_volume -= temp | 
 |  |  |                 break | 
 |  |  |             else: | 
 |  |  |                 order.remaining_volume -= self.askSide.levels[0][1].volume | 
 |  |  |                 order.filled_volume -= self.askSide.levels[0][1].volume | 
 |  |  |                 order.remaining_volume -= self.askSide.levels[0].volume | 
 |  |  |                 order.filled_volume -= self.askSide.levels[0].volume | 
 |  |  |                 heapq.heappop(self.askSide.levels) | 
 |  |  |         if (order.remaining_volume > 0): | 
 |  |  |             if (len(self.bidSide.levels) > 0 and | 
 |  |  |                     self.bidSide.levels[0][1].price == order.price): | 
 |  |  |                 self.bidSide.levels[0][1].addVolume(order.remaining_volume) | 
 |  |  |             else: | 
 |  |  |                 heapq.heappush(self.bidSide.levels, | 
 |  |  |                                (100 - order.price, | 
 |  |  |                                 Level(order.price, order.remaining_volume))) | 
 |  |  |             heapq.heappush(self.bidSide.levels, Level(order)) | 
 |  |  |  | 
 |  |  |     def printBook(self): | 
 |  |  |         """Test print book. Book is a heap so not strictly sorted.""" | 
 |  |  |         print("Sell side") | 
 |  |  |         for i in sorted(self.askSide.levels, reverse=True): | 
 |  |  |             print(i[1]) | 
 |  |  |         for i in sorted(self.askSide.levels, reverse=True)[-10:]: | 
 |  |  |             print(i) | 
 |  |  |         print("Buy side") | 
 |  |  |         for i in sorted(self.bidSide.levels): | 
 |  |  |             print(str(i[1])) | 
 |  |  |         for i in sorted(self.bidSide.levels)[:10]: | 
 |  |  |             print(str(i)) | 
 |  |  |  | 
 |  |  |  | 
 |  |  | def testBook(): | 
 |  |  | def testBook(orders: int = 10, printBook=True): | 
 |  |  |     """Test an example book.""" | 
 |  |  |     b = Book() | 
 |  |  |     for i in range(1, 10): | 
 |  |  |         b.addOrder(Order(i, OrderSide.Buy, 10)) | 
 |  |  |     for i in range(11, 20): | 
 |  |  |         b.addOrder(Order(i, OrderSide.Sell, 10)) | 
 |  |  |     b.printBook() | 
 |  |  |     time = 1 | 
 |  |  |     for i in range(1, orders): | 
 |  |  |         b.addOrder(Order(price=i, side=OrderSide.Buy, volume=10, | 
 |  |  |                          timestamp=time, id="a")) | 
 |  |  |         time += 1 | 
 |  |  |     for i in range(orders + 1, 2 * orders): | 
 |  |  |         b.addOrder(Order(i, OrderSide.Sell, 10, time, "a")) | 
 |  |  |         time += 1 | 
 |  |  |     if (printBook): | 
 |  |  |         b.printBook() | 
 |  |  |     return b |