當委託單成功建立、修改或取消成功時,都會執行order_callback,預設下的callback就是執行print(stat, msg),把回傳的狀態及訊息輸出。
當然,也可以自己自定callback所要執行的內容,範例如下:
# 定義callback的fuction,名稱可自行定義,但所傳的參數stat和msg是固定的
def place_cb(stat, msg):
print('my_place_callback')
print(f'stat:{stat}')
print(f'msg:{msg}')
api.update_status(api.stock_account) #測試,是否可以在成功發送委託單後,自動更新
api.set_order_callback(place_cb) #將剛才自行定義的function名稱傳入,設定為order的callback執行程式
完整程式範例如下:
rom dotenv import load_dotenv
import os
import shioaji as sj
from shioaji.constant import Action, StockPriceType, TFTOrderType, TFTStockOrderLot
load_dotenv('D:\\python\\shioaji\\.env') #讀取.env中的環境變數
api = sj.Shioaji()
api.login(
person_id=os.getenv('YOUR_PERSON_ID'),
passwd=os.getenv('YOUR_PASSWORD')
)
result = api.activate_ca(
ca_path=os.getenv('YOUR_CA_PATH'),
ca_passwd=os.getenv('YOUR_CA_PASS'),
person_id=os.getenv('YOUR_PERSON_ID'),
)
# 定義place_order、update_order及cancel_order後,要執行什麼動作
# 沒有定義的話,預設是print(stat, msg)
def place_cb(stat, msg):
print('my_place_callback')
print(f'stat:{stat}')
print(f'msg:{msg}')
api.update_status(api.stock_account) #測試,是否可以在成功發送委託單後,自動更新
api.set_order_callback(place_cb)
contract = api.Contracts.Stocks['2890']
order = api.Order(
price=contract.limit_down,
quantity=2,
action=Action.Buy,
price_type=StockPriceType.LMT,
order_type=TFTOrderType.ROD,
order_lot=TFTStockOrderLot.Common,
account=api.stock_account
)
trade = api.place_order(contract, order)
print(trade)
執行成功後,可以看到輸出結果如下:
OrderState中,最主要看operation這裡頭的資料,分別有以下三個屬性內容:
屬性 | 內容說明 |
---|---|
op_type | 委託單的動作內容 |
op_code | op_msg對應的code,若為00表示委託動作成功,其餘code皆為錯誤 |
op_msg | 錯誤訊息內容。若此內容為空,表示委託動作成功 |
由於官方文件中,只有放成功委託單所回傳的OrderState及message,以下列幾個在測試時發現的錯誤訊息範例。
委託單已全部成交,無法進行修改。
Trade(contract=Stock(exchange=<Exchange.TSE: 'TSE'>, code='2890', symbol='TSE2890', name='永豐金', category='17', unit=1000, limit_up=15.3, limit_down=12.6, reference=13.95, update_date='2021/09/27', day_trade=<DayTrade.Yes: 'Yes'>), order=Order(action=<Action.Buy: 'Buy'>, price=13.8, quantity=1, id='0ab3dd4a', seqno='092823', ordno='WA027', account=Account(account_type=<AccountType.Stock: 'S'>, person_id='PAPIUSER06', broker_id='9A95', account_id='0506701', signed=True), price_type=<StockPriceType.LMT: 'LMT'>, order_type=<FuturesOrderType.ROD: 'ROD'>), status=OrderStatus(id='0ab3dd4a', status=<Status.Filled: 'Filled'>, status_code='00', order_datetime=datetime.datetime(2021, 9, 27, 10, 56, 37), modified_price=14.0, deal_quantity=1, deals=[Deal(seq='000928', price=14.0, quantity=1, ts=1632712382)]))
OrderState.TFTOrder {'operation': {'op_type': 'UpdatePrice', 'op_code': '88', 'op_msg': '該委託書已完全成交,不可刪單/改量或改價'}, 'order': {'id': '076475b8', 'seqno': '092826', 'ordno': 'WA027', 'account': {'account_type': 'S', 'person_id': '', 'broker_id': '9A95', 'account_id': '0506701', 'signed': True}, 'action': 'Buy', 'price': 13.0, 'quantity': 1, 'order_type': 'ROD', 'order_cond': 'Cash', 'order_lot': 'Common', 'price_type': 'LMT'}, 'status': {'id': '076475b8', 'exchange_ts': 1632712456, 'modified_price': 13.0, 'cancel_quantity': 0}, 'contract': {'security_type': 'STK', 'exchange': 'TSE', 'code': '2890', 'symbol': '', 'name': '', 'currency': 'TWD'}}
股票的價格檔數錯誤,導致金額修改失敗。
Trade(contract=Stock(exchange=<Exchange.TSE: 'TSE'>, code='2890', symbol='TSE2890', name='永豐金', category='17', unit=1000, limit_up=15.3, limit_down=12.6, reference=13.95, update_date='2021/09/27', day_trade=<DayTrade.Yes: 'Yes'>), order=Order(action=<Action.Buy: 'Buy'>, price=13.8, quantity=1, id='11e11995', seqno='310462', ordno='XC307', account=Account(account_type=<AccountType.Stock: 'S'>, person_id='F126684691', broker_id='9A79', account_id='0103298', signed=True), price_type=<StockPriceType.LMT: 'LMT'>, order_type=<FuturesOrderType.ROD: 'ROD'>), status=OrderStatus(id='11e11995', status=<Status.Submitted: 'Submitted'>, status_code='00', order_datetime=datetime.datetime(2021, 9, 27, 10, 28, 52), modified_price=13.7, deals=[]))
OrderState.TFTOrder {'operation': {'op_type': 'UpdatePrice', 'op_code': '88', 'op_msg': '價格檔數錯誤'}, 'order': {'id': '12329396', 'seqno': '311673', 'ordno': 'XC307', 'account': {'account_type': 'S', 'person_id': '', 'broker_id': '9A79', 'account_id': '0103298', 'signed': True}, 'action': 'Buy', 'price': 13.71, 'quantity': 1, 'order_type': 'ROD', 'order_cond': 'Cash', 'order_lot': 'Common', 'price_type': 'LMT'}, 'status': {'id': '12329396', 'exchange_ts': 1632710044, 'modified_price': 13.71, 'cancel_quantity': 0}, 'contract': {'security_type': 'STK', 'exchange': 'TSE', 'code': '2890', 'symbol': '', 'name': '', 'currency': 'TWD'}}
盤後定價及盤後零股,非委託時間送出。
Trade(contract=Stock(exchange=<Exchange.TSE: 'TSE'>, code='2890', symbol='TSE2890', name='永豐金', category='17', unit=1000, limit_up=15.3, limit_down=12.6, reference=13.95, update_date='2021/09/27', day_trade=<DayTrade.Yes: 'Yes'>), order=Order(action=<Action.Buy: 'Buy'>, price=13.95, quantity=1, account=Account(account_type=<AccountType.Stock: 'S'>, person_id='PAPIUSER06', broker_id='9A95', account_id='0506701', signed=True), price_type=<StockPriceType.LMT: 'LMT'>, order_type=<FuturesOrderType.ROD: 'ROD'>, order_lot=<TFTStockOrderLot.Odd: 'Odd'>), status=OrderStatus(status=<Status.Failed: 'Failed'>, status_code='74009', order_datetime=datetime.datetime(2021, 9, 27, 14, 31, 45), msg='非委託時間', deals=[]))