Shioaji

Shioaji is sinopac provide the most pythonic api for trading the taiwan and global financial market. You can use your favorite Python packages such as numpy, scipy, pandas, pytorch or tensorflow to build your own trading model with intergrated the shioaji api on cross platform.



Installation

install

Let’s get it

pip install

直接pip install起來,台灣應該沒有其他券商的api那麼方便了。

pip install shioaji

docker

我們也準備好了docker image給各位直接使用,有需要那些其他的linux distribution歡迎在github上跟我們講。

docker run -it sinotrade/shioaji:latest bash

這邊沒有在使用docker的可以忽略,docker主要就是幫各位處理好各種環境問題,但是基本上大家應該pip install就可以開了

這邊也幫大家build好jupyter的環境,執行下面docker指令連到localhost:8888就可以使用了

docker run -p 8888:8888 sinotrade/shioaji:jupyter

Initialization

init

pip install shioaji 了之後,接著我們就可以用 python, ipython, jupyter notebook 或 JupyterLab 等編輯器開始接下來旅程。

在這邊我們還需要一個條件,就是請先開好永豐金證券的帳戶,實體開戶或是直接線上開戶

準備好永豐帳戶就讓我們開始吧!

載入

起手式 import我們的api就像import tensorflow pandas等等一樣

import shioaji as sj

初始api

接著我們需要初始化Shioaji這個物件來開始接下來要做的事

ipython有個很方便的方法可以看這個物件或函式的文件,就是直接在function或object後面加上?

下面文件部分可以看到我們api底下所有可以用的function跟object以及初始化Shioaji的參數說明

input

sj.Shioaji?

output

Init signature: sj.Shioaji(backend='http', simulation=True, proxies={}, currency='NTD')
Docstring:    
shioaji api 

Functions:
    login 
    activate_ca
    list_accounts
    set_default_account
    get_account_margin 
    get_account_openposition
    get_account_settle_profitloss
    place_order
    update_order
    update_status
    list_trades

Objects:
    Contracts
    Order
Init docstring:
initialize Shioaji to start trading

Args:
    backend (str): {http, socket} 
        use http or socket as backend currently only support http, async socket backend coming soon.
    simulation (bool): 
        - False: to trading on real market (just use your Sinopac account to start trading)
        - True: become simulation account(need to contract as to open simulation account)
    proxies (dict): specific the proxies of your https
        ex: {'https': 'your-proxy-url'}
    currency (str): {NTX, USX, NTD, USD, HKD, EUR, JPY, GBP}
        set the default currency for display

這邊我們選擇http為backend,並且關閉模擬模式,如果有需要使用模擬的客戶麻煩在gitter中聯絡我們,http比較完整socket會在近日釋出敬請期待。

input

api = sj.Shioaji(backend='http', simulation=False)

登入

接著我們要登入才有辦法開始使用api,登入帳號就是永豐金證券電子平台(如:eLeader)的登入帳號密碼。

input

api.login?

output

Signature: api.login(person_id, passwd)
Docstring:
login to trading server

Args:
    person_id (str): Same as your eleader, ileader login id(usually your person ID)
    passwd  (str): the password of your eleader login password(not ca password)

登入後會預設抓出第一個期貨帳戶與證券戶作為預設帳戶

input

api.login(person_id=person_id, passwd='2222')
api.fut_account

output

FutureAccount(person_id='SCCEIEFAJA', broker_id='F002000', account_id='9104000', username='莊*芬')

也可以列出我們所有帳戶,並使用api.set_default_account將常用設為預設的帳戶

input

api.list_accounts()

output

[Account(account_type='H', person_id='QCCAHIFFDH', broker_id='1300', account_id='09800762', username='n*m'),
FutureAccount(person_id='SCCEIEFAJA', broker_id='F002000', account_id='9104000', username='莊*芬'),
StockAccount(person_id='SCCEIEFAJA', broker_id='9A92', account_id='9802195', username='莊*芬')]

激活憑證

以上動作已經完成與下單無關的動作的初始化了,需要下單的話必須啟動憑證,若只是帳務相關等功能無需憑證。

input

api.activate_ca?

output

Signature: api.activate_ca(ca_path, ca_passwd, person_id)
Docstring:
activate your ca for trading

Args: 
    ca_path (str):
        the path of your ca, support both absloutely and relatively path, use same ca with eleader
    ca_passwd (str): password of your ca
    person_id (str): the ca belong which person ID

input

api.activate_ca(ca_path='../ca/Sinopac.pfx', ca_passwd='SCCEIEFAJA', person_id=person_id)

output

Ca Initial Done.
0

Ordering

order

開始下單的部分吧!首先api的place_order下單的函式中,需要傳入兩個物件,分別是Contract及Order,我們可以從Contracts物件中找到我們要交易的商品Contract,以及用Order製作出一筆order物件,然後丟進函式中,這個函式會回傳一個Trade物件包含Contract, Order及這筆單的狀態物件(OrderStatus)。

Order物件

Order物件需要帶入的參數部分一樣可以用?直接看到文件

input

api.Order?

output

Init signature: api.Order(action, price_type, order_type, price, quantity, *args, **kwargs)
Docstring:     
The basic order object to place order

Attributes:
    product_id (str): the code of product that order to placing
    action (srt): {B, S}, order action to buy or sell
        - B: buy
        - S: sell
    price_type (str): {LMT, MKT, MKP}, pricing type of order
        - LMT: limit
        - MKT: market
        - MKP: market range
    order_type (str): {ROD, IOC, FOK}, the type of order
        - ROD: Rest of Day
        - IOC: Immediate-or-Cancel
        - FOK: Fill-or-Kill
    octype (str): {' ', '0', '1', '6'}, the type or order to open new position or close position 
        - ' ': auto
        - '0': new position
        - '1': close position
        - '6': day trade
    price (float or int): the price of order
    quantity (int): the quantity of order
    account (:obj:Account): which account to place this order
    ca (binary): the ca of this order

接著我們有做一件方便大家開發的事,有兩個物件api.OrderPropsapi.Contracts這兩個物件可以快速輔助開發的時候直接用tab自動補齊的方式找到Order物件中需要填入的欄位。

input

api.OrderProps.</tab>
api.Contracts.</tab>

這邊我們以期貨為範例按tab鍵自動補齊可交易的合約,回傳的Future物件就是一個期貨的Contract物件,可以以isinstance(api.Contracts.Futures.TXF.TXF201903, shioaji.contracts.Contract)來確認他確實是個Contract物件 input

api.Contracts.Futures.TXF

output

TXF(TXF201903, TXF201906, TXF201809, TXF201810, TXF201811, TXF201812)

input

api.Contracts.Futures.TXF.TXF201903

output

Future(symbol='TXF201903', code='TXFC9', name='台指期貨', category='TXF', delivery_month='201903', underlying_kind='I', underlying_code='#001', unit=1.0)

知道使用方式後我們直接用自動補齊的方式幫我快速創建一筆Order,參數在OrderProps都有相對應的欄位可以幫我們免去用文件的選項輸入,當然也可以直接使用文件的選項直接填入。

sample_order = api.Order(price=9600,
                         action=api.OrderProps.action.Buy,
                         price_type=api.OrderProps.price_type.LMT,
                         order_type=api.OrderProps.order_type.ROD,
                         octype=api.OrderProps.octype.auto,
                         quantity=5,
                         account=api.fut_account,
                        )

另外為了不用煩鎖的Order我們可以直接使用MarketOrder, LimitOrder物件,需要填的選項就會很少。

MarketOrder

MarketOrder

    Args:
        product_id (str, optional): the code of product that order to placing 
                                    if not provide will gen from contract when placing order 
        action (srt): {B, S}, order action to buy or sell
            - B: buy
            - S: sell
        quantity (int): the quantity of order
        order_type (str, optional): {IOC, FOK}, the type of order
            - IOC: Immediate-or-Cancel
            - FOK: Fill-or-Kill
        octype (str, optional): {' ', '0', '1', '6'}, the type or order 
                                to open new position or close position 
                                if not provide will become auto mode 
            - ' ': auto
            - '0': new position
            - '1': close position
            - '6': day trade

製作一個MarketOrder物件就非常簡單,用下面填入買或賣,及口數就完成了。 > input

sample_mkt_order = api.MarketOrder('B', 5)
sample_mkt_order

output

MarketOrder(action='B', order_type='IOC', quantity=5)

LimitOrder

LimitOrder

    Args:
        product_id (str, optional): the code of product that order to placing 
                                    if not provide will gen from contract when placing order 
        action (srt): {B, S}, order action to buy or sell
            - B: buy
            - S: sell
        price (float or int): the price of order
        quantity (int): the quantity of order
        order_type (str, optional): {ROD, IOC, FOK}, the type of order
            - ROD: Rest of Day
            - IOC: Immediate-or-Cancel
            - FOK: Fill-or-Kill
        octype (str, optional): {' ', '0', '1', '6'}, the type or order 
                                to open new position or close position 
                                if not provide will become auto mode 
            - ' ': auto
            - '0': new position
            - '1': close position
            - '6': day trade

限價單的部分就多一個參數,價格就完成了。

input

sample_limit_order = api.LimitOrder('B', 9700, 5)
sample_limit_order

output

LimitOrder(action='B', order_type='ROD', price=9700, quantity=5)

下單函式

接著我們把製作好的Contract及Order物件傳進place_order函式中就會送出委託單了,這時候會回傳trade物件,Trade.status底下會是這筆交易的狀態,目前可以看到剛下出去是PendingSubmit。

input

txf = api.Contracts.Futures.TXF.TXF201903
trade = api.place_order(txf, sample_order)

output

Trade(contract=Future(symbol='TXF201903', code='TXFC9', name='台指期貨', category='TXF', delivery_month='201903', underlying_kind='I', underlying_code='#001', unit=1.0), order=Order(product_id='TXFC9', action='B', price_type='LMT', order_type='ROD', price=9600, quantity=5, account=FutureAccount(person_id='SCCEIEFAJA', broker_id='F002000', account_id='9104000', username='莊*芬')), status=OrderStatus(seqno='701124', order_id='7521840eb43914f94f98f025b1762e0b250ded21', status='PendingSubmit', order_datetime=datetime.datetime(2019, 1, 16, 12, 39, 28)))

Trade

拿到的Trade物件我可以透過update_status函式來更新所有Trade的狀態,這時候就會看到狀態變為Submitted,成交後會變為Filled。

input

api.update_status()
trade

output

Trade(contract=Future(symbol='TXF201903', code='TXFC9', name='台指期貨', category='TXF', delivery_month='201903', underlying_kind='I', underlying_code='#001', unit=1.0), order=Order(product_id='TXFC9', action='B', price_type='LMT', order_type='ROD', price=9600, quantity=5, account=FutureAccount(person_id='SCCEIEFAJA', broker_id='F002000', account_id='9104000', username='莊*芬')), status=OrderStatus(seqno='701124', ordno='ky00P', order_id='7521840eb43914f94f98f025b1762e0b250ded21', status='Submitted', status_code='0000', msg='ky00P', modified_price=9600.0, remaining=5, order_datetime=datetime.datetime(2019, 1, 16, 12, 39, 28)))

改價或改量的部分使用api.update_order函式傳入Trade物件,可以看到modified_price就變成9800並

input

trade = api.update_order(trade, price=9800, qty=1)
trade

output

Trade(contract=Future(symbol='TXF201903', code='TXFC9', name='台指期貨', category='TXF', delivery_month='201903', underlying_kind='I', underlying_code='#001', unit=1.0), order=Order(product_id='TXFC9', action='B', price_type='LMT', order_type='ROD', price=9600, quantity=5, account=FutureAccount(person_id='SCCEIEFAJA', broker_id='F002000', account_id='9104000', username='莊*芬')), status=OrderStatus(seqno='701124', ordno='ky00P', order_id='7521840eb43914f94f98f025b1762e0b250ded21', status='Submitted', status_code='0000', msg='ky00P', modified_price=9800.0, remaining=5, order_datetime=datetime.datetime(2019, 1, 16, 12, 39, 28)))

取消委託使用api.cancel_order函式並傳入欲取消的trade物件,就不寫出範例code了。


Account

account

下單ok後接著看帳務部分,帳務部份我們為了方便的與python的ecosystem結合,我們製作了將帳務的物件快速地轉換,就可以直接地變成pandas的Dataframe方便各位與自己的機器學習或深度學習模型直接介接。

權益數帳務

input

api.get_account_margin?

output

Signature: api.get_account_margin(currency='NTD', margin_type='1', account={})
Docstring:
query margin    currency: {NTX, USX, NTD, USD, HKD, EUR, JPY, GBP}
the margin calculate in which currency
    - NTX: 約當台幣
    - USX: 約當美金
    - NTD: 新台幣
    - USD: 美元
    - HKD: 港幣
    - EUR: 歐元
    - JPY: 日幣
    - GBP: 英鎊
margin_type: {'1', '2'}
    query margin type
    - 1 : 即時
    - 2 : 風險

input

account_margin = api.get_account_margin()
account_margin

output

AccountMargin
    Currency: NTD
    Account: F0020009104000
    Detail:
        OrderPSecurity: 207000.0
        ProfitAccCount: 207000.0
        FProfit: 0.0
        FMissConProfit: 0.0
        OMissConProfit: 0.0
        OColse: 0.0
        OMarketPrice: 0.0
        OTodayDiff: 0.0
        HandCharge: 0.0
        TradeTax: 0.0
        Security: 0.0
        StartSecurity: 0.0
        UpKeepSecurity: 0.0
        Statistics: 99999.0
        Flow: 999.0
        orderBid: 0.0
        orderAsk: 0.0
        Conclusionbid: 0.0
        Conclusionask: 0.0
        YesterdayBalance: 207000.0
        PayMoney: 0.0
        Equity: 207000.0
        Ogain: 0.0
        exrate: 1.0
        xgdamt: 0.0
        agtamt: 0.0
        YesterdayEquity: 207000.0
        Munet: 0.0
        Cashamt: 207000.0
        Bapamt: 0.0
        Sapamt: 0.0
        Adps: 0.0
        Adamt: 0.0
        Ybaln: 207000.0

直接用將物件傳入pandas.DataFrame就可以簡單的拿到常用的dataframe了

input

df_margin = pd.DataFrame([{**account_margin}])
df_margin

output

Adamt Adps Bapamt Cashamt Conclusionask Conclusionbid Equity FMissConProfit FProfit Flow TradeTax UpKeepSecurity Ybaln YesterdayBalance YesterdayEquity agtamt exrate orderAsk orderBid xgdamt
0 0.0 0.0 0.0 288000.0 0.0 0.0 288000.0 0.0 0.0 999.0 0.0 0.0 207000.0 207000.0 207000.0 0.0 1.0 0.0 0.0 0.0

1 rows × 34 columns

未平倉帳務

input

api.get_account_openposition?

output

Signature: api.get_account_openposition(product_type='0', query_type='0', account={})
Docstring:
query open position
product_type: {0, 1, 2, 3}
    filter product type of open position
    - 0: all
    - 1: future
    - 2: option
    - 3: usd base
query_type: {0, 1}
    query return with detail or summary
    - 0: detail
    - 1: summary

input

positions = api.get_account_openposition(query_type='1', account=api.fut_account)
positions

output

AccountOpenPosition

轉換成dataframe

input

df_positions = pd.DataFrame(positions.data())
df_positions

output

Account Code CodeName ContractAverPrice Currency Date FlowProfitLoss MTAMT OTAMT OrderBS OrderNum OrderType RealPrice SettlePrice SettleProfitLoss StartSecurity UpKeepSecurity Volume paddingByte
0 FF0020009104000 TXFA9 台指期貨 01 9508.4137 NTD 00000000 4795201.620000 6438000.000000 8352000.000000 B 9784.0 9784.00 4795201.620000 8352000.000000 6438000.000000 87.000000
1 FF0020009104000 XJFF9 日圓期貨 06 80.0000 JPY 00000000 31400.000000 47000.000000 61000.000000 B 0.0 81.57 31400.000000 61000.000000 47000.000000 1.000000
2 FF0020009104000 TXO08000L8 台指選擇權 8000 C 12 1870.0000 NTD 00000000 -14000.000000 0.000000 0.000000 B 1730.0 1810.00 -6000.000000 0.000000 0.000000 2.000000
3 FF0020009104000 TXO09200L8 台指選擇權 9200 C 12 720.0000 NTD 00000000 11250.000000 147000.000000 162000.000000 S 645.0 660.00 9000.000000 162000.000000 147000.000000 3.000000
4 FF0020009104000 TXO09400X8 台指選擇權 9400 P 12 199.0000 NTD 00000000 21200.000000 57600.000000 65600.000000 S 93.0 93.00 21200.000000 65600.000000 57600.000000 4.000000
5 FF0020009104000 TXO10200L8 台指選擇權 10200 C 12 111.0000 NTD 00000000 33550.000000 125950.000000 147950.000000 S 50.0 50.00 33550.000000 147950.000000 125950.000000 11.000000

平倉損益

input

api.get_account_settle_profitloss?

output

    Signature: api.get_account_settle_profitloss(product_type='0', summary='Y', start_date='', end_date='', currency='', account={})
    Docstring:
    query settlement profit loss
    product_type: {0, 1, 2}
        filter product type of open position
        - 0: all
        - 1: future
        - 2: option
    summary: {Y, N}
        query return with detail or summary
        - Y: summary
        - N: detail
    start_date: str
        the start date of query range format with %Y%m%d
        ex: 20180101
    end_date: str
        the end date of query range format with %Y%m%d
        ex: 20180201
    currency: {NTD, USD, HKD, EUR, CAD, BAS}
        the profit loss calculate in which currency
        - NTD: 新台幣
        - USD: 美元
        - HKD: 港幣
        - EUR: 歐元
        - CAD: 加幣 
        - BAS: 基幣

input

st_date = (date.today() - timedelta(days=60)).strftime('%Y%m%d')
settle_profitloss = api.get_account_settle_profitloss(summary='Y', start_date=st_date)
settle_profitloss

output

AccountSettleProfitLoss

轉換成dataframe

input

df_profitloss = pd.DataFrame(settle_profitloss.data())
df_profitloss

output

account averagePrice code codeName currency floatProfitLoss handCharge ord_bs ord_type ordno ordno_b settleAvgPrc settleDate settleVolume tFlag tdate tradeProfitLoss tradeTax unVolume volume
0 F0020009104000 9900.0 TXFK8 台指期貨 11 NTD 460.000000 60.000000 S 00 kY002 kY003 9897.0 20181022 1.000000 1 20181022 600.000000 80.000000 0.000000 1.000000

DevelopEnvSetup

開發環境設置Windows

Windows開發環境安裝app清單

  • git(version control)
  • vscode(text editor)
  • miniconda(python package management)
  • docker(optional)

Git

下載window版本Git 安裝時請選Use Git and optional Unix tools from the Windows Command Prompt

VSCode

下載Windows版本VSCode 安裝後到插件管理中搜尋python並安裝

miniconda

下載miniconda 我們在windows中使用miniconda來安裝我們的環境,安裝完成後打開cmd,輸入 conda install jupyterlab pandas -y 把相關的套件裝好接著輸入jupyter lab,打開瀏覽器連到 localhost:8888 就可以連到jupyter開始使用。