顯示具有 群益API 標籤的文章。 顯示所有文章
顯示具有 群益API 標籤的文章。 顯示所有文章

2023年2月20日 星期一

使用 pythonnet 呼叫群益api

 多年前曾用想要用pythonnet,來載入群益的api ,但最後失敗了。這篇純粹是出自個人好奇,還是想了解是否能用 pythonnet 來載入 dll,最近找到可以使用的步驟了,在windows下 python 可以呼叫群益api,讓熟悉 C# 的開發者,又想用 python 的人多一種選擇。

    目前使用這個方法的好處:

  1. 在 juypterlab 下,可以顯示各個 function 參數有哪些,減少一直翻手冊的時間。
  2. callback 部屬比較直覺快速,但也因此比較冗長。
  3. 熟悉 C# 的人,可以加入 C# 相關的 reference, namespace 當作 python 的模組來使用。
  4. 其他券商的 dll 檔,也有機會用這套方法來呼叫? 

    壞處:

  1. 目前遇到狀況是 callback 出現錯誤時,python沒有任何錯誤通知,除錯比較麻煩。


我的安裝環境:

  • windows 10, 
  • 我使用的是python 3.10.5 
  • visual studio 2022 (只是為了使用它的 tlbimp.exe)

前置工作

1. 用 tlbimp.exe 將 SKCOM.dll 轉成  Type library

    要先將群益的SKCOM.dll 轉成  Type library,我有安裝 visual studio 2022,利用它附帶的 comandline prompt terminal ,下指令 tlbimp.exe 將 SKCOM.dll 轉成 typelib 形式,最終產生 SKCOMLib.dll 的檔案。之後就可以輕鬆用 pythonnet 的 clr 模組取用。




2. 安裝 pythonnet

    Python.NET 模組可以讓 python 使用者無縫整合 .NET Common Language Runtime (CLR)。它讓 Python 可以跟 CLR 互動, 甚至也可以反過來將 Python 包進 .NET 裡.
    在你的 python 環境下用 pip 安裝 pythonnet 即可。詳細操作請看 pythonnet 官網


    pip install pythonnet


使用 pythonnet 的 clr 模組呼叫 SKCOMAPI











2020年6月24日 星期三

在 linux 下使用wine python 串接群益 SKCOM API

        群益api 是使用 windows 的 COM 技術,在 linux 下要靠 wine 來模擬 windows 的環境。wine 要使用 32 bit 的相容性比較好,因此本篇 linux 系統 , python, skcom.dll 皆是使用 32 bit版。

操作概念是 在 linux 下裝 wine 註冊 SKCOM.dll, 用 wine 安裝 windows 版本的 python,  再用這個windows 版的 python 安裝 comtypes, pywin32 等套件來使用 skcom。 整個環境會是在 wine 底下執行的,操作起來還是有點隔閡,不是很順暢,我也還在摸索 

linux 我使用 lubuntu 18.04 alternative-i386 這個桌面版本, 執行Wine時建議是要在有XWindow的環境下執行,安裝一些 windows 程式,會需要 GUI 的操作 

linux wine 的安裝跟使用是參考這兩篇, 研究的超仔細,大推!! 

安裝 wine, winetricks

  • 建議使用32位元的作業系統來安裝Wine,因為Wine目前64位元的支援很差,它主要是以執行32位元的Windows程式為主!
  • 建議是透過compile Wine原始碼的方式來安裝Wine,也是為了避免32位元的函式庫裝得不夠完整!
  • winetricks 可以幫助安裝 VC++ runtime 2010 ,註冊 SKCOM.dll 時需要用到 
  • 剛裝好的 lubuntu 環境,把 apt 更新至最新,並裝下列開發套件,編譯 Wine 需要用到
$ sudo apt update; apt upgrade
$ sudo apt install openssh-client openssh-server vim software-properties-common gcc g++ vim subversion automake autoconf perl patch build-essential libtool doxygen bison flex zlib1g-dev gperf tofrodos wget curl screen git samba vsftpd bash-completion ftp colordiff libkrb5-dev rar unrar unzip vnstat libssl-dev
  • 補足所需的套件
$ time apt install gnome-devel libx11-dev flex bison qt5-qmake libjpeg-dev libxslt1-dev libglu1-mesa-dev freeglut3-dev prelink libasound2-dev libfreetype6-dev libpng-dev libxml2-dev libxrender-dev libgl1-mesa-dev libgphoto2-dev libmpg123-dev libtiff-dev libpulse-dev liblcms2-dev libcapi20-dev libldap-dev libopenal-dev libv4l-dev libsane-dev libcups2-dev libgsm1-dev libosmesa6-dev libgnutls28-dev libpcap0.8-dev oss4-dev libcdk5-dev libgstreamer-plugins-base1.0-dev libarrayfire-opencl-dev
$ time apt install libsdl2-dev libvulkan-dev
  • 清除一下apt-get抓下來的殘餘檔
$ apt clean
  • 用root帳號登入
  • 先把Wine的git repository上的code拉下來!
$ mkdir -pv /root/packages ; cd /root/packages
$ time git clone https://github.com/wine-mirror/wine

  • 檢查套件是否足夠
$ cd ./wine
$ ./configure 

 #訊息大概剩下下面這樣,就差不多了。
configure: MinGW compiler not found, cross-compiling PE files won't be supported.
configure: libhal development files not found, no legacy dynamic device support.
configure: libFAudio development files not found, XAudio2 won't be supported.
configure: vkd3d development files not found (or too old), Direct3D 12 won't be supported.
  • 接下來編譯並且安裝!編譯會花大約40-60分鐘
$ time make
$ time make install
  • 接下來安裝winetricks!直接從github wget下來就可以用了!
$ mkdir -pv /opt/bin ; cd /opt/bin
$ wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
$ chmod +x ./winetricks
$ ./winetricks -V  

#檢查版本,出現下列訊息就沒問題了
20190615-next - sha256sum: 47304e177f259d6f9c05af01ab42c06531fd8a9716e2751d2fadcd664130feea

Wine 使用 SKCOM api

  • 設定Wine的windows環境,在 XWindow環境下。第一次使用須初始化一個windows 環境,打開Terminal,執行以下指令以設定Wine的環境!我的環境是建立在 ~./home/使用者/.wine 下,.wine 就是windows 虛擬的系統,底下有個 drive_c 資料夾,等於 C:\  槽
$ wineboot  

  • 群益API的SKCOM.dll檔需要 VC++ 2010可轉散發套件, 可透過winetricks來安裝 vcrun2010
$ winetricks vcrun2010 

  • 下載群益API,將API 資料夾 CapitalAPI_2.13.22 下的x86 資料夾搬到 ~/.wine/drive_c/skcom/x86  這等於是存在 windows 的 C:\\skcom\\x86, 之後使用python 呼叫會方便一點
  • cd 到 ~/.wine/drive_c/skcom/x86資料夾下,執行以下指令以註冊群益API:
$ regsvr32 ./SKCOM.dll

drive_c 下路徑的內容,skcom, python, strategy 是我自己創建的,資料夾名稱不要有空格,減少麻煩



wine下的 python環境

  • 用wine 來安裝 windows版的 python
  • 到 python 官網,我選了 Python3.8.3 的 Windows x86 executable installer 這個版本下載
  • 我有嘗試使用miniconda,但 conda 或 pip 位置不在預設路徑上,我搞不定,導致python套件裝不起來  

#使用 wine安裝windows版的python
#會有GUI跳出,可將python裝在 C:\\python 路徑下
$ wine python-3.8.3.exe   

#安裝 comtypes 及 pywin32 套件,其他python套件也可以如此安裝
$ wine pip install comtypes pywine32    


  • wine的windows版的 python 環境建置完成,可以開始 CODING!!
$ wine python



將寫好的 Script.py 交由 window python 執行, 要加wine 不然會呼叫到 linux系統下的 python, 兩個系統還是不相容的

$ wine python Script.py

附上 Script.py 的內容


import pythoncom, time, os
from comtypes.client import GetModule, GetEvents, CreateObject
from datetime import datetime

#第一次使用需要將 SKCOM 包成python 的package
#SKCOM.dll 在linux 下,我是放在 ~./home/yi/.wine/driv_c/skcom/x86/SKCOM.dll
#但在 wine 下,是放在下列路徑, drive_c 就是windows的C槽
GetModule(r'C:\\skcom\x86\SKCOM.dll')
#GetModule會在comtypes.gen 下產生 SKCOMLib package, 之後就用下面方式引用
import comtypes.gen.SKCOMLib as sk

#建立COM物件
if 'skC' not in globals(): skC=CreateObject(sk.SKCenterLib, interface=sk.ISKCenterLib)
if 'skQ' not in globals(): skQ=CreateObject(sk.SKQuoteLib, interface=sk.ISKQuoteLib)
if 'skR' not in globals(): skR=CreateObject(sk.SKReplyLib, interface=sk.ISKReplyLib)

#輸入身分證與密碼
ID=''
PW=''
#股票代號
strStock="TX00" 

print(str(datetime.now())[0:-4], 'ID & PW entered')

#建立事件類別
class skQ_events:                                
    def OnConnection(self, nKind, nCode):
        print(datetime.now(), 'OnConnection', nKind, nCode)
        if nKind == 3003:
            #nKind==3003 表連線報價主機就緒
            print("quoate server connected..., nkind= ", nKind)
            ncode=skQ.SKQuoteLib_RequestStocks(1, strStock)
            if ncode==0:
                print(strStock, 'requested')    
    
    def OnNotifyQuote(self, sMarket, sIndex):
        ts=sk.SKSTOCK()
        skQ.SKQuoteLib_GetStockByIndex(sMarket, sIndex, ts)
        print(ts.bstrStockName, ts.bstrStockNo,  ts.nClose/10**ts.sDecimal)
    
class skR_events:
    def OnReplyMessage(self, bstrUserID, bstrMessage, sConfirmCode=0xFFFF):
        print('OnReplyMessage', bstrMessage)
        return sConfirmCode
                            
#Event sink, 事件實體  
EventQ=skQ_events()
EventR=skR_events()

#make connection to event sink
ConnectionQ = GetEvents(skQ, EventQ)
ConnectionR = GetEvents(skR, EventR)

if __name__=='__main__':
    #登入
    nCode=skC.SKCenterLib_Login(ID, PW)
    print("Login,", skC.SKCenterLib_GetReturnCodeMessage(nCode))
    #連線報價主機
    print(f"{datetime.now()}, EnterMonitor,", skC.SKCenterLib_GetReturnCodeMessage(skQ.SKQuoteLib_EnterMonitor()))
    # Event loop, 持續檢查有沒有event產生
    pythoncom.PumpMessages()



輸出結果,大概類似下圖,夾雜很多 fixme的警告,但不影響使用







2019年10月13日 星期日

群益api 選擇擇權代碼規則

群益API 選擇權代碼規則
感謝 FB 網友提供

Call option : A~L代表1~12月
Put option  : M~X代表1~12月。
群益的編碼邏輯都是 TX+@+strike+$+到期年分。 

@:  可以是O代表一般月結算的選擇權,若以是數字則代表為 1~4 的週選。
$  : 是選擇權到期的月份,所以call跟put是不同的。

ex.
TXO10700L2     台指選, 履約價 10700,  12 月, 2022年 的 call  
TXO10700X2     台指選, 履約價 10700, 12 月, 2022年 的 put

TXO14800A3      台指選, 履約價 14800,  1 月, 2023年 的 call  
TXO14800M3     台指選, 履約價 14800,  1 月, 2023年 的 put

TX213000L2 台指週選 W2, 履約價 13000,  12 月, 2022年 的 call
TX213000X2    台指週選 W2, 履約價 13000,  12 月, 2022年 的 put



Ref:

2019年7月27日 星期六

群益API python 下單範例

今天來示範下單, 請務必搞懂每個參數後在下單喔
我自己不放心所以去申請了模擬平台帳號,在來試試看下單的功能,不過模擬帳號目前沒有提供夜盤的功能,就加減用吧!! 之前介紹模擬平台的文章,大家參考一下囉
模擬平台有練功跟競賽兩種帳號,我沒有研究,隨便拿一個來用



 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
from comtypes.client import GetModule, CreateObject, GetEvents
GetModule('C:\\skcom\\CapitalApi_2.13.17\\x64\\SKCOM.dll')
import comtypes.gen.SKCOMLib as sk
from datetime import datetime
import getpass

#建立物件,避免重複 createObject
#登錄物件
if 'skC' not in globals(): skC=CreateObject(sk.SKCenterLib, interface=sk.ISKCenterLib)
#下單物件
if 'skO' not in globals(): skO=CreateObject(sk.SKOrderLib , interface=sk.ISKOrderLib)   
#回報物件
if 'skR' not in globals(): skR=CreateObject(sk.SKReplyLib , interface=sk.ISKReplyLib)   

#輸入身分證與密碼

ID=''
PW=''
print(datetime.now(), 'ID & PW')

#建立事件類別             
class skO_events:
    def __init__(self):
        self.TFAcc=[]
        
    def OnAccount(self, bstrLogInID, bstrAccountData):
        strI=bstrAccountData.split(',')
        #找出期貨帳號
        if len(strI) > 3 :
            if strI[0] == 'TF' :
                self.TFAcc = strI[1]+strI[3]
            
class skR_events:        
    def OnReplyMessage(self, bstrUserID, bstrMessage, sConfirmCode=0xFFFF):
        '''API 2.13.17 一定要返回 sConfirmCode=0xFFFF'''
        print('skR_OnReplyMessage', bstrMessage)
        return sConfirmCode
    
    def OnData(self, bstrUserID, bstrData):
         #成交回報
        self.bstrOnData.append(datetime.now().strftime('%H:%M:%S,') + bstrData)
        strI = bstrData.split(",")
        print("skR_OnData", strI)
                        
    def OnNewData(self, bstrUserID , bstrData):
        print('skR_OnNewData', bstrData)

#Event sink, 事件實體
EventO=skO_events()
EventR=skR_events()

#make connection to event sink
ConnO = GetEvents(skO, EventO) 
ConnR = GetEvents(skR, EventR) 

print(datetime.now(), 'Making event objects')

%matplotlib auto
#登入模擬帳號
nCode=skC.SKCenterLib_ResetServer ("morder1.capital.com.tw")
print('set server to morder1.capital.com.tw', skC.SKCenterLib_GetReturnCodeMessage(nCode))

#login
nCode=skC.SKCenterLib_Login(ID,PW)
print('Login', skC.SKCenterLib_GetReturnCodeMessage(nCode))

#初始 Order 物件
nCode=skO.SKOrderLib_Initialize()
print("Initialize ", skC.SKCenterLib_GetReturnCodeMessage(nCode))

#初始 Cert by ID 物件,模擬平台不需要這個,會出現錯誤
nCode=skO.ReadCertByID(ID)
print("ReadCertByID ", skC.SKCenterLib_GetReturnCodeMessage(nCode))

#Get User TF Account
nCode=skO.GetUserAccount()
print("GetUserAccount ", skC.SKCenterLib_GetReturnCodeMessage(nCode), EventO.TFAcc)

#設定期貨單參數,請自行調整囉,注意參數的資料型別,例如 bstr開頭的是要輸入文字型態
#以下請再jupyter 裡用另外一個cell 跑
fo=sk.FUTUREORDER()
fo.bstrFullAccount=EventO.TFAcc      #TF 帳號
fo.bstrStockNo='MTX00'
fo.sBuySell=0                         #0 buy, 1 sell
fo.bstrPrice='10700'               #委託價格,「M」表示市價,{移動停損、MIT皆無須價格}
fo.nQty=1                              #交易口數
fo.sDayTrade=0                     #當沖0:否 1:是,可當沖商品請參考交易所規定。 
fo.sNewClose=2                     #新平倉,0:新倉 1:平倉 2:自動{新期貨、選擇權使用}
fo.sTradeType=1                    #0:ROD  1:IOC  2:FOK
fo.sReserved=0                     #盤別,0:盤中(T盤及T+1盤);1:T盤預約{新期貨、停損單使用}

#下單
nCode=skO.SendFutureOrder(ID, False, fo)
print(nCode)