2021永豐金鐵人賽
當程式要在很短的時間內發送好幾筆委託單,就會牽涉到blocking及non-blocking的issue,根據shioaji官方網站的介紹,主要的差異其實是在order裡面的timeout參數,這個參數設定的是毫秒數。下面就來介紹一下這兩者的差異。
只要在place_order內將timeout設定為0,就會是non-blocking mode囉,範例如下:
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)
印出來後,trade會是下面這樣:
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'>
)
)
可以發現status的部份,會是inactive,表示這筆委託單還沒送到交易所,就是還在傳送中的意思。那要怎麼知道委託單到底有沒有提交到交易所呢?可以透過order event callback或是non-blocking place order callback來查看。
可以看到下面status的部份有了id跟exchange_ts,表示已經送到交易所了。
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 mode有專屬的callback方式,如下:
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
)
收到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=[]
)
下面就來測試發送委託單的速度如何,可以發現non-blocking mode發送完成的速度快了許多,不過這是送出委託單的時間,交易所確認的時間會是另外一個時間。
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
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
其實blocking & non-blocking就有點像是同步跟非同步的意思,沒有哪個比較好或是比較差,端看使用者需求是什麼才去決定要用哪一套。