群益API 下單回傳值只回答三個時間點中的第一個示意圖

群益API 下單回傳值是 0 就成功了嗎?一筆委託的 3 個時間點

群益API 下單回傳值是 0,你的程式就在畫面上寫了「下單成功」。過了一會兒,委託查不到;或者回報裡出現一筆退單;或者本地記的部位和帳上對不起來。

問題出在那個 0 被讀錯了意思:它回答的,從來不是你以為的那個問題。 一筆委託送出之後會依序經過三個時間點,回傳值只回答第一個。

群益API 下單回傳值只回答三個時間點中的第一個示意圖

群益API 下單回傳值 0 代表什麼?一筆委託的 3 個時間點

先把一筆委託拆開來看:

時間點它問的問題答案從哪裡來
① 送出這筆委託有沒有被收下?下單函式的回傳值(同步)或 OnAsyncOrder(非同步)
② 委託交易所有沒有接受這筆委託?回報(OnNewData)
③ 成交有沒有成交、成交多少?回報(OnNewData)

群益API 下單回傳值 0,只回答了 ①。 ② 和 ③ 只能看回報。

這不是我們的詮釋。官方在 2.13.58 版本說明的「文件調整」裡,逐字寫著:

調整下單函式文件說明(同步、非同步委託收到回傳值為0時,表示成功送至交易所,交易結果請由回報確認)

「成功送至交易所」和「交易結果」,官方把它們分成兩件事,而且明講後者要看回報。

為什麼會把 0 當成功?官方在 2.13.58 調整了說明

這裡有一個值得知道的背景。在 2.13.57 版的元件說明文件裡,SendFutureOrderCLR 與 SendOptionOrder 對 bstrMessage 的說明是這樣寫的(節錄):

同步委託:如果回傳值為 0表示委託成功,訊息內容則為13碼的委託序號。回傳值非0表示委託失敗,訊息內容為失敗原因。

到了 2.13.58,官方發了上面那條「文件調整」,把回傳 0 的語意改成「成功送至交易所,交易結果請由回報確認」。

如果你手上是舊版文件,你看到的就是「委託成功」四個字——把 0 讀成「下單成功」,是照著當時的說明讀出來的。現在官方已經調整了說明,程式也該跟著調整。

改價、刪單回傳 0,委託就改好、刪掉了嗎?

改刪單這一家族的官方備註講得更直接。三個函式的備註各自的第一句是(節錄):

函式官方備註
CorrectPriceBySeqNo(改價)回傳值0 表示委託伺服器接收成功,詳細委託狀態仍須以委託改價回報內容為主。
DecreaseOrderBySeqNo(減量)回傳值0 表示委託伺服器接收成功,詳細委託狀態仍須以委託減量回報內容為主。
CancelOrderBySeqNo(刪單)回傳值0 表示委託伺服器接收成功,詳細委託狀態仍須以委託刪單回報內容為主。

注意用詞:下單那條寫「送至交易所」,改刪單這三條寫「委託伺服器接收成功」。兩種說法我們都照官方原文保留,但它們指向同一個結論——回傳值告訴你請求被收下了,最後的狀態看回報。

所以「刪單回 0」代表刪單請求被收下了,不代表那筆委託已經被刪掉。刪單請求送出去需要時間,如果那筆委託在刪單生效之前就成交了,就會以成交收場。這是從「詳細委託狀態仍須以委託刪單回報內容為主」這句推出來的:刪單有沒有生效,要看回報。

群益API 下單回傳值不是 0 時,錯誤從哪裡來?

非 0 也不是只有一種。官方把非 0 分成兩類:4 碼的錯誤代碼查官方錯誤代碼定義表,其他是交易主機回傳的錯誤。

  • 4 碼的錯誤代碼:查官方「下單準備介紹」裡的錯誤代碼定義表。〈群益API 下單初始化有哪 7 步〉提過的 1038(憑證尚未驗章)就屬於這一類,1040(SK_ERROR_ORDER_LOCK)也是。
  • 其他錯誤:由交易主機回傳錯誤代碼與錯誤原因。

不管是哪一類,同步委託失敗時,bstrMessage 裡放的就是失敗原因——這在前面引的 2.13.57 說明裡寫得很清楚(「訊息內容為失敗原因」)。

所以非 0 的時候,把 bstrMessage 的原文記下來、顯示出來,不要只顯示一個數字。 一個數字能告訴你「失敗了」,原文才能告訴你「為什麼」。

同步和非同步下單,回傳 0 之後拿到的東西有什麼不同?

下單函式的第二個參數 bAsyncOrder 決定走哪一種模式。兩者回傳 0 之後,你手上拿到的東西不一樣:

模式回傳 0 時的 bstrMessage收單結果從哪裡來
同步(false)13 碼委託序號回傳值本身
非同步(true)官方說明為「參照OnAsyncOrder」OnAsyncOrder 事件

非同步的收單結果由 OnAsyncOrder 事件帶回。它的官方宣告只有三個參數,C# 範例寫成:

void OnAsyncOrder(int nThreadID, int nCode, string bstrMessage)

官方備註的第一列是(節錄):

送單函式中使用非同步下單時會取得一個Thread ID,當此事件觸發時可藉由nThreadID對應下單來源。 委託成功:收單回傳訊息為 委託序號 委託失敗:收單回傳訊息為 委託失敗原因

也就是說,非同步下單的委託序號,要等 OnAsyncOrder 觸發時從它的 bstrMessage 拿,再用 nThreadID 對回是哪一筆下單。所以送出的時候,就要把「這是哪一筆委託」和它的 Thread ID 記在一起,事件回來才對得上。

非同步多了一層事件,但終點沒有變。 OnAsyncOrder 的 nCode 是 0,一樣只回答了 ①「收下了」——它是非同步版本的收單結果,跟同步下單的回傳值是同一層。不要把 OnAsyncOrder 當成回報。 委託成立、成交與否,還是看 OnNewData。

OnAsyncOrder 分得出是股票還是期貨嗎?

從宣告就看得出來:三個參數裡沒有市場別。

我們在實作上確認過,股票和期貨的非同步收單結果,走的是同一個 OnAsyncOrder 事件(這是實務經驗,官方文件沒有這樣寫)。如果你同時送多個市場的委託,就只能靠你自己記下的那份對應來分辨。

IOC 單回傳 0 之後又被退,是程式寫錯了嗎?

不是。IOC 這個委託條件,臺灣期貨交易所的正式名稱是「立即成交否則取消」——名稱本身就是規則:送出當下能成交的才成交,不能立即成交的就取消。

所以 IOC 單回傳 0、之後在回報裡看到被取消,正是三個時間點最具體的例子:

  • ① 收下了——回傳值 0
  • ②③ 沒能立即成交、被取消——回報告訴你的

這是規則的結果,不是程式或設定錯誤。 從實務經驗來說,要特別小心的是:程式不要把「被退」一律當成錯誤處理。如果程式看到退單就判定出錯、自動停止,那它是把一個正常的交易結果當成了故障。

群益API 下單回傳值該怎麼處理?5 條寫法紀律+程式碼

把前面整理成程式的寫法:

  1. 把回傳值當成「收單結果」,不是「交易結果」。 回傳 0 只把委託推進到「已送出」,不要在這一步更新部位或顯示「成交」。
  2. 非 0 時保存 bstrMessage 原文,同時看錯誤碼是不是 4 碼:是,就查錯誤代碼定義表;不是,就是交易主機回傳的錯誤。
  3. 用非同步時,送出當下就記下 Thread ID 與這筆委託的對應,在 OnAsyncOrder 用 nThreadID 配對。
  4. 委託是否成立、是否成交,一律以 OnNewData 回報為準;部位只由回報更新。回報的欄位怎麼讀,見〈群益API 委託回報怎麼解析〉。
  5. 改價、刪單同樣以回報為準。 刪單回 0 之後,那筆委託仍可能以成交收場。
// 回傳 0 只代表委託被收下,不代表委託成立或成交
string loginId = "YOUR_ID";
string bstrMessage;
int nCode = m_pSKOrder.SendFutureOrderCLR(loginId, bAsyncOrder, ref pOrder, out bstrMessage);

if (nCode != 0)
{
    // 失敗原因在 bstrMessage,不要只顯示數字
    ShowError(nCode, bstrMessage);
    return;
}

if (!bAsyncOrder)
    MarkAsSent(bstrMessage);        // 同步:bstrMessage 是 13 碼委託序號,狀態只到「已送出」

// 非同步:收單結果由 OnAsyncOrder 帶回,用 nThreadID 對應是哪一筆
void OnAsyncOrder(int nThreadID, int nCode, string bstrMessage) { /* 仍只是收單結果 */ }

// 委託是否成立、是否成交,只看回報
void OnNewData(string bstrUserID, string bstrData) { /* 在這裡更新委託狀態與部位 */ }

注意參數的傳遞方式:pOrder 用 ref、bstrMessage 用 out,這是官方 C# 範例的寫法,不要改成值傳遞。

還有一個前提沿用 F1:回報通道要先就緒。OnComplete 到了才開放送單,否則第 4 條「以回報為準」會沒有東西可看。細節見〈群益API 下單初始化有哪 7 步〉。

回傳值要一個函式一個函式查:四篇整理成一張判讀表

如果你讀過這個系列的其他幾篇,會發現「回傳值不代表你以為的那件事」已經出現好幾次了:

篇函式讀者以為實際上
〈登入錯誤判讀〉SKCenterLib_Login非 0 就是失敗600~699 是未使用雙因子的登入成功——非 0 不一定是失敗
〈訂閱額度〉SKQuoteLib_RequestStocks沒回錯誤就是全部訂上了依官方說明:超過 100 檔則僅以 100 檔處理、代號不存在直接略過,兩者都不回傳錯誤
〈下單初始化〉SKReplyLib_ConnectByID回 0 就是回報通道就緒回 0 只代表連線請求送出去了,要等 OnComplete(實作歸納,官方文件沒有明文)
本篇SendFutureOrderCLR 等下單函式回 0 就是成交回 0 只是收單,交易結果看回報

第一列是反方向的例子,而且它很重要:如果只看後三列,很容易得出「0 都不可信」的結論——那同樣是錯的。

這張表的共同點不是「0 不可信」,是「回傳值的意思要一個函式一個函式查」。 把「0=成功」當成通則,才是這幾篇所有問題的共同來源。

常見問題

群益API 下單回傳值是 0,是不是代表成交了?

不是。依官方 2.13.58 的說明,回傳 0 表示成功送至交易所,交易結果請由回報確認。委託是否成立、是否成交,都要看 OnNewData 回報。

刪單回傳 0,是不是代表委託已經刪掉了?

不是。官方備註寫的是「委託伺服器接收成功,詳細委託狀態仍須以委託刪單回報內容為主」。回 0 代表刪單請求被收下,那筆委託仍可能在刪單生效前成交,最終狀態看回報。

非同步下單的 OnAsyncOrder 就是回報嗎?

不是。OnAsyncOrder 是非同步版本的收單結果,跟同步下單的回傳值是同一層。它的 nCode 為 0 也只代表委託被收下,委託與成交仍然看 OnNewData。

非同步下單時,委託序號要去哪裡拿?

從 OnAsyncOrder 拿。依官方備註,收單成功時,OnAsyncOrder 的 bstrMessage 是委託序號,失敗時是失敗原因;事件觸發時用 nThreadID 對應是哪一筆下單。

風險揭露

期貨與選擇權屬高槓桿商品,價格波動可能造成超過原始保證金的損失,交易人須自負交易責任。本文為程式開發技術教學,說明下單函式回傳值與回報的判讀方式,不構成投資建議,也不保證任何交易結果。程式化交易並不降低市場風險,反而可能因程式錯誤造成非預期的委託行為——把回傳 0 當成成交而更新部位、或把刪單回 0 當成委託已刪除,都可能讓程式在錯誤的部位認知下繼續下單。

投資人教育資源

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

延伸閱讀

參考資料

  • 下單函式回傳 0 的語意,依群益官方 2.13.58 版本說明「文件調整」一節。
  • SendFutureOrderCLR/SendOptionOrder 的 bstrMessage 說明與回傳值說明、CorrectPriceBySeqNo/DecreaseOrderBySeqNo/CancelOrderBySeqNo 備註、OnAsyncOrder 宣告與備註,依群益官方元件說明文件 2.13.57 版的下單章節;OnNewData 宣告依回報章節。
  • IOC 委託條件名稱「立即成交否則取消」,依臺灣期貨交易所〈交易制度-委託單種及撮合原則〉。
  • OnAsyncOrder 股票與期貨共用同一事件、IOC 退單不應視為程式錯誤:實作與實盤經驗,非官方文件記載。

免責聲明

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

延伸閱讀|相關文章

發佈留言

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