Exemple #1
0
   def __init__(self, market, side, price, visible_qty, hidden_qty=0):
       """
       An individual quote expressing a desire to buy or sell a Product for a Price. Visible qty is required and
        hidden qty is optional, defaulting to 0 because many markets don't support hidden quantity.
 
       :param market: MarketObjects.Market.Market.
       :param side: Side.
       :param price: Price.
       :param visible_qty: int. Must be greater than 0
       :param hidden_qty: int. Must be 0 or more. Optional. Defaults to 0.
       """
       assert isinstance(price, Price) or isinstance(price, str)
       assert isinstance(side, Side)
       assert isinstance(market, Market)
       assert isinstance(visible_qty, int)
       assert isinstance(hidden_qty, int)
       assert visible_qty > 0, "A quote's visible qty must be greater than 0"
       assert hidden_qty >= 0, "A quote's hidden qty must be greater than or equal to 0"
       use_price = price
       if not isinstance(price, Price):
           use_price = Price(price)
       assert market.is_valid_price(use_price), \
           "%s is not a valid price for a product with minimum price increment %s" % \
           (str(use_price), str(market.mpi()))
       self._side = side
       self._market = market
       self._price_level = PriceLevel(use_price, visible_qty, hidden_qty, num_orders=1)
Exemple #2
0
def test_worse_or_same_as():
    pl1 = PriceLevel(Price("1.6"), 2, 3, 2)
    pl2 = PriceLevel(Price("2.1"), 2, 3, 2)
    pl3 = PriceLevel(Price("1.6"), 24, 4, 22)
    assert pl1.worse_or_same_as(pl2, BID_SIDE)
    assert pl2.worse_or_same_as(pl1, BID_SIDE) is False
    assert pl1.worse_or_same_as(pl2, ASK_SIDE) is False
    assert pl2.worse_or_same_as(pl1, ASK_SIDE)
    assert pl1.worse_or_same_as(pl3, BID_SIDE)
    assert pl1.worse_or_same_as(pl3, ASK_SIDE)
Exemple #3
0
def test_better_or_same_as():
    pl1 = PriceLevel(Price("1.4"), 2, 3, 2)
    pl2 = PriceLevel(Price("1.1"), 2, 3, 2)
    pl3 = PriceLevel(Price("1.4"), 24, 4, 22)
    assert pl1.better_or_same_as(pl2, BID_SIDE)
    assert pl2.better_or_same_as(pl1, BID_SIDE) is False
    assert pl1.better_or_same_as(pl2, ASK_SIDE) is False
    assert pl2.better_or_same_as(pl1, ASK_SIDE)
    assert pl1.better_or_same_as(pl3, BID_SIDE)
    assert pl1.better_or_same_as(pl3, ASK_SIDE)
Exemple #4
0
def test_worse_than():
    pl1 = PriceLevel(Price("1.6"), 2, 3, 2)
    pl2 = PriceLevel(Price("2.1"), 2, 3, 2)
    assert pl1.worse_than(pl2, BID_SIDE)
    assert pl2.worse_than(pl1, BID_SIDE) is False
    assert pl1.worse_than(pl2, ASK_SIDE) is False
    assert pl2.worse_than(pl1, ASK_SIDE)
Exemple #5
0
def test_better_than():
    pl1 = PriceLevel(Price("1.4"), 2, 3, 2)
    pl2 = PriceLevel(Price("1.1"), 2, 3, 2)
    assert pl1.better_than(pl2, BID_SIDE)
    assert pl2.better_than(pl1, BID_SIDE) is False
    assert pl1.better_than(pl2, ASK_SIDE) is False
    assert pl2.better_than(pl1, ASK_SIDE)
Exemple #6
0
def test_parital_passive_fill():
    ob = build_base_order_book()
    # get baseline
    chain_aggressed_into = ob.best_priority_chain(ASK_SIDE)
    visible_qty = ob.visible_qty_at_price(ASK_SIDE, Price("34.52"))
    hidden_qty = ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    num_orders = ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    best_price = ob.best_price(ASK_SIDE)

    # the ack'd order getting aggresed into:
    # a1_ack = AcknowledgementReport(4, 1234000.888, 1002, "user_b", MARKET, a1, Price("34.52"), 35, 10)
    agg_new = NewOrderCommand(101, 1234002.123, 1008, "user_z", MARKET, BID_SIDE, FAR,
                              Price("34.52"), 5)
    pf = PartialFillReport(102, 1234002.123, 1002, "user_b", MARKET, agg_new, 5, Price('34.52'),
                           ASK_SIDE, 3333, 30)
    chain_aggressed_into.apply_partial_fill_report(pf)
    ob.handle_partial_fill_report(pf, chain_aggressed_into)
    # now test for changes
    # ask visible should be 5 less
    assert ob.visible_qty_at_price(ASK_SIDE, Price("34.52")) == visible_qty - 5
    # ask hidden should stay the same
    assert hidden_qty == ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    # best price should be the same
    assert ob.best_ask_price() == best_price == Price("34.52")
    # num orders should stay the same
    assert num_orders == ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    # best chain on the ask should be the same
    assert ob.best_priority_chain(ASK_SIDE).chain_id() == chain_aggressed_into.chain_id() == 1002

    # nothing on bid should have changed
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
Exemple #7
0
def build_base_order_book():
    ob = OrderLevelBook(MARKET, LOGGER)
    b1 = NewOrderCommand(1, 1234000.123, 1001, "user_a", MARKET, BID_SIDE, FAR,
                         Price("34.50"), 50)
    bid_oec1 = OrderEventChain(b1, LOGGER, SUBCHAIN_ID_GENERATOR)
    b1_ack = AcknowledgementReport(2, 1234000.123, 1001, "user_a", MARKET, b1, Price("34.50"), 50, 50)
    bid_oec1.apply_acknowledgement_report(b1_ack)
    ob.handle_acknowledgement_report(b1_ack, bid_oec1)
    a1 = NewOrderCommand(3, 1234000.888, 1002, "user_b", MARKET, ASK_SIDE, FAR,
                         Price("34.52"), 35, 10)
    ask_oec1 = OrderEventChain(a1, LOGGER, SUBCHAIN_ID_GENERATOR)
    a1_ack = AcknowledgementReport(4, 1234000.888, 1002, "user_b", MARKET, a1, Price("34.52"), 35, 10)
    ask_oec1.apply_acknowledgement_report(a1_ack)
    ob.handle_acknowledgement_report(a1_ack, ask_oec1)
    a2 = NewOrderCommand(5, 1234001.888, 1003, "user_c", MARKET, ASK_SIDE, FAR,
                         Price("34.52"), 20, 20)
    ask_oec2 = OrderEventChain(a2, LOGGER, SUBCHAIN_ID_GENERATOR)
    a2_ack = AcknowledgementReport(6, 1234001.888, 1003, "user_b", MARKET, a2, Price("34.52"), 20, 20)
    ask_oec2.apply_acknowledgement_report(a2_ack)
    ob.handle_acknowledgement_report(a2_ack, ask_oec2)
    b2 = NewOrderCommand(9, 1234000.123, 1004, "user_z", MARKET, BID_SIDE, FAR,
                         Price("34.50"), 70)
    bid_oec2 = OrderEventChain(b2, LOGGER, SUBCHAIN_ID_GENERATOR)
    b2_ack = AcknowledgementReport(10, 1234000.123, 1004, "user_z", MARKET, b2, Price("34.50"), 70, 70)
    bid_oec2.apply_acknowledgement_report(b2_ack)
    ob.handle_acknowledgement_report(b2_ack, bid_oec2)

    # do some asserts to ensure we built book as expected
    bid_prices = ob.prices(BID_SIDE)
    print(ob.best_bid_price())
    print(bid_prices)
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
    assert ob.best_priority_chain(BID_SIDE) == bid_oec1
    ask_prices = ob.ask_prices()
    assert len(ask_prices) == 1
    assert ask_prices[0] == Price("34.52")
    assert ob.best_ask_price() == Price("34.52")
    assert ob.best_ask_level() == PriceLevel(Price("34.52"), 30, 25, 2)
    assert ob.best_priority_chain(ASK_SIDE) == ask_oec1
    return ob
Exemple #8
0
def test_acking_fak():
    # should not allow -- so no changes to order book
    ob = build_base_order_book()
    a = NewOrderCommand(56, 1234002.123, 1008, "user_z", MARKET, ASK_SIDE, FAK,
                        Price("34.51"), 35)
    ask_oec = OrderEventChain(a, LOGGER, SUBCHAIN_ID_GENERATOR)
    a_ack = AcknowledgementReport(57, 1234002.123, 1008, "user_z", MARKET, a, Price("34.51"), 35, 35)
    ask_oec.apply_acknowledgement_report(a_ack)
    ob.handle_acknowledgement_report(a_ack, ask_oec)
    # NOTHING SHOULD HAVE CHANGED
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
    ask_prices = ob.ask_prices()
    assert len(ask_prices) == 1
    assert ask_prices[0] == Price("34.52")
    assert ob.best_ask_price() == Price("34.52")
    assert ob.best_ask_level() == PriceLevel(Price("34.52"), 30, 25, 2)
Exemple #9
0
def test_establish_new_ask_tob():
    ob = build_base_order_book()
    a = NewOrderCommand(56, 1234002.123, 1008, "user_z", MARKET, ASK_SIDE, FAR,
                        Price("34.51"), 35)
    ask_oec = OrderEventChain(a, LOGGER, SUBCHAIN_ID_GENERATOR)
    a_ack = AcknowledgementReport(57, 1234002.123, 1008, "user_z", MARKET, a, Price("34.51"), 35, 35)
    ask_oec.apply_acknowledgement_report(a_ack)
    ob.handle_acknowledgement_report(a_ack, ask_oec)
    # ask should  have changed
    ask_prices = ob.ask_prices()
    assert len(ask_prices) == 2  # now 2 prices
    assert ob.best_priority_chain(ASK_SIDE) == ask_oec  # the bid order chain above should now be best
    assert ask_prices[0] == Price("34.51")  # should be new best price
    assert ob.best_ask_price() == Price("34.51")  # should be new best price
    assert ob.best_ask_level() == PriceLevel(Price("34.51"), 35, 0,
                                             1)  # should have new best price level with only 1 order
    # bid should not have changed
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
Exemple #10
0
def test_equality():
    pl1 = PriceLevel(Price("1.1"), 2, 3, 2)
    pl2 = PriceLevel(Price("1.1"), 2, 3, 2)
    pl_price_different = PriceLevel(Price("1.2"), 2, 3, 2)
    pl_visible_qty_different = PriceLevel(Price("1.1"), 3, 3, 2)
    pl_hidden_qty_different = PriceLevel(Price("1.1"), 2, 332, 2)
    pl_num_orders_different = PriceLevel(Price("1.1"), 2, 3, 3)
    pl_num_orders_none = PriceLevel(Price("1.1"), 2, 3, None)
    assert pl1 == pl2
    assert pl1 != pl_price_different
    assert pl1 != pl_visible_qty_different
    assert pl1 != pl_hidden_qty_different
    assert pl1 != pl_num_orders_different
    assert pl1 != pl_num_orders_none

    pl1_num_orders_none = PriceLevel(Price("1.1"), 2, 3)
    pl2_num_orders_none = PriceLevel(Price("1.1"), 2, 3)
    assert pl1_num_orders_none == pl2_num_orders_none
    assert pl1 != pl2_num_orders_none
    assert pl2 != pl1_num_orders_none
    def level_at_price(self, side, price):
        """
        Gets the PriceLevel at a price for a given side. Returns None if the
         price does not exist on that Side.

        :param side: MarketObjects.Side.Side
        :param price: MarketObjects.Price.Price
        :return: MarketObjects.PriceLevel.PriceLevel. Can be None
        """
        level = (self._bid_price_to_level
                 if side.is_bid() else self._ask_price_to_level).get(price)
        if level is None:
            return None
        return PriceLevel(price, self.visible_qty_at_price(side, price),
                          self.hidden_qty_at_price(side, price),
                          self.num_orders_at_price(side, price))
Exemple #12
0
def test_partial_passive_fill_for_all_qty():
    # a partial fill for eveything should balk with some logs but should still be successful.
    # NOTE: this scenario is crazy and shouldn't actually happen (hidden getting filled before visible)
    #       but what the hell, let's cut corners on a test
    ob = build_base_order_book()
    # get baseline
    chain_aggressed_into = ob.best_priority_chain(ASK_SIDE)
    second_ask_back = ob.order_chains_at_price(ASK_SIDE, Price("34.52"))[1]
    visible_qty = ob.visible_qty_at_price(ASK_SIDE, Price("34.52"))
    hidden_qty = ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    num_orders = ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    best_price = ob.best_price(ASK_SIDE)

    # the ack'd order getting aggresed into:
    # a1_ack = AcknowledgementReport(4, 1234000.888, 1002, "user_b", MARKET, a1, Price("34.52"), 35, 10)
    agg_new = NewOrderCommand(101, 1234002.123, 1008, "user_z", MARKET, BID_SIDE, FAR,
                              Price("34.52"), 35)
    pf = PartialFillReport(102, 1234002.123, 1002, "user_b", MARKET, agg_new, 35, Price('34.52'),
                           ASK_SIDE, 3333, 25)
    chain_aggressed_into.apply_partial_fill_report(pf)
    ob.handle_partial_fill_report(pf, chain_aggressed_into)
    # now test for changes
    # ask visible qty should be 10 less (the rest came from hidden)
    assert ob.visible_qty_at_price(ASK_SIDE, Price("34.52")) == visible_qty - 10
    # ask hidden should be 25 (35-10 visible) less
    assert hidden_qty - 25 == ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    # best price should be the same
    assert ob.best_ask_price() == best_price == Price("34.52")
    # should be 1 less order
    assert num_orders - 1 == ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    # best chain on the ask should be what was the second back
    assert ob.best_priority_chain(ASK_SIDE).chain_id() == second_ask_back.chain_id()
    # chain should no longer exist in book
    chains = ob.order_chains_at_price(ASK_SIDE, Price("34.52"))
    found = False
    for chain in chains:
        if chain.chain_id() == chain_aggressed_into.chain_id():
            found = True
    assert not found

    # nothing on bid should have changed
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
Exemple #13
0
def test_cancel_confirm_second_order():
    ob = build_base_order_book()
    first_order_chain = ob.best_priority_chain(ASK_SIDE)
    second_ask_back = ob.order_chains_at_price(ASK_SIDE, Price("34.52"))[1]
    visible_qty = ob.visible_qty_at_price(ASK_SIDE, Price("34.52"))
    hidden_qty = ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    num_orders = ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    best_price = ob.best_price(ASK_SIDE)

    cancel_command = CancelCommand(101, 1234002.123, second_ask_back.chain_id(), second_ask_back.user_id(), MARKET,
                                   USER_CANCEL)
    second_ask_back.apply_cancel_command(cancel_command)
    cancel_report = CancelReport(102, 1234002.123, second_ask_back.chain_id(), second_ask_back.user_id(), MARKET,
                                 cancel_command, USER_CANCEL)
    second_ask_back.apply_cancel_report(cancel_report)
    ob.handle_cancel_report(cancel_report, second_ask_back)
    # the 20 visible are now gone
    assert ob.visible_qty_at_price(ASK_SIDE, Price("34.52")) == visible_qty - 20
    # hidden should stay the same
    assert hidden_qty == ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    # best price should be the same
    assert ob.best_ask_price() == best_price == Price("34.52")
    # should be 1 less order
    assert num_orders - 1 == ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    # best chain on the ask should be the original first
    assert ob.best_priority_chain(ASK_SIDE).chain_id() == first_order_chain.chain_id()
    # chain should no longer exist in book
    chains = ob.order_chains_at_price(ASK_SIDE, Price("34.52"))
    found = False
    for chain in chains:
        if chain.chain_id() == second_ask_back.chain_id():
            found = True
    assert not found

    # bids shouldn't change
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
Exemple #14
0
def test_partial_passive_fill_resets_visible_qty():
    ob = build_base_order_book()
    # get baseline
    chain_aggressed_into = ob.best_priority_chain(ASK_SIDE)
    second_ask_back = ob.order_chains_at_price(ASK_SIDE, Price("34.52"))[1]
    visible_qty = ob.visible_qty_at_price(ASK_SIDE, Price("34.52"))
    hidden_qty = ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    num_orders = ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    best_price = ob.best_price(ASK_SIDE)

    # the ack'd order getting aggresed into:
    # a1_ack = AcknowledgementReport(4, 1234000.888, 1002, "user_b", MARKET, a1, Price("34.52"), 35, 10)
    agg_new = NewOrderCommand(101, 1234002.123, 1008, "user_z", MARKET, BID_SIDE, FAR,
                              Price("34.52"), 10)
    pf = PartialFillReport(102, 1234002.123, 1002, "user_b", MARKET, agg_new, 10, Price('34.52'),
                           ASK_SIDE, 3333, 25)
    chain_aggressed_into.apply_partial_fill_report(pf)
    ob.handle_partial_fill_report(pf, chain_aggressed_into)
    # now test for changes
    # ask visible qty should stay the same because the 10 was filled and then replenished due to iceberg activity
    assert ob.visible_qty_at_price(ASK_SIDE, Price("34.52")) == visible_qty
    # ask hidden should be 10 less becaue of replenishment of iceberg peak
    assert hidden_qty - 10 == ob.hidden_qty_at_price(ASK_SIDE, Price("34.52"))
    # best price should be the same
    assert ob.best_ask_price() == best_price == Price("34.52")
    # num orders should stay the same
    assert num_orders == ob.num_orders_at_price(ASK_SIDE, Price("34.52"))
    # best chain on the ask should be what was the second back
    assert ob.best_priority_chain(ASK_SIDE).chain_id() == second_ask_back.chain_id()
    # worst chain on the ask should be what was the first
    assert ob.order_chains_at_price(ASK_SIDE, Price("34.52"))[-1].chain_id() == chain_aggressed_into.chain_id()

    # nothing on bid should have changed
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
Exemple #15
0
def test_cancel_confirm_entire_price_level():
    ob = build_base_order_book()

    # first add an order at a second price (34.53)
    a = NewOrderCommand(56, 1234002.123, 1009, "user_x", MARKET, ASK_SIDE, FAR,
                        Price("34.53"), 20)
    ask_oec = OrderEventChain(a, LOGGER, SUBCHAIN_ID_GENERATOR)
    a_ack = AcknowledgementReport(57, 1234002.123, 1009, "user_z", MARKET, a, Price("34.53"), 20, 20)
    ask_oec.apply_acknowledgement_report(a_ack)
    ob.handle_acknowledgement_report(a_ack, ask_oec)

    # cancel the orderchains at best price
    id_generator = MonotonicIntID()
    for i, chain in enumerate(ob.order_chains_at_price(ASK_SIDE, ob.best_price(ASK_SIDE))):
        cancel_command = CancelCommand(id_generator.id(), 1234002.123, chain.chain_id(), chain.user_id(), MARKET,
                                       USER_CANCEL)
        chain.apply_cancel_command(cancel_command)
        cancel_report = CancelReport(id_generator.id(), 1234002.123, chain.chain_id(), chain.user_id(), MARKET,
                                     cancel_command, USER_CANCEL)
        chain.apply_cancel_report(cancel_report)
        ob.handle_cancel_report(cancel_report, chain)

    assert ob.best_priority_chain(ASK_SIDE).chain_id() == ask_oec.chain_id()
    # best price should now be 34.53
    assert ob.best_ask_price() == Price('34.53')
    # visible qty is 20
    assert ob.visible_qty_at_price(ASK_SIDE, ob.best_ask_price()) == 20
    # hidden qty is 0
    assert ob.hidden_qty_at_price(ASK_SIDE, ob.best_ask_price()) == 0
    # num orders is 1
    assert ob.num_orders_at_price(ASK_SIDE, ob.best_ask_price()) == 1

    # bids shouldn't change
    bid_prices = ob.bid_prices()
    assert len(bid_prices) == 1
    assert bid_prices[0] == Price("34.50")
    assert ob.best_bid_price() == Price("34.50")
    assert ob.best_bid_level() == PriceLevel(Price("34.50"), 120, 0, 2)
Exemple #16
0
def test_negative_hidden_qty_failes():
    with pytest.raises(AssertionError):
        PriceLevel(Price("23.33"), 3, -3)
Exemple #17
0
def test_cannot_have_more_orders_than_qty():
    with pytest.raises(AssertionError):
        PriceLevel(Price("1.1"), 3, 2, 8)
Exemple #18
0
def test_pricelevel_creation():
    pl = PriceLevel(Price("84.5"), 12)
    assert pl.price() == Price("84.5")
    assert pl.number_of_orders() is None
    assert pl.visible_qty() == 12
    assert pl.hidden_qty() == 0

    pl = PriceLevel(Price("32.134"), 14, 23)
    assert pl.price() == Price("32.134")
    assert pl.number_of_orders() is None
    assert pl.visible_qty() == 14
    assert pl.hidden_qty() == 23
Exemple #19
0
def test_negative_num_orders_fails():
    with pytest.raises(AssertionError):
        PriceLevel(Price("1.1"), 3, 4, -2)
Exemple #20
0
def test_zero_num_orders_fails():
    with pytest.raises(AssertionError):
        PriceLevel(Price("1.1"), 3, 4, 0)
Exemple #21
0
def test_hidden_qty_must_be_int():
    with pytest.raises(AssertionError):
        PriceLevel(Price("1.1"), 3, 4.0)
Exemple #22
0
def test_visible_qty_must_be_int():
    with pytest.raises(AssertionError):
        PriceLevel(Price("1.1"), 3.0)
Exemple #23
0
def test_zero_visible_qty_fails():
    with pytest.raises(AssertionError):
        PriceLevel(Price("23.33"), 0)
Exemple #24
0
class Quote(object):
    def __init__(self, market, side, price, visible_qty, hidden_qty=0):
        """
        An individual quote expressing a desire to buy or sell a Product for a Price. Visible qty is required and
         hidden qty is optional, defaulting to 0 because many markets don't support hidden quantity.
  
        :param market: MarketObjects.Market.Market.
        :param side: Side.
        :param price: Price.
        :param visible_qty: int. Must be greater than 0
        :param hidden_qty: int. Must be 0 or more. Optional. Defaults to 0.
        """
        assert isinstance(price, Price) or isinstance(price, str)
        assert isinstance(side, Side)
        assert isinstance(market, Market)
        assert isinstance(visible_qty, int)
        assert isinstance(hidden_qty, int)
        assert visible_qty > 0, "A quote's visible qty must be greater than 0"
        assert hidden_qty >= 0, "A quote's hidden qty must be greater than or equal to 0"
        use_price = price
        if not isinstance(price, Price):
            use_price = Price(price)
        assert market.is_valid_price(use_price), \
            "%s is not a valid price for a product with minimum price increment %s" % \
            (str(use_price), str(market.mpi()))
        self._side = side
        self._market = market
        self._price_level = PriceLevel(use_price, visible_qty, hidden_qty, num_orders=1)

    def side(self):
        """
        Get the side of the market the quote is for
  
        :return: Side
        """
        return self._side

    def market(self):
        """
        Get the market the quote is for
  
        :return: MarketObjects.Market.Market
        """
        return self._market

    def price(self):
        """
        Get the price of the quote
  
        :return: Price.
        """
        return self._price_level.price()

    def visible_qty(self):
        """
        Get the visible qty of the quote
  
        :return: int
        """
        return self._price_level.visible_qty()

    def hidden_qty(self):
        """
        Get the hidden qty of the quote
  
        :return: int
        """
        return self._price_level.hidden_qty()

    def total_qty(self):
        """
        Get the total qty of the quote.
  
        :return: int.
        """
        return self._price_level.hidden_qty() + self._price_level.visible_qty()

    def is_buy(self):
        """
        Tells if you the Quote is a buy or not
  
        :return: bool
        """
        return self._side.is_bid()

    def is_sell(self):
        """
        Tells if you the Quote is a sell or not
  
        :return: bool
        """
        return self._side.is_ask()

    def __eq__(self, other):
        if not isinstance(other, Quote):
            return False
        return self._price_level == other._price_level and \
               self.side() == other.side() and \
               self.market() == other.market()

    def __str__(self):
        return "%s Quote: %s %d (%d visible, %d hidden) at %s" % \
               (str(self.market()),
                "Buy" if self.is_buy() else "Sell",
                self.total_qty(),
                self.visible_qty(),
                self.hidden_qty(),
                str(self.price()))
Exemple #25
0
def test_zero_hidden_qty_works():
    pl = PriceLevel(Price("23.33"), 3, 0)
    assert pl.hidden_qty() == 0
Exemple #26
0
def test_negative_visible_qty_fails():
    with pytest.raises(AssertionError):
        PriceLevel(Price("23.33"), -2)
Exemple #27
0
def test_pricelevel_must_have_price():
    with pytest.raises(AssertionError):
        PriceLevel(None, -2)