群益API行情串接(五)

像股票這樣的金融商品百百種,加上市場的變化性與多樣的市場規則,使得這類的分析總是相當困難。但相關數據取得與蒐集的管道也相當稀少,甚至難以整合與上手。國內幾家券商提供之API服務便顯得相當地重要。

Jerome Lin
Coding Learning Sharing
11 min readMar 31, 2021

--

前言

唉~時間過得很快阿。平常總是抽不出時間把自己所見、所聞、所學,進行整理,更新到部落格上。今日收到一則簡訊,猛然一驚,群益API必須得要更版啦~_~。

我們廢話不多說,趕緊上工。

本篇將不會特別詳細介紹元件註冊,我們注重在群益API換版

程式環境

程式語言: Python 3.6.8 x86

作業系統: Windows 10 64位元

API版本: 2.13.16 x86版本 to 2.13.28 x86版本

解除元件

想要解除元件非常簡單,我們以系統管理員權限執行Uninstall.bat檔。如下圖所示:

看到以下訊息,代表你已經成功解除元件嚕~。

什麼?你還不放心?執行平常在使用的程式碼看看就知道嚕~。

只要你能看到像上圖這樣的報錯,就非常值得開心,你已經成功跨出一大步了。很明顯,出錯並不總是壞的,我們得學會與其共處。

重新註冊新元件

接著,我們從官方網站上下載最新的元件,以目前來說就是2.13.28版本,我習慣依版本分開存放,各位也可以直接刪除舊版元件檔案並取代之,如下圖所示:

我們觀察其結構基本上沒有變,那就很好辦了,我們依照先前的註冊方式,重新進行註冊,記得選擇x86版本,如下圖所示:

註冊同樣需要系統管理員權限,不要忘記了,成功訊息如下圖所示:

不放心的話,可以使用同目錄底下的SKCOMTester.exe執行檔進行登入確認。

回到Python主程式

既然,該解除的元件已解除,並且我們也重新進行註冊了,那是不是可以跑了呢~,你可以試試看阿。

事實上,從2.13.17版本開始,就強制在進行登入時,也要註冊回報(Reply)事件,也就是公告的部分,因此,如果我們現在直接執行,會發生如下情況:

下圖是2.13.17版本的出錯:

而下圖是2.13.28版本的出錯:

我們可以發現錯誤訊息稍微不一樣,到底改了哪些東西呢?這倒是不那麼中要,我們知道我們必須先註冊公告

不過,令我疑惑的倒是,官方文件提到2.13.16版本就已經需要此步驟,才能登入,但我至今天為止仍然用得好好地。

還記得先前有寫了一個初始化API的函式嗎?

我們要進行SKReplyLib物件的添加,:

其中,我們同樣使用comtypes.client.CreateObject()函式來建立物件,並且capital_api_init()函式會額外回傳出這個物件。

而為了方便區分不同功能,我們另外為這個事件建立一個Class,這個Class中,我們會需要有一個OnReplyMessage()的函式:

根據官方文件,我們可以知道OnReplyMessage()函式有一個回傳值,型態為short int,當其為VARIANT_TRUE時,我們才算正常開通功能。

那到底VARIANT_TRUE是什麼呢?

VARIANT_BOOL這種型態,很明顯就是一個布林型態,但是給COM元件所使用的,實際上會是short的型態。

VARIANT_TRUE其值會是什麼呢?我們可以透過以下文件查詢得知:

我們可以知道VARIANT_TRUE相當於0xFFFF,而VARIANT_FALSE相當於0x0000VARIANT_FALSE的部分我想不需要解說,就是整數0。但VARIANT_TRUE的整數是什麼呢?由於我們得轉換為short,是屬於signed整數,我們可以用二補數進行轉換,首先需要先轉為二進制:

因此,我們就能得知VARIANT_TRUE值相當於-1

這就是在OnReplyMessage()函式中,為何要回傳-1的原因。

接下來,我們需要註冊事件,透過comtypes.client.GetEvents()函式去進行綁定:

好啦~~~,我們是跑看看吧,迫不及待了對不對。執行結果如下圖所示:

怎麼出錯了啊…

因為我們得要在登入之前,進行Reply事件的綁定呀~

所以我們修改一下上面的程式碼:

現在執行看看吧~嘿嘿:

又出錯啦~~,全都照著步驟做了,怎麼會這樣呢?

這是因為我們先前介紹到使用comtypes時,有提到的一個重點。

由於comtypes.client.GetModule()函式會對指定的COM檔案,參考裡面所涵蓋的type library,進一步轉為一組Python module,基本上會放置於path\to\Lib\site-packages\comtypes\gen目錄底下。

我們可以在執行的時候,用debug功能進行中斷,查看當前使用到的元件是哪個版本的。如下圖所示(為何<api_path>變數是2.13.25版本的目錄呢?因為這張圖片我先前早就先擷取好了,只是苦無時間繼續往下編輯):

找出源頭之後,我們回過頭去找到目標檔案,果然發現還是取用到舊版的元件:

整個目錄結構如下面兩張圖所示:

這些檔案是我們在第一次執行時,會另存的一個暫存檔,會這樣做的好處是第二次(含)之後的執行,都不需要另外進行轉換的動作。

所以我們仔細看,主目錄裡面還有一個子目錄__pycache__,裡面便會存放Python在第一次執行主程式後,把相關依賴的函式庫或模組轉為bytecode進行儲存,以.pyc為副檔名的檔案存在。之所以會這樣做,也是為了讓Python這類的Interpreted Language可以在第二次與之後的執行更快速(簡單來說,就是不用再轉換一次bytecode的動作)。

所以只要COM元件指向不變,更版的動作並不會重新刷新這些暫存檔,往後我們又會去使用到這些舊的暫存code去執行,這顯然不行啊,我們需要把這些全部移除,並重新執行我們的python主程式,讓其自動產生一個新的暫存檔

成功執行就會如下圖:

功能都與先前一樣,看起來也沒有什麼問題,我們並不需要另外再修改什麼地方。(不過,倒是聽說新版在獲取資料時,可能會漏資料,這個問題目前就聽天由命吧)

結論

其實更新版本應該是一件非常簡單的事情,但由於我們是自行串接,透過一些程式語言與套件進行開發,若對我們自己所使用的東西不那麼了解,那我們很可能會遇到所謂的邏輯錯誤

無論如何,本篇完整介紹了一個在使用Python開發,並使用comtypes套件時,該如何進行群益API的版本更新。中間我們也詳細解析了會遇到的問題,並去解決它。

--

--

Jerome Lin
Coding Learning Sharing

覺得平凡就好,但還是多少充實一下人生。It feels good to be ordinary, but you still need to enrich your life a little bit. Buy Me A Coffee: https://www.buymeacoffee.com/jeromelinil