當我滿心期待地建立好開發環境,心想:「接下來就是打開群益內建的範例程式碼,大展身手了吧?」
現實是,我想得太天真了。
一打開範例檔案,迎面而來的是各種看不懂的程式碼。我試著查閱 API 文件,卻發現自己陷入了更深的迷霧。這種有看沒有懂的窘境,該如何是好?
沉思許久,心中浮現一個聲音:「各個擊破 (Divide and conquer)」。沒錯,一個完整的交易程式,不外乎是由幾個核心元件組成的:
正是這些基本的功能,組合成了千變萬化的交易策略。所以我決定化繁為簡,從最小、最基本的功能開始逐一擊破。首要任務,就是實現「查詢想要的商品」這個功能,畢竟,能取得資料,才有後續的交易。
好的,目標確立,馬上就遇到了一個問題:不進行登入認證,API 根本不讓我抓取任何資料。
看起來,我的第一個任務並不是查詢商品,而是必須先把「登入」功能給做好!
在研究登入功能時,我發現群益 API 的元件在設計上主要分成兩種類型:
這是我們最常見的模式:帶入參數、呼叫 API、然後 API 回傳成功或失敗的結果。例如,我發出一個請求:「請給我某支股票現在的價格」,API 就會回傳:「現在是 XX 時間,價格是 OO 元」。
但這種模式在某些情境下會有效率問題。如果我需要持續更新價格呢?難道要每秒都瘋狂地發送 Request 來取得最新報價嗎?
為了避免上述的輪詢 (Polling) 問題,就有了第二種元件:Event。簡單來說,這是一個設計用來「監聽」特定事件的元件。你只需要註冊好監聽器,當有新報價、成交回報等事件發生時,API 會「主動通知」你的程式,而不需要你一直去問它。
在我們要實作的登入功能上,就需要同時運用到這兩種設計。整個流程會分成兩個部分:
首先,我們需要撰寫一個函式來觸發「登入」這個動作。這個函式會呼叫 API 的登入方法,並立即回傳一個代碼,告訴我們這個「請求」本身是否成功發送。
def buttonSKCenterLib_Login_Click(self):
"""
處理登入按鈕點擊事件,發送登入請求
"""
# 呼叫登入 API,傳入帳號與密碼
nCode = m_pSKCenter.SKCenterLib_Login(
textBoxUserID.get(),
textBoxPassword.get()
)
# 根據回傳的 nCode 取得對應的訊息
msg = f"【SKCenterLib_Login】{m_pSKCenter.SKCenterLib_GetReturnCodeMessage(nCode)}"
print(msg)
注意: 這裡的 nCode
只代表「登入請求已成功送出」,並不代表「登入成功」。真正的登入結果(成功、失敗、失敗原因)需要透過第二部分的事件監聽來接收。
當我們查閱 API 文件時,會看到兩條關鍵說明:
"登入失敗時可由 log 查詢失敗原因。"
"登入前,需先註冊 4-3-e 公告資訊 SKReplyLib_OnReplyMessage。"
這意味著,我們不能只發送請求,還必須建立一個監聽器來接收來自伺服器的回覆訊息。因此,我們需要宣告一個 API 的事件物件 (SKReplyLibEvent
),這樣在我們發送登入請求後,相關的成功或失敗 Log 訊息,就能透過OnReplyMessage
這個方法持續地被接收。
此方法的參數也需要與文件規範的完全相同。
class SKReplyLibEvent:
"""
處理 API 回覆訊息的事件類別
"""
def OnReplyMessage(self, bstrUserID, bstrMessages):
"""
當接收到伺服器回覆訊息時被觸發
"""
nConfirmCode = -1
msg = f"【註冊公告 OnReplyMessage】使用者:{bstrUserID}, 訊息:{bstrMessages}"
print(msg) # 將收到的訊息顯示出來
return nConfirmCode
溫馨提醒:本次專案有部分內容有使用AI工具