Source code for oxberrypis.orderbook.book

"""Order book implementation.

Created on Apr 28, 2013

.. codeauthor:: Hynek Jemelik

"""
from ..errors import OrderBookError

from .fibonacci_heap import FibonacciHeap
from .linked_list import LinkedList


[docs]class OrderBook(object): """Order book. Keeps order in either demand or supply for single stock. """ def __init__(self): self.orders = {} self.limitbooks = {} self.book = self.create_book_structure() def create_book_structure(self): return FibonacciHeap() def create_limit_book_structure(self): return LinkedList() def get_best(self): if self.book.is_empty(): return None else: limitbook_node = self.book.front() limitbook = limitbook_node.data if limitbook.is_empty(): # Removing empty limit book self.book.extract() del self.limitbooks[abs(limitbook_node.key)] return self.get_best() else: return limitbook.front() def get_order_by_id(self, order_id): if order_id in self.orders: return self.orders[order_id].data else: return None def add_order(self, order): if order.id in self.orders: msg = 'Order {} already exists.'.format(order.id) raise OrderBookError(msg) if order.price not in self.limitbooks: limitbook = self.create_limit_book_structure() limitbook_node = self.book.insert(order.key(), limitbook) self.limitbooks[order.price] = limitbook_node else: limitbook = self.limitbooks[order.price].data order_node = limitbook.add(order) self.orders[order.id] = order_node def remove_order(self, order_id): if order_id not in self.orders: return order_node = self.orders[order_id] price = order_node.data.price limitbook = self.limitbooks[price].data limitbook.remove(order_node) # We might at this point remove limit book if it is empty, # but it might be better for performance reasons to keep it there. del self.orders[order_id] def update_order(self, updated_order): if updated_order.id not in self.orders: msg = 'Cannot update non-existing order {}.'.format(updated_order.id) raise OrderBookError(msg) order_node = self.orders[updated_order.id] order = order_node.data if updated_order.price == order.price: # We can do change locally inside limit book if updated_order.num_shares < order.num_shares: # Order stays at its position in queue order_node.data = updated_order else: # Order moves at the end of queue limitbook = self.limitbooks[order.price].data limitbook.remove(order_node) updated_order_node = limitbook.add(updated_order) self.orders[updated_order.id] = updated_order_node else: # Changing price is equivalent to removing and adding again self.remove_order(order.id) self.add_order(updated_order)