2017年7月31日 星期一

群益 API in pyhton 報價範例

群益api更新至2.13.8後,改一下順序,先呼叫 SKReplyLib_ConnectByID,再 EnterMonitor,才會可以收到 OnConnection 3003 的回報,然後就可以求報價了。本範例示範如何用python 接群益api的報價,希望能拋磚引玉, 讓更多能手參與。小弟python自學,COM 元件的運作也是一知半解,東拼西湊下還算可用,程式碼很醜請見諒。過程遇到一些錯誤,很多我無法解決,以下是我試誤各種組合後, 可以運作的一組方法,,若有更好的解法,請各位大大多加分享。

另外是事件處理,我用comtypes 中的 showevents 也有錯誤產生,於是用 pyhoncom.PumpWaitingMessages() 來代替

使用comtpyes 若出現
"comtypes com object's method returns: 'tuple' object has no attribute 'ctypes_from_outparam'",需要做一些修正 ,請參考
https://easontseng.blogspot.com/2017/07/install-pythoncom-tuple-object-has-no.html
#這個bug好像在最新版的comtypes中被修正了

弄個FB社團,大家來討論好了。
https://www.facebook.com/groups/1805224676441902/

運行環境:
winXP, Anaconda python3.4 32 bit, CapitalAPI 2.13.8, pywin32 build221, comtypes 1.1.3

參考文獻:
#pythoncom 是安裝 pywin32 附帶的
https://sourceforge.net/projects/pywin32/
#用pywin makepy utility 找 GUID
https://easontseng.blogspot.tw/2017/07/pywin32-com-makpy-utiltiy-api-com.html
#python 元大期貨 api,
http://hlfutures.blogspot.tw/2016/08/api-in-python_8.html

#comtpyes:
https://pythonhosted.org/comtypes/
http://starship.python.net/crew/theller/comtypes/
https://easontseng.blogspot.tw/2017_07_07_archive.html

###########################################################
# pythoncom 是安裝 pywin32 附的,如果 event 沒反應才需要用到
# 第一次使用cc.GetModule, 會在 comtypes\gen\ 下產生幾個.py檔,像是
# _75AAD71C_8F4F_4F1F_9AEE_3D41A8C9BA5E_0_1_0.py
# 如果有 dll 錯誤產生,請檢查 SKCOM.dll 路徑有沒有錯誤
# 如果發生 gen 下沒有 SKCOMLib 錯誤訊息,請將python關閉
# AttributeError: module 'comtypes.gen.SKCOMLib' has no attribute 'SKCenterLib'
# 重新啟動python後,應該就可以找到了
# 如果還是不行,請重新安裝 capital API 元件,注意 API 與python 版本要一致,
# API安裝要以管理員權限執行

# 20190506,程式碼簡化
import pythoncom, time
import comtypes.client as cc

cc.GetModule('C:\\SKCOM\\x86\\SKCOM.dll')
import comtypes.gen.SKCOMLib as sk

ts=sk.SKSTOCK()

skC=cc.CreateObject(sk.SKCenterLib,interface=sk.ISKCenterLib)
skQ=cc.CreateObject(sk.SKQuoteLib,interface=sk.ISKQuoteLib)

#Some Configure
ID='身分證'
PW='密碼'

#想取得報價的股票代碼
strStocks='TSEA'

#define functions
def getStock(nMarket, nIndex, ts):
    skQ.SKQuoteLib_GetStockByIndex(nMarket, nIndex, ts)
    print(ts.bstrStockName, ts.bstrStockNo,  ts.nClose/10**ts.sDecimal)

#建立事件類別
class skQ_events:
    def OnConnection(self, nKind, nCode):
        if nCode == 0 :
            if nKind == 3001 :
                print("skQ OnConnection, nkind= ", nKind)
            elif (nKind == 3003):
                #等到回報3003 確定連線報價伺服器成功後,才登陸要報價的股票
                skQ.SKQuoteLib_RequestStocks(1, strStocks)
                print("skQ OnConnection, request stocks, nkind= ", nKind)
    def OnNotifyQuote(self, sMarketNo, sStockIdx):
        getStock(sMarketNo, sStockIdx, ts)

#Event sink
EventQ=skQ_events()
#make connection to event sink
ConnectionQ = cc.GetEvents(skQ, EventQ)        

#Login
print("Login,", skC.SKCenterLib_GetReturnCodeMessage(skC.SKCenterLib_Login(ID,PW)))
time.sleep(1)

#登錄報價伺服器
print("EnterMonitor,", skC.SKCenterLib_GetReturnCodeMessage(skQ.SKQuoteLib_EnterMonitor()))
#每秒 pump event 一次,這裡示範15秒

for i in range(15):
    time.sleep(1)
    pythoncom.PumpWaitingMessages()

11 則留言:

  1. 謝謝你的分享,可以請教sendfutureorder中要用futuerorder參數要如何下嗎?謝謝

    回覆刪除
  2. 我測成功了,謝謝,不好意思打擾
    fu1 =sk.FUTUREORDER()
    fu1.bstrFullAccount=' '
    fu1.bstrStockNo='TX01'
    fu1.nQty=1
    fu1.sBuySell=0
    fu1.sDayTrade=0
    fu1.sTradeType=0
    fu1.sNewClose=0
    fu1.bstrPrice='10000'
    ncode=skO.SendFutureOrder(Id,False,fu1)

    回覆刪除
  3. 您好!抱歉打擾!
    想請問一下關於以下這行程式碼:
    skC=cc.CreateObject(sk.SKCenterLib,interface=sk.ISKCenterLib)

    其中的sk.ISKCenterLib是什麼意思呢?翻遍了群益的API說明也沒有找到...

    回覆刪除
  4. 我也不是很懂,應該是跟dll運作有關,comtypes 跟 dll 溝通介面,你可能要翻一下微軟COM object運作的原理。我都看不懂,所以無法解釋太多。總之不是群益api的元件

    回覆刪除
  5. 您好,最近再用版大的程式學習,可目前遇到了一個問題。
    在我call pump() function 的時候會回傳錯誤,錯誤為
    Error in sys.excepthook:

    Original exception was:
    這是為什麼呢?

    回覆刪除
    回覆
    1. 第一次看到這個錯誤,你給的訊息太少了,我無法判斷
      如果直接下 pythoncom.PumpWaitingMessages(),這個錯誤還會出現嗎?
      或是你試試看用 jupyter Notebook 的環境,用 %matplotlib auto 的方式來試試看吧
      參考這篇用法 https://easontseng.blogspot.com/2017/11/python-api-tick.html

      刪除
  6. 問題的原因已經找到
    https://github.com/virus-warnning/skcom_examples/issues/6

    回覆刪除
  7. 我就出現下方訊息,只是不會重啟python, 重開機也沒用。
    os:win10x64 python 3.8.8 , pip 安裝comtypes,
    # AttributeError: module 'comtypes.gen.SKCOMLib' has no attribute 'SKCenterLib'
    # 重新啟動python後,應該就可以找到了
    請教各位有沒有解??

    回覆刪除
    回覆
    1. 一定要先
      cc.GetModule('C:\\SKCOM\\x86\\SKCOM.dll')

      import comtypes.gen.SKCOMLib as sk
      順序一定要這樣。不知道你是不是這個問題。

      刪除