群益API 委託回報怎麼解析?OnNewData 欄位的 5 個判讀重點
判斷買賣方向時,拿回報裡的 BuySell 欄跟 "B" 比,永遠比不到。把每一筆回報的數量加起來當成交量,結果比實際多。
群益API 委託回報是一串逗號分隔的欄位,而同一個欄位,在不同回報裡的意思不一樣。 光知道欄位在第幾個位置,還讀不懂一筆回報。
本文只談「讀懂一筆回報」。怎麼用回報去更新自己的掛單簿、怎麼對帳,見〈群益API 委託回報怎麼對帳〉。

目錄
群益API 委託回報長什麼樣?一串逗號分隔的欄位
委託回報由 OnNewData(string bstrUserID, string bstrData) 事件送來。官方對 bstrData 的說明是「每一筆資料以「,」分隔每一個欄位」,欄位依固定順序排列,用索引取值。
下面是本文會用到的重點欄位。索引依官方欄位表的順序,從 0 起算:
| 索引 | 欄位 | 說明 |
|---|---|---|
| 0 | KeyNo | 原始 13 碼委託序號(國內期選成交單沒有,見下文) |
| 1 | MarketType | 市場別,例如 TF 期貨、TO 選擇權 |
| 2 | Type | 這筆是什麼回報 |
| 3 | OrderErr | Y 失敗、T 逾時、N 正常 |
| 6 | BuySell | 複合欄位,要逐字元讀 |
| 8 | ComId | 商品代碼 |
| 11 | Price | 價格,意思隨 Type 改變 |
| 20 | Qty | 數量,意思隨 Type 改變 |
| 23 | Date | 交易日期 |
| 24 | Time | 交易時間,含冒號的字串(例 01:02:03) |
| 38 | ExecutionNo | 成交序號 |
| 44 | ErrorMsg | OrderErr 為 Y 時的委託單錯誤訊息 |
| 47 | SeqNo | 13 碼序號 |
| 49 | Timefff | 國內期選的下單時間到毫秒(V2.13.59 新增) |
完整的欄位表請見官方元件說明文件。
注意第 24 欄 Time:它是含冒號的字串,跟報價那邊的整數時間編碼不同(見〈群益API 報價價格為什麼是整數〉),解析方式要分開寫。
先看 Type:這筆是什麼回報?
讀一筆回報,第一步是看第 2 欄 Type。官方的定義是:
N:委託 C:取消 U:改量 P:改價D:成交 B:改價改量S:動態退單
再看第 3 欄 OrderErr:Y 是失敗、T 是逾時、N 是正常。OrderErr 為 Y 時,第 44 欄 ErrorMsg 是委託單錯誤訊息。
還要知道一件事:一筆委託會產生好幾筆回報。 官方備註舉的例子是(節錄):
被「動態退單」的委託,會收到委託回報、取消回報與動態退單回報,若有成交部位還會有成交回報。
群益API 委託回報的數量為什麼不能直接加總?
因為同一個欄位,意思會隨 Type 改變。官方欄位表是這樣寫的:
| 欄位 | Type = N(委託) | Type = D(成交) | Type = U(改量) | Type = C(取消) |
|---|---|---|---|---|
Price(第 11 欄) | 委託價 | 成交價 | — | — |
Qty(第 20 欄) | 委託量 | 成交量 | 減量數 | 原委託剩量 |
把每一筆的 Qty 加總當成交量,會把改量的「減量數」和取消的「原委託剩量」也算進去。 成交量只能累加 Type = D 的 Qty。
累加成交量時,還有一件事要注意:〈群益API 下單初始化有哪 7 步〉講過,回報連線之後會先回補,OnComplete 到了才表示回補完成。回補送來的舊成交回報,Type 也是 D。 累加之前要把這一點考慮進去;同一筆成交怎麼去重,見〈群益API 委託回報怎麼對帳〉。
另外,官方對 Price 的說明是「價格,代表已經處理的價格」——回報裡的價格已經處理過小數,不需要像報價那樣除以 10 的 sDecimal 次方。複式單成交時,第 14 欄 Price1 是第一腳成交價、第 17 欄 Price2 是第二腳成交價。
BuySell 為什麼跟 “B” 比不到?要逐字元讀
因為官方把 BuySell 定義成複合欄位,每一個字元的位置代表不同的意思,而且不同市場別的定義也不一樣。國內期貨、選擇權的定義是:
| 位置 | 意思 |
|---|---|
[0] | B: 買 S: 賣 |
[1] | Y: 當沖 N: 新倉 O: 平倉 7: 代沖銷 |
[2] | I: IOC R: ROD F: FOK |
[3] | 1: 市價 2: 限價 3: 範圍市價 4: 停損限價 5: 收市 |
[4] | N/A |
所以整欄跟 "B" 比對永遠不會相等。判斷買賣只取第 0 個字元。
證券、海期海選、複委託的 BuySell 每一位意思都不一樣,要依第 1 欄 MarketType 查官方表。這跟〈群益API 下單價格為什麼是字串〉講的 M 與時效代碼是同一個教訓:特殊值的意思要逐個查。
官方另有一個註記:刪單失敗單(例如預約單已被取消又再刪單)的 [0] 會顯示 0,不是 B 或 S。這條註記在官方表裡列在證券那一段。
國內期選的成交為什麼對不上原始委託序號?
因為國內期選的成交回報沒有這一欄。官方對第 0 欄 KeyNo 的說明是(節錄):
國內期選、海外市場:成交單無此欄 可使用新增的SeqNo 比對
所以用第 0 欄追國內期選的成交,會對不上。要用第 47 欄 SeqNo,官方說明是「13碼序號(成交單含IOC/FOK產生取消單)」。SeqNo 怎麼跟委託配對,見〈群益API 委託回報怎麼對帳〉。
其他幾個欄位也不是每筆都有:BeforeQty、AfterQty 僅提供證券、複委託市場;TradeDate 僅提供海外委託;PreOrder 與 Reserved(盤別)僅國內期、選委託。
欄位數為什麼不能寫死?
V2.13.59 在欄位表最尾端新增了 Timefff(國內期選的下單時間到毫秒),而官方對這個欄位的註記是(節錄):
預約單跟錯誤回報無提供
也就是說,同一個事件,不同回報型態的欄位數不一樣,換版也會增加。 前面所有欄位的位置沒有變。
用固定索引取前面的欄位;不要檢查「欄位數必須等於 N」,也不要用「取最後一欄」的方式取值。 索引超出範圍時,當成空字串處理。
先看第 0 欄是不是 980
官方範例程式會先判斷第 0 欄是否為 980,範例的註解寫「980(後台問題)」;是的話,整筆原樣顯示,不照欄位表解析。
在官方文件裡,980 只出現在這類事件資料字串的開頭,下單函式的回傳值說明裡沒有它。解析前先判斷第 0 欄;是 980 時整筆記錄下來,不要套欄位表。
群益API 委託回報的 7 條解析原則+程式碼
- 按索引解析,所有欄位走同一個解析入口,不要在程式各處各自寫索引。
- 先判斷第 0 欄是不是
980。 - 先看
Type,再讀其他欄位;OrderErr為Y時看ErrorMsg。 - 成交量只累加
Type = D的Qty,並注意回報回補送來的舊成交。 - 買賣方向只取
BuySell的第 0 個字元;其他位置依市場別查官方表。 - 國內期選的成交用
SeqNo比對,不要用KeyNo。 - 不要檢查欄位數等於 N;索引超出範圍當空字串。
void OnNewData(string bstrUserID, string bstrData)
{
string[] v = bstrData.Split(',');
if (v[0] == "980") { LogRaw(bstrData); return; } // 官方範例:980 開頭不套欄位表
string F(int i) => i < v.Length ? v[i] : ""; // 欄位數不寫死:超出範圍當空字串
string type = F(2); // N 委託 C 取消 U 改量 P 改價 D 成交 B 改價改量 S 動態退單
string orderErr = F(3); // Y 失敗 T 逾時 N 正常
char side = F(6).Length > 0 ? F(6)[0] : ' '; // BuySell 是複合欄位,買賣只看第 0 個字元
string qty = F(20); // 意思隨 Type 改變
string seqNo = F(47); // 國內期選成交用這個比對
if (orderErr == "Y") { ShowError(F(44)); return; } // ErrorMsg
if (type == "D") AddFilledQty(side, qty); // 成交量只累加成交回報(注意回報回補)
}幾點補充:
string F(int i) => ...用的是 C# 7 的區域函式,改寫成一般方法意思也一樣。- 解析本身很輕量,但之後要更新畫面或狀態時,照〈群益API 事件回呼跑在哪個執行緒〉的紀律,回呼裡只做收集。
常見問題
群益API 委託回報怎麼判斷買還是賣?
取 BuySell(第 6 欄)的第 0 個字元。官方把這一欄定義成複合欄位,國內期選的第 0 位是 B 買、S 賣,其他位置分別是新平倉、時效、價格類型,所以整欄跟 “B” 比對不會相等。
成交量要怎麼算?
只累加 Type = D(成交)的 Qty。依官方欄位表,Qty 在改量時是減量數、在取消時是原委託剩量。另外要注意,回報連線後回補送來的舊成交,Type 也是 D。
國內期選的成交回報要用哪一個序號比對?
用第 47 欄 SeqNo。官方寫明國內期選的成交單沒有第 0 欄 KeyNo,可使用 SeqNo 比對。
回報的欄位數為什麼跟文件不一樣?
不同回報型態的欄位數不同,換版也會增加。例如 V2.13.59 新增的 Timefff,官方註記預約單跟錯誤回報不提供。用固定索引取值,不要檢查欄位數。
風險揭露
期貨與選擇權屬高槓桿商品,價格波動可能造成超過原始保證金的損失,交易人須自負交易責任。本文為程式開發技術教學,說明委託回報欄位的判讀方式,不構成投資建議,也不保證任何交易結果。程式化交易並不降低市場風險,回報解析錯誤——例如把取消的剩量算成成交、或把買賣方向判斷錯——都可能讓程式對自己的部位產生錯誤認知並繼續下單。
投資人教育資源
| 機構 | 資源 |
|---|---|
| 臺灣期貨交易所(TAIFEX) | 期貨及選擇權數位學習網 |
| 證券暨期貨市場發展基金會 | 證券期貨市場教育推廣 |
| 金融智慧網 | 金管會金融知識平台 |
| 中華民國期貨業商業同業公會 | 期貨業法規與宣導 |
| 證券投資人及期貨交易人保護中心 | 投資人保護與申訴 |
延伸閱讀
- 〈群益API 下單回傳值是 0 就成功了嗎〉——回傳 0 之後,委託與成交要看回報。
- 〈群益API 下單初始化有哪 7 步〉——回報通道要等
OnComplete,以及回報回補。 - 〈群益API 報價價格為什麼是整數〉——報價的整數價格與時間編碼,跟回報不同。
- 〈群益API 下單價格為什麼是字串〉——特殊值的意思要逐個物件查。
參考資料
OnNewData的宣告、參數說明與備註,依群益官方元件說明文件「回報」章節;欄位表(含Type、OrderErr、Price、Qty、BuySell、KeyNo、SeqNo等欄位說明)依官方元件說明文件 V2.13.59 主手冊;Timefff依 V2.13.59 版本說明。980的判斷依官方範例程式。- 回報回補依官方
OnComplete說明。
免責聲明
本文章僅作為群益API實作經驗分享,不構成投資建議,且策略及程式皆應自行撰寫。期貨及衍生性金融商品交易屬高風險投資,請謹慎評估自身風險承擔能力。







