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