Skip to content

Non-blocking Mode

What is Non-blocking?

First lets see what is Blocking? A function is blocking if it has to wait for something to complete. Yes, every function is blocking — no matter if you are doing I/O or doing CPU task. Everything takes some time. If a function is doing some task which is making the CPU work, then it is blocking the function from returning. Similarly, if a function is trying to get something from the database, then it is going to wait for the result to come and will block until then to continue the processing.

Conversely, when you make a non-blocking operation, it will never wait for the operation to complete. Non-blocking mode is extreamly useful if you try to send a bulk orders in a short period of time. To make you understand what's diffenrence between blocking and non-block mode, we show you examples of comparison.

Shioaji Blocking & Non-blocking Mode

Shioaji provides blocking and non-blocking mode, by simply changing the value of timeout. Default value of timeout is 5000 (ms) which means the function will wait for the response up to 5 seconds. If the execution time exceeds 5 seconds, the function will raise error. However, some api function like tick may takes more than 5 seconds. At this circumstance, just scale up timeout or use non-blocking mode by setting the timeout = 0.

Non-Blocking Place Order

To submit order in non-blocking mode is easy, just set timeout = 0 in place_order function.

In

contract = api.Contracts.Futures.TXF['TXF202108']
order = api.Order(
    action='Sell',
    price=18500,
    quantity=1,
    price_type='LMT',
    order_type='ROD', 
    octype=sj.constant.FuturesOCType.Auto,
    account=api.futopt_account
)
trade = api.place_order(contract, order, timeout=0)
print(trade)

Out

Trade(
    contract=Future(
        code='TXFH1', 
        symbol='TXF202108', 
        name='臺股期貨', 
        category='TXF', 
        delivery_month='202108',
        underlying_kind='I', 
        unit=1,
        limit_up=19412.0, 
        limit_down=15884.0, 
        reference=17648.0, 
        update_date='2021/07/15'
    ), 
    order=Order(
        action=<Action.Sell: 'Sell'>, 
        price=18500, 
        quantity=1, 
        account=FutureAccount(
            person_id='PERSON_ID', 
            broker_id='BROKER_ID', 
            account_id='ACCOUNT_ID', 
            signed=True, 
            username='USERNAME'
        ), 
        price_type=<StockPriceType.LMT: 'LMT'>, 
        order_type=<FuturesOrderType.ROD: 'ROD'>
    ), 
    status=OrderStatus(
        status=<Status.Inactive: 'Inactive'>
    )
)

Note that the Trade object is different from the one we get from blocking mode. First, there is no id and seqno in Order. Second, id, status code, order_datetime and deals are missing in OrderStatus. Finally, status is Inactive. That's because we hadn't really send the order to exchange. The order is still in transmission. Of course we know nothing about this order. Then it comes to a problem, how do we know this order is successfully submitted? We offer you two kinds of methods, order event callback and non-blocking place order callback.

Order event callback

Out

OrderState.FOrder {
    'operation': {
        'op_type': 'New', 
        'op_code': '00', 
        'op_msg': ''
    }, 
    'order': {
        'id': '40fd85d6', 
        'seqno': '958433', 
        'ordno': 'kY01g', 
        'action': 'Sell', 
        'price': 18500.0, 
        'quantity': 1, 
        'order_cond': None, 
        'order_type': 'ROD', 
        'price_type': 'LMT', 
        'market_type': 'Night', 
        'oc_type': 'Cover', 
        'subaccount': ''
    }, 
    'status': {
        'id': '40fd85d6', 
        'exchange_ts': 1626354872, 
        'modified_price': 0.0, 
        'cancel_quantity': 0
    }, 
    'contract': {
        'security_type': 'FUT', 
        'code': 'TXF', 
        'exchange': 'TIM', 
        'delivery_month': '202108', 
        'strike_price': 0.0, 
        'option_right': 'Future'
    }
}

Non-blocking place order callback

In

from shioaji.order import Trade

def non_blocking_cb(trade:Trade):
    print('__my_callback__')
    print(trade)

trade = api.place_order(
    contract, 
    order, 
    timeout=0, 
    cb=non_blocking_cb # only work in non-blocking mode
)

Out: place order callback

__my_callback__
contract=Future(
    code='TXFH1', 
    symbol='TXF202108', 
    name='臺股期貨', 
    category='TXF', 
    delivery_month='202108', 
    underlying_kind='I', 
    unit=1, 
    limit_up=19412.0, 
    limit_down=15884.0, 
    reference=17648.0, 
    update_date='2021/07/15'
), 
order=Order(
    action=<Action.Sell: 'Sell'>, 
    price=18500, 
    quantity=1, 
    id='40fd85d6', 
    seqno='958433', 
    ordno='kY01g', 
    account=Account(
        account_type=<AccountType.Future: 'F'>, 
        person_id='PERSON_ID', 
        broker_id='BROKER_ID', 
        account_id='ACCOUNT_ID', 
        signed=True
    ), 
    price_type=<StockPriceType.LMT: 'LMT'>, 
    order_type=<FuturesOrderType.ROD: 'ROD'>
), 
status=OrderStatus(
    id='40fd85d6', 
    status=<Status.Submitted: 'Submitted'>, 
    status_code='    ', 
    order_datetime=datetime.datetime(2021, 7, 15, 21, 14, 32), 
    deals=[]
)


Blocking & Non-Blocking Comparison

contract and order

contract = api.Contracts.Futures.TXF['TXF202108']
order = api.Order(
    action='Sell',
    price=18500,
    quantity=1,
    price_type='LMT',
    order_type='ROD', 
    octype=sj.constant.FuturesOCType.Auto,
    account=api.futopt_account
)

Blocking

start_time = time.time()
api.place_order(contract, order) # block and wait for the order response
print(time.time() - start_time)
# 0.136578369140625 <- may be different

Non-Blocking

start_time = time.time()
api.place_order(contract, order, timeout=0) # non-block, the order is in transmition (inactive).
print(time.time() - start_time)
# 0.011670351028442383 <- may be different

As you cas see above, in non-blocking mode, it takes about 0.01 seconds to execute place_order function, which is 12x faster than the execution time in blocking mode. Remind again, though it's more efficient to place order in non-blocking mode, the order won't be active until the exchange confirms the order.

Non-Blocking mode Supported Function

  • Function:
    • ticks
    • place_order
    • update_order
    • cancel_order
    • update_status
    • list_positions
  • Parameter: timeout
  • Parameter type: int
  • Default Mode: Block