From e8c910e52d1807e2fcca3b43d80a9df6acac5387 Mon Sep 17 00:00:00 2001 From: Joel Grunbaum <joelgrun@gmail.com> Date: Wed, 12 Jan 2022 06:26:46 +0000 Subject: [PATCH] write price level to each book --- book.py | 177 +++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 118 insertions(+), 59 deletions(-) diff --git a/book.py b/book.py index a506adb..50543ef 100644 --- a/book.py +++ b/book.py @@ -10,8 +10,8 @@ class OrderSide(Enum): """Order side enum.""" - Buy = 0, - Sell = 1 + Buy = "BUY", + Sell = "SELL" class ProductTypeEnum(Enum): @@ -37,14 +37,18 @@ 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: @@ -52,44 +56,97 @@ 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 @@ -100,7 +157,8 @@ 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: @@ -111,6 +169,13 @@ def __init__(self): """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: @@ -166,64 +231,58 @@ 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 -- Gitblit v1.9.3