按照官網的說法我們來寫一個簡單的登入
import shioaji as sj
api = sj.Shioaji()
accounts = api.login(api_key="請到永豐網站申請取得",
secret_key="請到永豐網站申請取得"
)
api.logout()
這樣就登入成功了!!!
但是注意因為永豐限制登入連線帳號數量,所以要記得登出api.logout()
print(accounts)
將以上程式碼加上這一行可以檢驗連線的狀況。
你會得到:
Response Code: 0 | Event Code: 0 | Info: host '203.66.91.161:80', hostname '203.66.91.161:80' IP 203.66.91.161:80 (host 1 of 1) (host connection attempt 1 of 1) (total connection attempt 1 of 1) | Event: Session up
[StockAccount(person_id='身分證', broker_id='9DFSDF5', account_id='073SDFSDF80', username='你名字')]
Contract物件是API的核心,因為他是商品的基本資料,需要以此物件指定要獲取的金融商品資料,有三種寫法,都是等價的:
api.Contracts.Stocks.TSE.TSE2890 #使用SYMBOL
api.Contracts.Stocks.TSE['2890'] #使用CODE
api.Contracts.Stocks['2890'] #使用CODE
以下是相關的屬性表格:
屬性 | 屬性值 | 說明 |
---|---|---|
exchange | <Exchange.TSE: 'TSE'> | 掛牌交易所(TSE:上市, OTC:上櫃, OES:興櫃) |
code | '2890' | 股票代碼 |
symbol | 'TSE2890' | |
name | '永豐金' | 股票名稱 |
category | '17' | 股票類型 |
unit | 1000 | 每單位股數 |
limit_up | 15.5 | 當日漲停價 |
limit_down | 12.7 | 當日跌停價 |
reference | 14.1 | 參考價格,即前一個交易日的收盤價 |
update_date | '2021/09/17' | 更新日期 |
day_trade | <DayTrade.Yes: 'Yes'> | 買賣現沖(OnlyBuy:先買現沖, Yes:買賣現沖, No:無現股當沖) |
margin_trading_balance | 0 | 融資限額 |
short_selling_balance | 0 | 融券限額 |
就是用來抓取股票當下的資訊,因此我們只需要傳入Contract組成的List,回傳就會是一個lsit
contracts = [api.Contracts.Stocks['2330'], api.Contracts.Stocks['2890']]
snapshots = api.snapshots(contracts)
屬性 | 值 | 說明 |
---|---|---|
code | '2330' | 股票代碼 |
exchange | 'TSE' | 掛牌交易所 |
high | 610.0 | 最高價 |
low | 599.0 | 最低價 |
open | 600.0 | 開盤價 |
close | 600.0 | 收盤價 |
volume | 57 | 成交量 |
amount | 34200000 | 成交金額 |
average_price | 601.91 | 均價 |
change_price | 0.0 | 變動價格 |
change_rate | 0.0 | 變動幅度(單位:%) |
change_type | <ChangeType.Unchanged: 'Unchanged'> | 變動類型 |
buy_price | 600.0 | 委買價 |
buy_volume | 1107.0 | 委買量 |
sell_price | 601.0 | 委賣價 |
sell_volume | 3 | 委賣量 |
tick_type | <TickType.Sell: 'Sell'> | tick類型 |
total_amount | 24508038290 | 總成交金額 |
total_volume | 40717 | 總成交量 |
ts | 1631889000000000000 | 時間戳 |
volume_ratio | 1.81 | 成交量比率(今日總成交量/昨日總成交量) |
yesterday_volume | 22539.0 | 昨日成交量(張數) |
tick又為成交明細,是每一筆成交的時間、數量、價格等等資訊的物件。我們一般盤後可以仰賴這個物件提供資料,以下是參數:
參數 | type | 意義 |
---|---|---|
contract | BaseContract | 傳入所要抓取ticks資料的Contract |
date | str | 交易日期,預設為程式執行當下的日期 |
query_type | TicksQueryType | 預設為抓當天一整天的資料 |
time_start | typing.Union[str, dt.time] | 資料開始時間,預設為None,即不指定開始時間 |
time_end | typing.Union[str, dt.time] | 資料結束時間,預設為None,即不指定結束時間 |
last_cnt | int | 僅回傳最後X筆資料,預設為0,即回傳所有的資料 |
timeout | int | |
cb |
對於程式交易,在盤中時需要取得即時的報價和成交資訊。儘管可以使用快照 (snapshots) 或 K 線 (kbars) 來獲取盤中資訊,但這兩種方法都會消耗較多資源。透過訂閱 (subscribe) 的方式,您可以同時訂閱多個金融商品的即時報價和成交資訊,並為回傳的內容編寫相應的執行動作(程式)。
與其他報價資訊相比,目前訂閱功能允許最多同時訂閱200個不同內容。
參數 | type | 意義 |
---|---|---|
contract | shioaji.contracts.Contract | contract |
quote_type | shioaji.constant.QuoteType | 報價類型,預設為tick資料 |
intraday_odd | bool | 盤中零股,預設為False,即現股資料 |
version | shioaji.constant.QuoteVersion | 報價資訊類型,用不太到 |
若要取消訂閱,可呼叫api.quote.unsubscribe,使用方式及參數與subscribe相同。
訂閱之後市場只要有成交就會回傳一筆資料。
以下是範例:
from shioaji import TickSTKv1, Exchange, Shioaji, constant
from threading import Event # event模組用於維持程式運作
import os
api = Shioaji()
accounts = api.login(api_key=os.getenv('API_KEY'),
secret_key=os.getenv('SECRET_KEY')
)
#訂閱個股盤中tick資訊
api.quote.subscribe(
api.Contracts.Stocks["2330"],
quote_type = constant.QuoteType.Tick,
version = constant.QuoteVersion.v1
)
# 維持程式運作等待交易資料送入
Event().wait()
# 定義quote_callback,即回傳報價資訊時所要執行的動作
@api.on_tick_stk_v1()
def quote_callback(exchange: Exchange, tick:TickSTKv1):
print(f"Exchange: {exchange}, Tick: {tick}") #將報價資訊內容輸出
api.logout()
交易股票時還有委買委賣的部分也可以讓API回傳,修改一下12、31行就可以了:
from shioaji import Exchange, Shioaji, constant, BidAskSTKv1
from threading import Event # event模組用於維持程式運作
api = Shioaji()
accounts = api.login(api_key="9EwVF2HtBmfeexfLBYUExWvFbaL6f1jenPfxESjSo4x5",
secret_key="5BW5ZxGc3Vz186y5EzhCeg7b25qC3bD2kk823t9L7kyx"
)
#訂閱個股盤中tick資訊
api.quote.subscribe(
api.Contracts.Stocks["2330"],
quote_type = constant.QuoteType.BidAsk,
version = constant.QuoteVersion.v1
)
# 維持程式運作等待交易資料送入
Event().wait()
# 定義quote_callback,即回傳報價資訊時所要執行的動作
@api.on_tick_stk_v1()
def quote_callback(exchange: Exchange, tick:BidAskSTKv1):
print(f"Exchange: {exchange}, Tick: {tick}") #將報價資訊內容輸出
api.logout()
下單需要下單的憑證(不然誰下單都行,太不安全了),啟用憑證前要先登入LOGIN,未來在CloudRun會將路徑等等寫在環境數中,這裡先這樣寫吧:
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'), # 身份證字號
)
電子憑證啟用成功,則回傳的result就會是True
在下單之前我們要建立Order物件,直接使用這個程式碼order = api.Order()
代入參數如下:
參數 | 參數說明 | 參數範例 |
---|---|---|
price | 委託價格 | 18.5 |
quantity | 委託數量 | 1 |
action | 委託單動作 | {Buy, Sell} |
price_type | 價格類型 | {LMT, MKT, MKP} |
order_type | 委託單類型 | {ROD, IOC, FOK} |
order_cond | 委託單種類 | {Cash, MarginTrading, ShortSelling} |
order_lot | 委託單交易單位 | {Common, Fixing, Odd, IntradayOdd} |
first_sell | 是否為現沖先賣 | {true, false} |
octype | 倉別 | {Auto, NewPosition, Cover, DayTrade} |
OptionRight | 選擇權類別 | {Call, Put} |
account | 交易帳戶 | 可由API取得account物件 |
已經把order建立起來了,要發出委託就要使用以下的函式:
api.place_order(
contract: Contract,
order: Order,
timeout: int = 5000
)
修改:
api.update_order(
trade: Trade, #傳入原本的委託單
price: typing.Union[StrictInt, float] = None, #變更後的委託價格
qty: int = None, #qty指的是所要取消的委託數量
timeout: int = 5000
)
刪除:
api.cancel_order(
trade: shioaji.order.Trade,
timeout: int = 5000
)
我們肯定會需要查庫存:
api.list_positions(
account: shioaji.account.Account = None, #交易帳戶,預設為None
unit: shioaji.constant.Unit = <Unit.Common: 'Common'>, #單位,預設為整股
timeout: int = 5000 #timeout預設為5000ms,即延遲時間?
)
今天先到這裡我好睏,明天我們就開始準備上雲的工作吧!!!不過明天是假日不能測試。