iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
永豐金融APIs

永豐金API之30天不中斷Q&A系列 第 21

Day21 - Blocking & Non-blocking Mode

tags: 2021永豐金鐵人賽

當程式要在很短的時間內發送好幾筆委託單,就會牽涉到blocking及non-blocking的issue,根據shioaji官方網站的介紹,主要的差異其實是在order裡面的timeout參數,這個參數設定的是毫秒數。下面就來介紹一下這兩者的差異。

Non-Blocking Place Order

只要在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來查看。

Order event 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 place order callback

而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=[]
)

Blocking & Non-Blocking比較

下面就來測試發送委託單的速度如何,可以發現non-blocking mode發送完成的速度快了許多,不過這是送出委託單的時間,交易所確認的時間會是另外一個時間。

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

小結

其實blocking & non-blocking就有點像是同步跟非同步的意思,沒有哪個比較好或是比較差,端看使用者需求是什麼才去決定要用哪一套。


上一篇
Day20 - Shioaji的log位置,讀取方式
下一篇
Day22 - Shioaji X Backtesting -雙均線策略
系列文
永豐金API之30天不中斷Q&A26

尚未有邦友留言

立即登入留言