Day29 - Shioaji - 超入門!永豐證券程式交易API快速上手 2
今天來看一下如何使用Shioaji問回歷史交易資料,不過在此先提醒一下,上一篇有講到的永豐講師的Youtube課程,其中講師特別提醒大家,這個用法僅僅是方便永豐API用戶測試用途使用,因為資源有限,並不建議大家過度使用這個方式進行歷史資料的大量撈取,若在非正常情況下的使用,永豐是有權將使用者的帳號鎖定。所以大家要使用的前提下,若僅進行資料測試時,盡量設定資料存取範圍,以及愛惜資源。
詢問歷史Ticks資料:以股票為例
以下僅列出程式片段要點,前面該做login的步驟,請還是要按照方式使用,可參考前一篇的介紹。 就拿護國神山2330台積電為例。
import pandas as pd
TSE2330 = api.Contracts.Stocks.TSE.TSE2330
ticks = api.ticks(
contract=TSE2330,
date="2021-10-13",
query_type=sj.constant.TicksQueryType.RangeTime,
time_start="13:24:00",
time_end="13:24:30"
)
pd.set_option('display.max_columns', None)
df = pd.DataFrame({**ticks})
df.ts = pd.to_datetime(df.ts)
print(df.tail(10))
這裡使用了api.ticks()
取回我們指定的Contract的歷史資料,可指定某天的當日tick資料,為了縮小資料量,可透過query_type
設定為TicksQueryType.RangeTime
的方式,我們可設定取回的起迄時間。
例如我這裡設定了取回收盤前逐筆搓合時間段的某30秒的資料。
並且使用pandas的DataFrame進行資料整理,記得把ts的時間作轉換。我們印出最末端10筆資料。
Output如下:
ts ask_price close bid_volume bid_price \
9 2021-10-13 13:24:09.456604 572.0 571.0 121 571.0
10 2021-10-13 13:24:11.003873 572.0 572.0 121 571.0
11 2021-10-13 13:24:14.429999 572.0 571.0 122 571.0
12 2021-10-13 13:24:18.495718 572.0 572.0 124 571.0
13 2021-10-13 13:24:22.597406 572.0 572.0 125 571.0
14 2021-10-13 13:24:23.154184 572.0 572.0 125 571.0
15 2021-10-13 13:24:23.206579 573.0 572.0 126 571.0
16 2021-10-13 13:24:27.416942 573.0 572.0 129 571.0
17 2021-10-13 13:24:27.782836 573.0 572.0 130 571.0
18 2021-10-13 13:24:28.055190 573.0 573.0 130 571.0
ask_volume volume
9 71 41
10 69 1
11 67 3
12 65 2
13 65 1
14 64 1
15 116 64
16 120 1
17 120 1
18 119 2
詢問K線(KBar)資料:以股票為例
我們接著可以使用api.kbars()
來問回K線資料,一樣指定contract與起迄日期,並會以每分鐘的K線資料逐筆回傳。而K線資料會有每個區間的Open、High、Low、Close四個價格數值,K線圖也是以此作為最重要的依據。
kbars = api.kbars(
contract=TSE2330,
start="2021-10-12",
end="2021-10-12"
)
df = pd.DataFrame({**kbars})
df.ts = pd.to_datetime(df.ts)
我們印出部份的Kbars值如下:
Volume Close Open Low High Amount
ts
2021-10-12 09:01:00 4493 570.0 570.0 570.0 571.0 2.561513e+09
2021-10-12 09:02:00 415 570.0 570.0 569.0 571.0 2.364880e+08
2021-10-12 09:03:00 184 570.0 570.0 569.0 571.0 1.048730e+08
2021-10-12 09:04:00 636 569.0 570.0 568.0 570.0 3.616940e+08
2021-10-12 09:05:00 276 568.0 568.0 568.0 569.0 1.567810e+08
... ... ... ... ... ... ...
2021-10-12 13:22:00 84 573.0 573.0 573.0 574.0 4.815400e+07
2021-10-12 13:23:00 48 573.0 573.0 573.0 574.0 2.753100e+07
2021-10-12 13:24:00 128 573.0 574.0 573.0 574.0 7.336300e+07
2021-10-12 13:25:00 88 573.0 573.0 572.0 574.0 5.037700e+07
2021-10-12 13:30:00 3792 575.0 575.0 575.0 575.0 2.180400e+09
接下來,介紹一個畫金融資料的好用圖表工具:mplfinance
可透過conda的安裝路徑進行安裝,可參考conda-forge package網址。
conda install -c conda-forge mplfinance
接著就可以使用簡單的方法,來繪製K線圖。
用圖表來顯示更直覺
import mplfinance as mpf
df.set_index('ts', inplace=True)
df.index.name = "ts"
df.index = pd.DatetimeIndex(df.index)
color = mpf.make_marketcolors(up='r', down='g', inherit=True)
style = mpf.make_mpf_style(base_mpf_style='charles', marketcolors=color)
mpf.plot(df, **dict(type='candle', volume=True, style=style))
上面需設定DatetimeIndex,請參考上述方式,才能正確透過malfinance畫圖。
接著是定義其線圖的顏色與型態,需要將上漲與下跌的重新指定台灣股市特有的紅漲綠跌。(國外是相反過來的)
style有幾種可以指定,可透過mplfinance.available_styles()
印出:
['blueskies', 'brasil', 'charles', 'checkers', 'classic', 'default', 'mike', 'nightclouds', 'sas','starsandstripes', 'yahoo']
再來就是指定plot的參數,我們需要畫的是candle圖,以及把上述的設定放入。 如此一來,我們的1分鐘期的K線圖就產生了。
Snapshot快照
官方文件的Snapshot定義如下:
Snapshot is a present stock, future, option info. It contain open, high, low, close, change price, average price, volume, total volume, buy price, buy volume, sell price, sell volume and yesterday volume.
也就是股票、期貨、選擇權的當下資訊的摘要整理資訊。
直接使用範例程式看結果比較有感覺,Snapshot可一次放入多筆Contracts。 我們將2330台積電與2409友達光電放入作 快照:
contracts = [api.Contracts.Stocks['2330'], api.Contracts.Stocks['2409']]
snapshots = api.snapshots(contracts)
df = pd.DataFrame(snapshots)
df.ts = pd.to_datetime(df.ts)
print(df)
Output結果如下:
amount average_price buy_price buy_volume change_price change_rate \
0 25695000 571.26 570.0 2289.0 -4.00 -0.70
1 6014400 16.95 16.8 3349.0 -0.25 -1.47
change_type close code exchange high low open sell_price \
0 ChangeType.Down 571.0 2330 TSE 575.0 570.0 572.00 571.00
1 ChangeType.Down 16.8 2409 TSE 17.2 16.8 17.15 16.85
sell_volume tick_type total_amount total_volume ts \
0 19 TickType.Buy 10804728928 18914 2021-10-13 14:30:00
1 218 TickType.Sell 997845168 58854 2021-10-13 14:30:00
volume volume_ratio yesterday_volume
0 45 0.71 26522.0
1 358 0.83 71159.0
Order與掛單
證券的買賣交易是投資人最關心的行為,當然程式交易必定終究還是要出手的。 當然交易不是買,就是賣,但其中有不少的交易特性是需要了解的,其Order的屬性如下:
price (float or int): the price of order
quantity (int): the quantity of order
action (str): order action to buy or sell
{Buy, Sell}
price_type (str): pricing type of order
{LMT, MKT, MKP} (限價、市價、範圍市價)
order_type (str): the type of order
{ROD, IOC, FOK}
order_cond (str): order condition stock only
{Cash, MarginTrading, ShortSelling} (現股、融資、融券)
order_lot (str): the type of order
{Common, Fixing, Odd, IntradayOdd} (整股、定盤、盤後零股、盤中零股)
first_sell {str}: the type of first sell
{true, false}
account (:obj:Account): which account to place this order
ca (binary): the ca of this order
價格與數量這不用多說,但當然你是買一般整股還是零股交易,數量的單位數是不同的需要特別注意。
再來就是會影響成交行為的掛單類型:ROD
, IOC
, FOK
- ROD (Rest of Day):當日有效,這是一般股市下單的預設值。也就是你下的張數或股數,在今日收盤入都有效。所以如果要買入5張股票,先成交了3張,另外2張會繼續自動掛單。
- IOC (Immediate or Cancel):可同意部份成交,以剛的例子先成交了3張後,另2張就取消。
- FOK (Fill or Kill):也就是只能全部數量成交才算,否則就直接全部取消。
而以上的Order物件,是純粹就「不含Contract的交易資訊」進行設定,設定好了後,才和你要的標的物Contract一起送到api.place_order()
中。
我們就進行針對友達光電2409進行小買5張的掛單實例:
TSE2409 = api.Contracts.Stocks.TSE.TSE2409
order = api.Order(
price=17.0,
quantity=5,
action=sj.constant.Action.Buy,
price_type=sj.constant.StockPriceType.LMT,
order_type=sj.constant.TFTOrderType.ROD,
account=api.stock_account
)
trade_2409 = api.place_order(TSE2409, order)
print(trade_2409)
上述先準備好目標Contract,然後是要掛單的Order設定。 我們以17.0元,下5張委買,使用限價模式以及ROD掛單。接著就可以把呼叫place_order()掛單。
以下是掛單的資訊:
contract=Stock(exchange=<Exchange.TSE: 'TSE'>, code='2409', symbol='TSE2409', name='友達', category='26', unit=1000, limit_up=18.75, limit_down=15.35, reference=17.05, update_date='2021/10/13', margin_trading_balance=99098, short_selling_balance=1344, day_trade=<DayTrade.Yes: 'Yes'>) order=Order(action=<Action.Buy: 'Buy'>, price=17.0, quantity=5, id='e40a1458', seqno='100538', ordno='00000', account=Account(account_type=<AccountType.Stock: 'S'>, person_id='PAPIUSER02', broker_id='9A95', account_id='0504486', signed=True), price_type=<StockPriceType.LMT: 'LMT'>, order_type=<FuturesOrderType.ROD: 'ROD'>) status=OrderStatus(id='e40a1458', status=<Status.PendingSubmit: 'PendingSubmit'>, status_code='0', order_datetime=datetime.datetime(2021, 10, 13, 22, 45, 23), deals=[])
上面的資訊,分為contract
、order
以及status
三部份,而status中我們可看到目前狀態為PendingSubmit
(傳送中)。
共有以下的狀態:
- PendingSubmit: 傳送中
- PreSubmitted: 預約單
- Submitted: 傳送成功
- Failed: 失敗
- Cancelled: 已刪除
- Filled: 完全成交
- Filling: 部分成交
更新掛單狀態
可使用api.update_status()
對帳戶進行狀態更新,裡面傳入的參數是證券帳戶。
例如:
api.update_status(api.stock_account)
而我們可以把剛剛上面使用變數接值下來的交易trade,進行其他的操作,例如取消單或修改單量或價格等。
我們以下面的取消單實例,看一下status的變化:
trade_2409 = api.place_order(TSE2409, order)
print(trade_2409)
api.update_status(api.stock_account)
print(trade_2409)
api.cancel_order(trade_2409)
api.update_status(api.stock_account)
print(trade_2409)
我們只列出上面三次print(trade_2409)的status的部份:
status=OrderStatus(id='e0d6ad73', status=<Status.PendingSubmit: 'PendingSubmit'>, status_code='0', order_datetime=datetime.datetime(2021, 10, 13, 22, 57, 2), deals=[])
status=OrderStatus(id='e0d6ad73', status=<Status.PreSubmitted: 'PreSubmitted'>, status_code='R', order_datetime=datetime.datetime(2021, 10, 13, 22, 57, 2), deals=[])
status=OrderStatus(id='e0d6ad73', status=<Status.Cancelled: 'Cancelled'>, status_code='X', order_datetime=datetime.datetime(2021, 10, 13, 22, 57, 2), cancel_quantity=5, deals=[])
可看到上述的status歷經了:PendingSubmit(傳送中) → PreSubmitted(預約單) → Cancelled(已刪除)
看一下期貨與選擇權的Order
都看了股票了,也把期貨與選擇權的Order屬性也一併確認一下:
price (float or int): the price of order
quantity (int): the quantity of order
action (str): order action to buy or sell
{Buy, Sell}
price_type (str): pricing type of order
{LMT, MKT, MKP} (限價、市價、範圍市價)
order_type (str): the type of order
{ROD, IOC, FOK}
octype (str): the type or order to open new position or close position future only
{Auto, NewPosition, Cover, DayTrade} (自動、新倉、平倉、當沖)
account (:obj:Account): which account to place this order
ca (binary): the ca of this order
上述在octype
和股票不太相同。
模擬期貨掛單
我們針對大台指TXF 2021年10月份期貨進行新倉掛買進2口。
TXF202110 = api.Contracts.Futures.TXF.TXF202110
order = api.Order(action="Buy",
price=16355,
quantity=2,
price_type=sj.constant.StockPriceType.LMT,
order_type=sj.constant.FuturesOrderType.ROD,
octype=sj.constant.FuturesOCType.Auto,
account=api.futopt_account)
trade_txf202110 = api.place_order(TXF202110, order)
print(trade_txf202110)