コード例 #1
0
async def test_message_handling_of_stop_order_events():
    """Tests handling of messages of the trading channel"""
    async def handle_message(json_message):
        LOG.debug("ignored message %s", json_message)

    client = AdvancedBitpandaProWebsocketClient(None, 'test', handle_message)
    client.apply_trading_buffer()
    order_creation = '{"order":{"time_in_force":"GOOD_TILL_CANCELLED","is_post_only":false,"trigger_price":"359.71",' \
                     '"order_id":"c02b49a0-312b-42e4-803b-5ff2179c3d5f",' \
                     '"account_id":"379a12c0-4560-11e9-82fe-2b25c6f7d123","instrument_code":"ETH_EUR",' \
                     '"time":"2020-08-07T14:21:53.691Z","side":"BUY","price":"359.71","amount":"1.0",' \
                     '"filled_amount":"0.0","type":"STOP"},"channel_name":"ORDERS","type":"ORDER_CREATED",' \
                     '"time":"2020-08-07T14:21:53.691Z"}'
    await client.handle_message(json.loads(order_creation))
    assert len(client.state.open_orders_by_order_id) == 1

    stop_order_tracked = '{"order_book_sequence": 0, "trigger_price": "359.71", "current_price": "359.78", ' \
                         '"instrument_code": "ETH_EUR", "order_id": "c02b49a0-312b-42e4-803b-5ff2179c3d5f", ' \
                         '"remaining": "1.0", "channel_name": "TRADING", "type": "TRACKED", ' \
                         '"time": "2020-08-07T14:21:53.692Z"} '
    await client.handle_message(json.loads(stop_order_tracked))
    assert len(client.state.open_orders_by_order_id) == 1

    stop_order_triggered = '{"order_book_sequence": 1, "price": "359.71", "instrument_code": "ETH_EUR", "order_id": ' \
                           '"c02b49a0-312b-42e4-803b-5ff2179c3d5f", "remaining": "1.0", "channel_name": "TRADING", ' \
                           '"type": "TRIGGERED", "time": "2020-08-14T14:22:03.064Z"} '
    await client.handle_message(json.loads(stop_order_triggered))
    assert len(client.state.open_orders_by_order_id) == 1
コード例 #2
0
async def test_handling_of_done_error_events():
    """Tests handling of error messages where type is DONE"""
    async def handle_message(json_message):
        LOG.debug("ignored message %s", json_message)

    client = AdvancedBitpandaProWebsocketClient(None, 'test', handle_message)
    client.apply_trading_buffer()
    # Matching order would have caused a self trade => so it is never booked
    self_trade_prevented = '{"status": "SELF_TRADE", "instrument_code": "ETH_EUR", "order_id": ' \
                           '"338b7543-95d3-4cb8-a264-ed4212da7d92", "client_id": ' \
                           '"58672b66-fc1b-4855-add7-5365297a7213", "remaining": "60.6767", "channel_name": ' \
                           '"TRADING", "type": "DONE", "time": "2020-09-15T12:57:39.737Z"} '
    await client.handle_message(json.loads(self_trade_prevented))
    assert len(client.state.open_orders_by_order_id) == 0

    # Only for market orders => when not enough funds have been locked the order fails
    insufficient_funds = '{"status": "INSUFFICIENT_FUNDS","instrument_code": "ETH_EUR","order_id": ' \
                         '"fb2d540e-6fe4-411c-8d91-7c94b94d1ae2","remaining": "1.0","channel_name": "TRADING",' \
                         '"type": "DONE","time": "2020-09-15T13:15:07.214Z"}'
    await client.handle_message(json.loads(insufficient_funds))
    assert len(client.state.open_orders_by_order_id) == 0

    # Only for market orders => when not enough liquidity is in the order book the market order fails
    insufficient_liquidity = '{"status": "INSUFFICIENT_LIQUIDITY","instrument_code": "ETH_EUR","order_id": ' \
                             '"80cf3fed-5766-4b5c-a378-213c5541bf5d","remaining": "80.0","channel_name": "TRADING",' \
                             '"type": "DONE","time": "2020-09-15T12:58:12.305Z"}'
    await client.handle_message(json.loads(insufficient_liquidity))
    assert len(client.state.open_orders_by_order_id) == 0

    # Internal system error => order was never booked
    time_to_market_exceeded = '{"status": "TIME_TO_MARKET_EXCEEDED","instrument_code": "ETH_EUR","order_id": ' \
                              '"bbf4780c-c26b-45dd-a17d-4d554a5b6e30","remaining": "34.0","channel_name": "TRADING",' \
                              '"type": "DONE","time": "2020-09-15T12:58:12.305Z"}'
    await client.handle_message(json.loads(time_to_market_exceeded))
    assert len(client.state.open_orders_by_order_id) == 0
コード例 #3
0
async def test_message_handling_of_trading_channel_events():
    """Tests handling of messages of the trading channel"""
    async def handle_message(json_message):
        LOG.debug("ignored message %s", json_message)

    client = AdvancedBitpandaProWebsocketClient(None, 'test', handle_message)
    client.apply_trading_buffer()
    order_creation = '{"order":{"time_in_force":"GOOD_TILL_CANCELLED","is_post_only":false,' \
                     '"order_id":"c241b172-ee8d-4e1b-8900-6512c2c23579",' \
                     '"account_id":"379a12c0-4560-11e9-82fe-2b25c6f7d123","instrument_code":"BTC_EUR",' \
                     '"time":"2020-06-02T06:48:08.278Z","side":"BUY","price":"6000.0","amount":"1.0",' \
                     '"filled_amount":"0.0","type":"LIMIT"},"channel_name":"ORDERS","type":"ORDER_CREATED",' \
                     '"time":"2020-06-02T06:48:08.278Z"}'
    await client.handle_message(json.loads(order_creation))
    assert len(client.state.open_orders_by_order_id) == 1
    order_booked = '{"order_book_sequence": 1, "instrument_code": "BTC_EUR", "order_id": ' \
                   '"c241b172-ee8d-4e1b-8900-6512c2c23579", "remaining": "1.0", "channel_name": "TRADING", ' \
                   '"type": "BOOKED", "time": "2020-06-02T06:48:08.279Z"}'
    await client.handle_message(json.loads(order_booked))
    assert len(client.state.open_orders_by_order_id) == 1
    order_filled = '{"order_book_sequence": 1, "side": "BUY", "amount": "1.0", "trade_id": ' \
                   '"c2591a26-5f76-401f-83ec-4d20657f2db3", "matched_as": "MAKER", "matched_amount": "0.1", ' \
                   '"matched_price": "6000.0", "instrument_code": "BTC_EUR", "order_id": ' \
                   '"c241b172-ee8d-4e1b-8900-6512c2c23579", "remaining": "0.9", "channel_name": "TRADING", ' \
                   '"type": "FILL", "time": "2020-06-02T06:49:08.279Z"}'
    await client.handle_message(json.loads(order_filled))
    assert len(client.state.open_orders_by_order_id) == 1

    order_filled_fully = '{"status": "FILLED_FULLY", "order_book_sequence": 1, "instrument_code": "BTC_EUR", ' \
                         '"order_id": "c241b172-ee8d-4e1b-8900-6512c2c23579", "remaining": "0.0", "channel_name": ' \
                         '"TRADING", "type": "DONE", "time": "2020-06-02T06:50:08.279Z"}'
    await client.handle_message(json.loads(order_filled_fully))
    assert len(client.state.open_orders_by_order_id) == 0
コード例 #4
0
async def test_handle_trade_settled_updates():
    """Test trade settlement events"""
    client = AdvancedBitpandaProWebsocketClient("irrelevant", "irrelevant",
                                                log_messages)
    await client.handle_message(account_balances_json)
    balance = client.state.balances["BTC"]
    assert balance.available == Decimal("8975.828764802")
    assert balance.locked == Decimal("0.4")

    # ------- Order created  ----------
    await client.handle_message(order_created_json)
    expected_order = client.state.open_orders_by_order_id.get(
        "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c")
    # Orders are handled through orders/trading channel
    assert expected_order is None

    # On order channel update the order is in the store
    await client.handle_message(order_created_orders_channel_json)
    expected_order = client.state.open_orders_by_order_id.get(
        "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c")
    assert expected_order is not None
    assert expected_order.remaining == Decimal("1.0")
    assert expected_order.order_id == "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c"
    assert expected_order.price == "8500.0"

    # check balance
    balance = client.state.balances["BTC"]
    assert balance.available == Decimal("8974.828764802")
    assert balance.locked == Decimal("1.4")

    # ------- half of order settled  ----------
    await client.handle_message(trade_settled_partially_json)
    # check balance again, partially filled
    balance = client.state.balances["BTC"]
    assert balance.available == Decimal("8974.828764802")
    assert balance.locked == Decimal("0.9")
    # order is still part of open orders
    expected_order = client.state.open_orders_by_order_id.get(
        "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c")
    assert expected_order is not None
    assert expected_order.remaining == Decimal("1.0")
    assert expected_order.order_id == "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c"
    assert expected_order.price == "8500.0"

    # ------- fully settled  order ----------
    await client.handle_message(trade_settled_json)
    # check balance again, not locked anymore
    balance = client.state.balances["BTC"]
    assert balance.available == Decimal("8974.828764802")
    assert balance.locked == Decimal("0.4")
    # order is completed, on update from trading channel the store is updated
    client.apply_trading_buffer()
    await client.handle_message(trade_settled_order_done_json)

    expected_order = client.state.open_orders_by_order_id.get(
        "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c")
    assert expected_order is None
    inactive_order = client.state.inactive_orders.get(
        "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c")
    assert inactive_order is not None
    assert inactive_order.order_id == "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c"
    assert inactive_order.remaining == Decimal("0.0")
    assert inactive_order.order_id == "65ecb524-4a7f-4b22-aa44-ec0b38d3db9c"
    assert inactive_order.price == "8500.0"