def test_basic_partial_fill_replenish_visible(): n = NewOrderCommand(121234, 1234235.123, 2342, "user_x", MARKET, BID_SIDE, FAR, Price("34.52"), 100, 40) oec = OrderEventChain(n, LOGGER, MonotonicIntID()) # now ack it ack = AcknowledgementReport(121235, 1234235.123, 2342, "user_x", MARKET, n, Price("34.52"), 100, 40) oec.apply_acknowledgement_report(ack) aggressor = NewOrderCommand(1111, 1234237.123, 22222, "user_y", MARKET, ASK_SIDE, FAR, Price("34.52"), 40) # now resting partial fill pf = PartialFillReport(121236, 1234237.123, 2342, "user_x", MARKET, aggressor, 40, Price("34.52"), BID_SIDE, 99999, 100-40) oec.apply_partial_fill_report(pf) assert oec.open_exposure_requests() == [] assert oec.current_exposure().price() == Price("34.52") assert oec.current_exposure().qty() == 100-40 assert oec.visible_qty() == 40 # should have replenished assert oec.iceberg_peak_qty() == 40 # should not have changed assert oec.has_partial_fill() # now test the partial fill wipes out 40 more, so visible is min aggressor2 = NewOrderCommand(1114, 1234237.123, 33333, "user_y", MARKET, ASK_SIDE, FAR, Price("34.52"), 40) # now resting partial fill pf2 = PartialFillReport(121236, 1234237.123, 2342, "user_x", MARKET, aggressor2, 40, Price("34.52"), BID_SIDE, 99999, 100-40-40) # subtract out the size of 2 40 lot fills now oec.apply_partial_fill_report(pf2) assert oec.open_exposure_requests() == [] assert oec.current_exposure().price() == Price("34.52") assert oec.current_exposure().qty() == 100-40-40 assert oec.visible_qty() == 100-40-40 # should have replenished to min of 40 and 100-40-40 assert oec.iceberg_peak_qty() == 40 # should not have changed assert oec.has_partial_fill()
def test_partial_aggressive_fill(): # nothing should change as we only update orderbook for passive partial fills ob = build_base_order_book() # get baseline ask_prices = ob.ask_prices() bid_prices = ob.bid_prices() best_ask_price = ob.best_ask_price() best_bid_price = ob.best_bid_price() bast_ask_level = ob.best_ask_level() bast_bid_level = ob.best_bid_level() agg_new = NewOrderCommand(101, 1234002.123, 1008, "user_z", MARKET, BID_SIDE, FAR, Price("34.52"), 45) oec = OrderEventChain(agg_new, LOGGER, SUBCHAIN_ID_GENERATOR) pf = PartialFillReport(102, 1234002.123, 1008, "user_z", MARKET, agg_new, 35, Price('34.52'), BID_SIDE, 3333, 10) oec.apply_partial_fill_report(pf) ob.handle_partial_fill_report(pf, oec) # nothing at the order book should have changed assert ask_prices == ob.ask_prices() assert bid_prices == ob.bid_prices() assert best_ask_price == ob.best_ask_price() assert best_bid_price == ob.best_bid_price() assert bast_ask_level == ob.best_ask_level() assert bast_bid_level == ob.best_bid_level()
def test_partial_fill_on_unacked_order(): # when an unacked order is filled the requested exposure gets impacted n = NewOrderCommand(121234, 1234235.123, 2342, "user_x", MARKET, BID_SIDE, FAR, Price("34.52"), 100) oec = OrderEventChain(n, LOGGER, MonotonicIntID()) assert oec.current_exposure() is None assert oec.most_recent_requested_exposure().qty() == 100 assert oec.most_recent_requested_exposure().price() == Price("34.52") # now resting partial fill pf = PartialFillReport(1212344, 1234237.123, 2342, "user_x", MARKET, n, 10, Price("34.52"), BID_SIDE, 99999, 90) oec.apply_partial_fill_report(pf) assert oec.current_exposure() is None assert oec.most_recent_requested_exposure().qty() == 90 assert oec.most_recent_requested_exposure().price() == Price("34.52")
def test_partial_fill_to_zero_closes_out_order(): # when a partialfill closses out to an order there should be a balking because it is a paritial fill so shouldn't happen, but should allow n = NewOrderCommand(121234, 1234235.123, 2342, "user_x", MARKET, BID_SIDE, FAR, Price("34.52"), 100) oec = OrderEventChain(n, LOGGER, MonotonicIntID()) # now ack it ack = AcknowledgementReport(121235, 1234235.123, 2342, "user_x", MARKET, n, Price("34.52"), 100, 100) oec.apply_acknowledgement_report(ack) aggressor = NewOrderCommand(1111, 1234237.123, 22222, "user_y", MARKET, ASK_SIDE, FAR, Price("34.52"), 100) # now resting partial fill pf = PartialFillReport(1212344, 1234237.123, 2342, "user_x", MARKET, aggressor, 100, Price("34.52"), BID_SIDE, 99999, 0) oec.apply_partial_fill_report(pf) assert oec.open_exposure_requests() == [] assert oec.is_open() is False assert oec.visible_qty() == 0 assert oec.current_exposure() == Exposure(None, 0, 1212344)
def test_subchain_getters_partial_fill_before_ack(): # pretty basic, just testing that it doesn't break n = NewOrderCommand(121234, 1234235.123, 2342, "user_x", MARKET, BID_SIDE, FAR, Price("34.52"), 1000) oec = OrderEventChain(n, LOGGER, MonotonicIntID()) # now aggressive partial fill pf = PartialFillReport(121236, 1234237.123, 2342, "user_x", MARKET, n, 44, Price("34.52"), BID_SIDE, 99999, 1000 - 44) oec.apply_partial_fill_report(pf) # now ack it ack = AcknowledgementReport(121235, 1234235.123, 2342, "user_x", MARKET, n, Price("34.52"), 1000-44, None) oec.apply_acknowledgement_report(ack) subchain = oec.most_recent_subchain() assert subchain.open_event() == n assert subchain.first_execution_report() == pf assert subchain.fills() == [pf] assert subchain.last_event() == ack
def test_basic_partial_fill(): n = NewOrderCommand(121234, 1234235.123, 2342, "user_x", MARKET, BID_SIDE, FAR, Price("34.52"), 1000) oec = OrderEventChain(n, LOGGER, MonotonicIntID()) # now ack it ack = AcknowledgementReport(121235, 1234235.123, 2342, "user_x", MARKET, n, Price("34.52"), 1000, 1000) oec.apply_acknowledgement_report(ack) aggressor = NewOrderCommand(1111, 1234237.123, 22222, "user_x", MARKET, ASK_SIDE, FAR, Price("34.52"), 44) # now resting partial fill pf = PartialFillReport(121236, 1234237.123, 2342, "user_x", MARKET, aggressor, 44, Price("34.52"), BID_SIDE, 99999, 1000-44) oec.apply_partial_fill_report(pf) assert oec.open_exposure_requests() == [] assert oec.current_exposure().price() == Price("34.52") assert oec.current_exposure().qty() == 1000-44 assert oec.visible_qty() == 1000-44 assert oec.iceberg_peak_qty() == 1000 # should not have changed assert oec.has_partial_fill()
def test_partial_fill_on_multiple_unacked_requests(): n = NewOrderCommand(1, 1234235.123, 2342, "user_x", MARKET, BID_SIDE, FAR, Price("34.52"), 1000) oec = OrderEventChain(n, LOGGER, MonotonicIntID()) # should have 1 open exposure assert len(oec.open_exposure_requests()) == 1 assert oec.most_recent_requested_exposure() == Exposure(Price("34.52"), 1000, 1) cr1 = CancelReplaceCommand(2, 1234235.863, 2342, "user_x", MARKET, BID_SIDE, Price("34.51"), 800) oec.apply_cancel_replace_command(cr1) # now should have 2 open exposures assert len(oec.open_exposure_requests()) == 2 assert oec.open_exposure_requests()[0] == Exposure(Price("34.52"), 1000, 1) assert oec.open_exposure_requests()[1] == Exposure(Price("34.51"), 800, 2) cr2 = CancelReplaceCommand(3, 1234236.842, 2342, "user_x", MARKET, BID_SIDE, Price("34.55"), 800) oec.apply_cancel_replace_command(cr2) # now should have 2 open exposures assert len(oec.open_exposure_requests()) == 3 assert oec.open_exposure_requests()[0] == Exposure(Price("34.52"), 1000, 1) assert oec.open_exposure_requests()[1] == Exposure(Price("34.51"), 800, 2) assert oec.open_exposure_requests()[2] == Exposure(Price("34.55"), 800, 3) cr3 = CancelReplaceCommand(4, 1234236.842, 2342, "user_x", MARKET, BID_SIDE, Price("34.56"), 800) oec.apply_cancel_replace_command(cr3) # now should have 2 open exposures assert len(oec.open_exposure_requests()) == 4 assert oec.open_exposure_requests()[0] == Exposure(Price("34.52"), 1000, 1) assert oec.open_exposure_requests()[1] == Exposure(Price("34.51"), 800, 2) assert oec.open_exposure_requests()[2] == Exposure(Price("34.55"), 800, 3) assert oec.open_exposure_requests()[3] == Exposure(Price("34.56"), 800, 4) # a partial fill should should only impact the one the partial fill is for # partially filling orderid 3 (cr2) pf1 = PartialFillReport(5, 1234237.123, 2342, "user_x", MARKET, cr2, 10, Price("34.55"), BID_SIDE, 999, 790) oec.apply_partial_fill_report(pf1) assert len(oec.open_exposure_requests()) == 4 assert oec.open_exposure_requests()[0] == Exposure(Price("34.52"), 1000, 1) assert oec.open_exposure_requests()[1] == Exposure(Price("34.51"), 800, 2) assert oec.open_exposure_requests()[2] == Exposure(Price("34.55"), 790, 3) assert oec.open_exposure_requests()[3] == Exposure(Price("34.56"), 800, 4) # and again pf2 = PartialFillReport(6, 1234237.123, 2342, "user_x", MARKET, cr2, 10, Price("34.55"), BID_SIDE, 1000, 780) oec.apply_partial_fill_report(pf2) assert len(oec.open_exposure_requests()) == 4 assert oec.open_exposure_requests()[0] == Exposure(Price("34.52"), 1000, 1) assert oec.open_exposure_requests()[1] == Exposure(Price("34.51"), 800, 2) assert oec.open_exposure_requests()[2] == Exposure(Price("34.55"), 780, 3) assert oec.open_exposure_requests()[3] == Exposure(Price("34.56"), 800, 4) # and now I can fill order id 4 (cr 3) pf3 = PartialFillReport(6, 1234237.123, 2342, "user_x", MARKET, cr3, 50, Price("34.56"), BID_SIDE, 1001, 750) oec.apply_partial_fill_report(pf3) assert len(oec.open_exposure_requests()) == 4 assert oec.open_exposure_requests()[0] == Exposure(Price("34.52"), 1000, 1) assert oec.open_exposure_requests()[1] == Exposure(Price("34.51"), 800, 2) assert oec.open_exposure_requests()[2] == Exposure(Price("34.55"), 780, 3) assert oec.open_exposure_requests()[3] == Exposure(Price("34.56"), 750, 4) # now start acking them ack1 = AcknowledgementReport(10, 1234235.123, 2342, "user_x", MARKET, n, Price("34.52"), 1000, None) oec.apply_acknowledgement_report(ack1) assert len(oec.open_exposure_requests()) == 3 assert oec.open_exposure_requests()[0] == Exposure(Price("34.51"), 800, 2) assert oec.open_exposure_requests()[1] == Exposure(Price("34.55"), 780, 3) assert oec.open_exposure_requests()[2] == Exposure(Price("34.56"), 750, 4) assert oec.current_exposure() == Exposure(Price("34.52"), 1000, 10) ack2 = AcknowledgementReport(11, 1234235.123, 2342, "user_x", MARKET, cr1, Price("34.51"), 800, None) oec.apply_acknowledgement_report(ack2) assert len(oec.open_exposure_requests()) == 2 assert oec.open_exposure_requests()[0] == Exposure(Price("34.55"), 780, 3) assert oec.open_exposure_requests()[1] == Exposure(Price("34.56"), 750, 4) assert oec.current_exposure() == Exposure(Price("34.51"), 800, 11) ack3 = AcknowledgementReport(12, 1234235.123, 2342, "user_x", MARKET, cr2, Price("34.55"), 780, None) oec.apply_acknowledgement_report(ack3) assert len(oec.open_exposure_requests()) == 1 print(oec.open_exposure_requests()[0]) assert oec.open_exposure_requests()[0] == Exposure(Price("34.56"), 750, 4) assert oec.current_exposure() == Exposure(Price("34.55"), 780, 12) ack4 = AcknowledgementReport(13, 1234235.123, 2342, "user_x", MARKET, cr3, Price("34.56"), 750, None) oec.apply_acknowledgement_report(ack4) assert len(oec.open_exposure_requests()) == 0 assert oec.current_exposure() == Exposure(Price("34.56"), 750, 13)