def test_orders_of_the_same_id(self): order1 = Order((1, "Limit", "Buy", 100, 100, 0)) order2 = Order((1, "Limit", "Buy", 200, 300, 0)) self.assertRaises(ValueError, order1.__eq__, order2) order2 = Order((1, "Limit", "Buy", 100, 100, 0)) self.assertEqual(order1, order2)
def test_order_book_not_storing_transactions(self): order_book = OrderBook(store_transactions=False) order_book.add(Order((1, "Limit", "Buy", 100, 100, 0))) self.assertEqual(order_book.last_transactions, []) order_book.add(Order((2, "Limit", "Sell", 100, 100, 0))) self.assertEqual(order_book.last_transactions, []) self.assertEqual(order_book.get_state(), '{"buyOrders": [], "sellOrders": []}')
def test_sell_order_comparison(self): order1 = Order((1, "Limit", "Sell", 20, 100, 0)) order2 = Order((2, "Limit", "Sell", 30, 100, 0)) self.assertLess(order1, order2) order2 = Order((2, "Limit", "Sell", 10, 100, 0)) self.assertLess(order2, order1) order2 = Order((2, "Limit", "Sell", 20, 100, 0)) self.assertLess(order1, order2)
def test_order_simple_dictionary(self): order = Order((1, "Iceberg", "Sell", 30, 100, 10)) order_dictionary = order.__dict__() self.assertEqual(order_dictionary.get('id'), 1) self.assertEqual(order_dictionary.get('price'), 30) self.assertEqual(order_dictionary.get('quantity'), 10) self.assertEqual(order_dictionary.get('peak'), None) self.assertEqual(order_dictionary.get('direction'), None) self.assertEqual(order_dictionary.get('type'), None)
def test_order_detailed_dictionary(self): order = Order((1, "Iceberg", "Sell", 30, 100, 10)) order_dictionary = order.__dict__(simple=False) order_info_dictionary = order_dictionary.get('order') self.assertEqual(order_info_dictionary.get('id'), 1) self.assertEqual(order_info_dictionary.get('price'), 30) self.assertEqual(order_info_dictionary.get('quantity'), 10) self.assertEqual(order_info_dictionary.get('peak'), 10) self.assertEqual(order_info_dictionary.get('direction'), "Sell") self.assertEqual(order_dictionary.get('type'), "Iceberg")
def test_order_book_cancel_order(self): order_book = OrderBook() order = Order((1, "Limit", "Buy", 100, 100, 0)) order_book.add(order) order_book.cancel(order) self.assertEqual(order_book.get_state(), '{"buyOrders": [], "sellOrders": []}')
def test_correct_limit_tuple(self): order = Order((1, "Limit", "Buy", 100, 100, 0)) self.assertEqual(order.id, 1) self.assertEqual(order.type, "Limit") self.assertEqual(order.direction, "Buy") self.assertEqual(order.quantity, 100) self.assertEqual(order.hidden_quantity, 0) self.assertEqual(order.price, 100)
def test_order_book_add_order(self): order_book = OrderBook() order = Order((1, "Limit", "Buy", 100, 100, 0)) order_book.add(order) self.assertEqual( order_book.get_state(), '{"buyOrders": [{"id": 1, "price": 100, "quantity": 100}], "sellOrders": []}' )
def test_order_book_limit_transactions(self): order_book = OrderBook(store_transactions=True) order_book.add(Order((1, "Limit", "Buy", 100, 100, 0))) self.assertEqual(order_book.last_transactions, []) order_book.add(Order((2, "Limit", "Sell", 80, 50, 0))) self.assertEqual(order_book.last_transactions, [ '{"buyOrderId": 1, "sellOrderId": 2, "price": 100, "quantity": 50}' ]) order_book.add(Order((3, "Limit", "Sell", 120, 40, 0))) self.assertEqual(order_book.last_transactions, []) self.assertEqual( order_book.get_state(), '{"buyOrders": [{"id": 1, "price": 100, "quantity": 50}],' ' "sellOrders": [{"id": 3, "price": 120, "quantity": 40}]}')
def checkout(self, *items, user=None): if user is None: user = User() order = Order.createOrderFromItems(items) promotion = Promotion() activity = promotion.getApplicableActivity(user, order) order.applyPromotion(activity) return order
def test_correct_iceberg_tuple(self): order = Order((1, "Iceberg", "Buy", 100, 100, 10)) self.assertEqual(order.id, 1) self.assertEqual(order.type, "Iceberg") self.assertEqual(order.direction, "Buy") self.assertEqual(order.quantity, 10) self.assertEqual(order.hidden_quantity, 90) self.assertEqual(order.price, 100) self.assertEqual(order.peak, 10)
def test_correct_limit_json(self): order = Order( '{"type": "Limit", "order":' '{"direction": "Buy", "id": 1, "price": 100, "quantity": 100}}') self.assertEqual(order.id, 1) self.assertEqual(order.type, "Limit") self.assertEqual(order.direction, "Buy") self.assertEqual(order.quantity, 100) self.assertEqual(order.hidden_quantity, 0) self.assertEqual(order.price, 100)
def test_correct_iceberg_json(self): order = Order( '{"type": "Iceberg", "order":' '{"direction": "Buy", "id": 1, "price": 100, "quantity": 100, "peak": 10}}' ) self.assertEqual(order.id, 1) self.assertEqual(order.type, "Iceberg") self.assertEqual(order.direction, "Buy") self.assertEqual(order.quantity, 10) self.assertEqual(order.hidden_quantity, 90) self.assertEqual(order.price, 100) self.assertEqual(order.peak, 10)
def generate_random_orders( number_of_orders: int, iceberg_probability: float = default_iceberg_probability, price_mean: int = default_price_mean, price_deviation: int = default_price_deviation, quantity_mean: int = default_quantity_mean, quantity_deviation: int = default_quantity_deviation, peak_min: int = default_peak_min, peak_max: int = default_peak_max, output_file: str = default_data_file): """ :param number_of_orders: the total number of orders :param iceberg_probability: the expected relative amount of iceberg type orders :param price_mean: normal distribution mean for 'price' field :param price_deviation: standard deviation for 'price' field :param quantity_mean: normal distribution mean for 'quantity' field :param quantity_deviation: standard deviation for 'quantity' field :param peak_min: minimum value of 'peak' field :param peak_max: maximum value of 'peak' field :param output_file: output file name Generates a series of random transactions to a JSON file. """ orders = [] print("Generating data...") for i in range(number_of_orders): order_type = "Limit" direction = "Buy" if random.random() < 0.5 else "Sell" peak = 0 quantity = _generate(quantity_mean, quantity_deviation, random.normalvariate) if random.random() < iceberg_probability: order_type = "Iceberg" peak = min(_generate(peak_min, peak_max, random.uniform), quantity // 2) price = _generate(price_mean, price_deviation, random.normalvariate) orders.append( Order((i + 1, order_type, direction, price, quantity, peak)).__dict__(simple=False)) print("Generated data. Saving to " + output_file + " file...") with open(output_file, 'w') as file: json.dump(orders, file, indent=4)
def __refresh_order(self, order: Order): """ :param order: order to refresh Refreshes the order if its visible quantity is exhausted. If the real quantity is exhausted, removes from the list. """ if order.quantity == 0: orders_list = self.__get_orders_list(order) orders_list.remove(order) if order.hidden_quantity > 0: order.timestamp = self.__get_timestamp() difference = min(order.peak, order.hidden_quantity) order.quantity += difference order.hidden_quantity -= difference orders_list.add(order)
def create_order_list(output_file: str = default_data_file) -> list[Order]: """ :param output_file: JSON file containing serialized orders :return: list of order objects Creates a list of orders from a given file. """ orders = [] try: with open(output_file) as json_file: orders_data = json.load(json_file) for order_data in orders_data: order = Order(json.dumps(order_data)) orders.append(order) except json.JSONDecodeError as error: print("JSON decoder error: " + str(error)) return orders
def add(self, order: Order): """ :param order: order being added to the order book Adds an order to the order book. Executes all possible transactions if possible and then returns the order book state. """ order.timestamp = self.__get_timestamp() self.__get_orders_list(order).add(order) self.last_transactions.clear() while order.quantity > 0: matched_order = self.__match_order(order) if matched_order: self.__make_transaction(order, matched_order) self.__refresh_order(order) else: break
def test_order_book_iceberg_transactions(self): order_book = OrderBook(store_transactions=True) orders = [ '{"type": "Iceberg", "order": {"direction": "Sell", "id": 1, "price": 100, "quantity": 200, "peak": 100}}', '{"type": "Iceberg", "order": {"direction": "Sell", "id": 2, "price": 100, "quantity": 300, "peak": 100}}', '{"type": "Iceberg", "order": {"direction": "Sell", "id": 3, "price": 100, "quantity": 200, "peak": 100}}', '{"type": "Iceberg", "order": {"direction": "Buy", "id": 4, "price": 100, "quantity": 500, "peak": 100}}' ] expected_states = [ '{"buyOrders": [], "sellOrders": [{"id": 1, "price": 100, "quantity": 100}]}', '{"buyOrders": [], "sellOrders":' ' [{"id": 1, "price": 100, "quantity": 100}, {"id": 2, "price": 100, "quantity": 100}]}', '{"buyOrders": [], "sellOrders":' ' [{"id": 1, "price": 100, "quantity": 100}, {"id": 2, "price": 100, "quantity": 100},' ' {"id": 3, "price": 100, "quantity": 100}]}', '{"buyOrders": [], "sellOrders":' ' [{"id": 3, "price": 100, "quantity": 100}, {"id": 2, "price": 100, "quantity": 100}]}' ] expected_transactions = [ [], [], [], [ '{"buyOrderId": 4, "sellOrderId": 1, "price": 100, "quantity": 100}', '{"buyOrderId": 4, "sellOrderId": 2, "price": 100, "quantity": 100}', '{"buyOrderId": 4, "sellOrderId": 3, "price": 100, "quantity": 100}', '{"buyOrderId": 4, "sellOrderId": 1, "price": 100, "quantity": 100}', '{"buyOrderId": 4, "sellOrderId": 2, "price": 100, "quantity": 100}' ] ] for i in range(4): order_book.add(Order(orders[i])) self.assertEqual(order_book.get_state(), expected_states[i]) self.assertEqual(order_book.last_transactions, expected_transactions[i])
def test_order_book_cancel_not_present_order(self): order_book = OrderBook() order = Order((1, "Limit", "Buy", 100, 100, 0)) order_book.add(order) order_book.cancel(order) self.assertRaises(ValueError, order_book.cancel, order)
delta_time = timer() print("\nFinal order book state:\n" + order_book.get_state()) print("\nElapsed time: {0} seconds.".format(delta_time)) print("{:.2f} orders per second.".format(number_of_transactions / delta_time)) sys.exit(0) # run the main program if no special branch has been activated order_book = OrderBook(store_transactions=True) print(program_description + """ To add an order to the order book, insert a JSON line. Type 'exit' to quit the program.\n""") try: for line in sys.stdin: if bool(line and not line.isspace()): if "exit" in line: break order = Order(line) # we assume that id cannot be negative if order.id >= 0: order_book.add(order) print(order_book) except KeyboardInterrupt: pass print("\nSession ended.")
def test_limit_positive_peak_json(self): order = Order( '{"type": "Limit", "order":' '{"direction": "Buy", "id": 1, "price": 100, "quantity": 100, "peak": 10}}' ) self.assertEqual(order.peak, 0)