群益API Python 回傳值:[in,out]、[out] 參數與 comtypes 的回傳規則

群益API Python 回傳值為什麼是 list?[in,out]、[out] 參數與 comtypes 的回傳規則

回傳值印出來是 [1, 0] 這種 list,拿去跟 0 比,永遠不相等。官方宣告明明有三個參數,OnReplyMessage 的 Python 方法卻只收兩個、還要 return -1。對照官方文件的宣告,也看不出 Python 到底要傳幾個參數。

群益API Python 回傳值的規則可以用一句話講完:看每個參數的方向。[in] 要傳;[out] 不用傳,但會出現在回傳值;[in,out] 要傳,也會回來。回傳多個值時,直接拆成多個變數。

本文的實測環境是 SKCOM 2.13.59 x64、Python 3.12、comtypes 1.4.16,在未登入的狀態下進行。

群益API Python 回傳值示意圖:依參數方向決定要不要傳、會不會回來

群益API Python 怎麼看參數方向?

官方元件說明文件的宣告裡,每個參數前面都標了方向。comtypes 照這個方向決定 Python 的呼叫方式與回傳值:

方向呼叫時要傳嗎會出現在回傳值嗎例子
[in]要不會RequestStocks 的 bstrStockNos
[out]不用會回傳碼;SendFutureOrderCLR 的 bstrMessage
[in,out]要會RequestStocks 的 psPageNo;GetStockByIndexLONG 的 pSKStock

回傳值的組成:

  • 只有一個要回來的值(只有回傳碼):直接回那個值,例如 RequestStockList 回傳一個整數。
  • 兩個以上:回傳一組值,順序跟宣告裡的參數順序一樣,回傳碼在最後一個。

群益API Python 回傳值為什麼是 list,不是 tuple?

我們的實測(未登入,所以回傳碼都是 1000,也就是 SK_ERROR_LOGIN_FIRST):

呼叫回傳
quote.SKQuoteLib_RequestStocks(1, "TX00")[1, 1000](list)
quote.SKQuoteLib_RequestTicks(0, "TX00")[0, 1000](list)
quote.SKQuoteLib_GetStockByNoLONG("TX00", sk.SKSTOCKLONG())[SKSTOCKLONG, 1000](list)
quote.SKQuoteLib_GetStockByIndexLONG(2, 0, sk.SKSTOCKLONG())[SKSTOCKLONG, 1000](list)
quote.SKQuoteLib_RequestStockList(2)1000(int)

規則是:方法有 [in,out] 參數時,comtypes 回傳 list。 只有 [out] 參數的函式(例如下單的 SendFutureOrderCLR)回傳的是 tuple;這一點我們沒有實際呼叫下單函式驗證。

還有一個地方容易混淆:comtypes 產生的模組裡,型別提示寫的是 tuple。編輯器可能顯示 tuple,實際執行回傳的是 list,以實際執行為準。

所以,不需要記哪個是 list、哪個是 tuple,直接拆包就好,兩種都適用:

page_no, code = quote.SKQuoteLib_RequestStocks(1, "TX00")

不要用 isinstance(r, tuple) 判斷。 有 [in,out] 參數的方法回傳的是 list,這個判斷會失敗,結果整個 list 被當成回傳碼,後面的判斷全部出錯。本系列〈群益API Python 入門〉的範例早期曾用這種寫法,已更正。

[in,out] 要傳值:psPageNo 的例子

官方對 RequestStocks 的宣告是:

Long SKQuoteLib_RequestStocks([in,out] SHORT* psPageNo, [in] BSTR bstrStockNos);

comtypes 產生的模組裡,psPageNo 的方向也是 in、out 兩者都有,跟官方宣告一致。所以第一個參數就是頁號,要傳:

page_no, code = quote.SKQuoteLib_RequestStocks(1, "TX00")

少傳頁號會怎樣?我們實測 RequestStocks("TX00"),會拋出 TypeError: 'str' object cannot be interpreted as an integer:comtypes 把 "TX00" 當成第一個位置的頁號,但它是字串,型別不符。

參數名稱以官方手冊為準;comtypes 產生的模組裡,有些參數名稱跟手冊不同,但位置與方向一致。

結構類的 [in,out] 可以省略

我們實測 GetStockByNoLONG 與 GetStockByIndexLONG 這兩個函式,不傳結構也可以呼叫,comtypes 會自動補一個空的結構:

stock, code = quote.SKQuoteLib_GetStockByNoLONG("TX00")   # 不傳結構也可以

傳一個新建的結構進去也可以,例如 sk.SKSTOCKLONG()。其他函式我們沒有逐一測過。

數值類的 [in,out](例如 psPageNo)不能省略:它在前面的位置,省了後面的參數就錯位。

純 [out] 不用傳:函式從回傳值拿,事件用 return 給

這是最值得對照的一組:

函式的 [out],從回傳值拿。 SendFutureOrderCLR 的宣告是:

Long SendFutureOrderCLR([in] BSTR bstrLogInID, [in] VARIANT_BOOL bAsyncOrder, [in] struct FUTUREORDER* pAsyncOrder,[out] BSTR* bstrMessage);

Python 只傳前三個參數,bstrMessage 跟回傳碼一起回來:message, code = ...。訊息的判讀見〈群益API 下單回傳 980 怎麼讀〉。

事件的 [out],用 return 給。 OnReplyMessage 的宣告是:

void OnReplyMessage([in] BSTR bstrUserID , [in] BSTR bstrMessage,[out]SHORT* sConfirmCode);

事件是元件呼叫你的程式,[out] 是你要交回去的值。所以 Python 的事件方法只收兩個 [in] 參數,用 return -1 交回 sConfirmCode,見〈群益API Python 入門〉的步驟 4。

怎麼查某個函式的參數方向?

有兩個地方可以查:

  1. 官方元件說明文件的宣告:每個參數都標了 [in]、[out] 或 [in,out]。
  2. comtypes 產生的模組:GetModule 之後,用 import comtypes.gen.SKCOMLib as sk; print(sk.__file__) 找到所在的資料夾。SKCOMLib.py 只是轉介,真正的定義在同一個資料夾、以一串編號命名的那個檔案裡,每個方法都列了參數方向(['in']、['out']、['in', 'out'])。

第二種是元件型別的實際內容,跟〈群益API Python 環境檢查〉講的「以元件型別為準」是同一個原則。

群益API Python 回傳值判讀程式碼

下面的片段示範三種情況,未登入也能跑,回傳的形態一樣:

# 群益API Python 回傳值:依參數方向決定怎麼呼叫、怎麼接
# 前提:GetModule、CreateObject 完成;未登入也能看到回傳的形態
import comtypes.gen.SKCOMLib as sk

# 1. 只有回傳碼([in] 參數 + 回傳碼)→ 直接回一個整數
code = quote.SKQuoteLib_RequestStockList(2)
print(type(code).__name__, code)

# 2. 有 [in,out] 的數值參數(psPageNo)→ 要傳,會和回傳碼一起回來
page_no, code = quote.SKQuoteLib_RequestStocks(1, "TX00")
print(page_no, code)

# 3. 有 [in,out] 的結構參數 → 傳一個新建的結構,結構和回傳碼一起回來
stock, code = quote.SKQuoteLib_GetStockByNoLONG("TX00", sk.SKSTOCKLONG())
print(type(stock).__name__, code)

# 錯誤示範:判斷 tuple 會失敗,因為上面兩種回的是 list
result = quote.SKQuoteLib_RequestStocks(1, "TX00")
print(type(result).__name__)          # list

未登入時的輸出(1000 是 SK_ERROR_LOGIN_FIRST):

int 1000
1 1000
SKSTOCKLONG 1000
list

第 3 段只印結構的型別名稱、不印欄位:未登入時結構裡沒有內容。

群益API Python 回傳值的 4 個誤解

  1. 誤解: comtypes 回傳多個值,一定是 tuple。其實: 有 [in,out] 參數的方法回傳 list(我們在 comtypes 1.4.16 實測);直接拆包兩種都適用。
  2. 誤解: psPageNo 是輸出參數,不用傳。其實: 官方宣告是 [in,out],要傳值,也會回來。
  3. 誤解: 官方宣告有幾個參數,Python 就傳幾個。其實: [out] 參數不用傳,它會出現在回傳值裡。
  4. 誤解: OnReplyMessage 的 Python 方法要收三個參數。其實: 事件的 [out] 參數由你用 return 交回,方法只收兩個 [in] 參數。

常見問題

群益API Python 的回傳值印出來是 [1, 0],回傳碼是哪一個?

最後一個。有 [in,out] 參數的方法,comtypes 會把參數和回傳碼一起放進 list 回傳,回傳碼在最後;直接寫 page_no, code = … 拆開來用。

為什麼不能用 isinstance(r, tuple) 判斷回傳值?

因為有 [in,out] 參數的方法回傳的是 list,不是 tuple,判斷會失敗。直接拆包對 list 和 tuple 都適用。

RequestStocks 少傳頁號會怎樣?

我們實測會拋出 TypeError: ‘str’ object cannot be interpreted as an integer。官方宣告的第一個參數 psPageNo 是 [in,out],要傳值。

OnReplyMessage 為什麼只收兩個參數、還要 return -1?

第三個參數 sConfirmCode 是 [out]。事件的 [out] 是你要交回給元件的值,在 Python 裡用 return 交回;官方說明要回傳 -1。

風險揭露

期貨與選擇權屬高槓桿商品,價格波動可能造成超過原始保證金的損失,交易人須自負交易責任。本文為程式開發技術教學,說明 Python 呼叫群益API 時參數與回傳值的處理方式,不構成投資建議,也不保證任何交易結果。程式化交易並不降低市場風險,回傳碼判讀錯誤可能讓程式誤判委託或訂閱的狀態,正式使用前請充分測試。

投資人教育資源

機構資源
臺灣期貨交易所(TAIFEX)期貨及選擇權數位學習網
證券暨期貨市場發展基金會證券期貨市場教育推廣
金融智慧網金管會金融知識平台
中華民國期貨業商業同業公會期貨業法規與宣導
證券投資人及期貨交易人保護中心投資人保護與申訴

延伸閱讀

參考資料

  • SKQuoteLib_RequestStocks、SKQuoteLib_GetStockByIndexLONG、SendFutureOrderCLR、OnReplyMessage、SKQuoteLib_RequestStockList 的宣告,依群益官方元件說明文件。
  • comtypes – PyPI
  • 回傳形態(list、int)、少傳頁號的錯誤訊息、結構可省略:我們 2026-10-16 在 comtypes 1.4.16、未登入狀態的實測,非官方文件記載;其他 comtypes 版本沒有測過。
  • 只有 [out] 的函式回傳 tuple:依 Python 底層的行為,我們沒有實際呼叫下單函式驗證。

免責聲明

本文章僅作為群益API實作經驗分享,不構成投資建議,且策略及程式皆應自行撰寫。期貨及衍生性金融商品交易屬高風險投資,請謹慎評估自身風險承擔能力。

延伸閱讀|相關文章

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *