群益API 下單價格為什麼是字串?送出前要自己檢查的 5 件事
群益API 下單價格欄位裡,填進去的是一個字串。你用 double 從 0 開始加三次 0.1,轉成字串是 0.30000000000000004;同一個 123.5,在地區設定不同的電腦上可能被轉成 123,5。你在證券下單裡填了 M,以為是市價,但證券的 M 是昨收價。
價格欄是字串,代表你往裡面放什麼,它就收到什麼。 報價端的價格是整數、要自己換算;下單端正好反過來,要你自己交出一個正確的字串。

目錄
群益API 下單價格為什麼是字串?報價是整數,下單是字串
依官方元件說明文件的結構定義,三種下單物件的價格欄位型別都是 BSTR(字串):
| 物件 | 用途 | 價格欄位 |
|---|---|---|
FUTUREORDER | 國內期貨、選擇權 | bstrPrice |
STOCKORDER | 證券 | bstrPrice |
OVERSEAFUTUREORDER | 海外期貨 | bstrOrder |
這跟〈群益API 報價價格為什麼是整數〉講的報價端剛好相反:報價端給你整數,要除以 10 的 sDecimal 次方才是價格;下單端要你給字串。
而字串裡除了數字,還可以放 M、P、H、L 這類特殊價代碼——這是一個數字欄位做不到的事。
官方沒有說明元件會替你檢查哪些情況,所以格式、跳動點、特殊代碼的意思,都要自己保證。
還有一個實務經驗:字串裡放的是實際價格,不必乘上 10 的 sDecimal 次方。 這是我們實際送單的做法;官方結構註解只寫「委託價格」,沒有另外說明單位。
同一個 M,期貨和證券各代表什麼?
這是群益API 下單價格最值得注意的地方。兩個物件的官方結構註解如下:
| 物件 | bstrPrice 官方註解 |
|---|---|
FUTUREORDER「一般期選委託」小節 | 委託價格(IOC and FOK,可用「M」表示市價,「P」表示範圍市價) |
STOCKORDER(證券,不含盤中零股) | 委託價格,「M」表示參考價(昨收價)、「H」表示漲停價、「L」表示跌停價 |
同一個字母 M,在一般期選委託裡是市價,在證券裡是參考價(昨收價)。 如果把期貨程式的寫法直接搬來寫證券,照習慣填進去的 M 是昨收價,不是市價。
(盤中零股另有一份 STOCKORDER 定義,它的 bstrPrice 只寫「委託價格」,沒有這三個代碼。)
證券的市價單怎麼下?
用另一個欄位。STOCKORDER 的 nSpecialTradeType 在官方註解裡標著「[證券逐筆交易]」,1 是市價、2 是限價,下一行寫著:
(市價單之委託價格Price請給0; 限價單之委託價格Price 不可為0)
錯誤代碼表也有對應的一條:
| 錯誤碼 | 常數 | 官方說明 |
|---|---|---|
1068 | SK_ERROR_SPECIAL_TRADE_TYPE_IS_MARKETPRICE_AND_ORDERPRICE_SHOULD_BE_ZERO | (逐筆交易)凡市價單之委託價應為0 |
也就是說,證券(逐筆交易)要下市價:nSpecialTradeType 設 1,價格給 0,不要填 M。
期貨市價單可以用 ROD 嗎?
再看一次 FUTUREORDER「一般期選委託」小節裡 bstrPrice 的官方註解:「委託價格(IOC and FOK,可用「M」表示市價,「P」表示範圍市價)」。
官方只在 IOC 與 FOK 的條件下列出 M、P 可用。 所以一般期選委託下市價或範圍市價時,時效欄位 sTradeType 用 1(IOC)或 2(FOK);0(ROD)不在官方列出的範圍裡。
版本也值得留意。官方的版本控管表有兩條相關紀錄:
- 2.13.47:修正
SendFutureOrderCLR期貨下單委託價輸入市價(M)、範圍市價(P)錯誤之情況 - 2.13.50:修正
SendOptionOrder選擇權下單委託價輸入市價(M)、範圍市價(P)錯誤之情況
如果你用的元件比這兩版舊,遇到市價單的問題時,先確認元件版本。
群益API 下單價格要落在哪裡?跳動點從商品清單拿
限價單的價格要落在這個商品的跳動點(最小價格變動單位)上。群益API 下單價格送出前,先把它貼齊跳動點。
跳動點不必自己寫死一張表。依官方版本控管表,2.13.52 起,商品清單事件 OnNotifyStockList 與 OnNotifyCommodityListWithTypeNo 的回傳內容新增了「跳動點」與「幣別」兩個欄位。
官方在 OnNotifyStockList 的備註裡給了證券的範例:
10| 0.01 |/ 50| 0.05 |/ 100 | 0.1 |/ 500| 0.5 |/ 1000| 1 |/ 10000| 5 |每一段是「上限|跳動點|」,段與段之間用「/」隔開。上限那一端不含——官方的說明是(節錄):「50元(不含)以下,0.05」。
⚠️ 這個範例是證券的。期貨、選擇權的跳動點,請從你查到的商品清單欄位讀出來,不要拿這個範例去推。
至於下單回 1017(SK_ERROR_PRICE_INVALID),官方說明是「下單價格錯誤。」,沒有寫哪些情況會觸發。遇到時照〈群益API 下單回傳值是 0 就成功了嗎〉的做法,把 bstrMessage 原文保存下來。
用 double 算價格會出什麼錯?十進位、地區設定與捨入
這一段是通用的程式原則,跟群益無關,但它會直接破壞上一節的「貼齊跳動點」。
第一,二進位浮點數表示不了 0.1 這類十進位小數。 double 與 float 無法精確表示 0.1、0.05 這類數字,一格一格加減跳動點,累積出來的值可能不在跳動點上,轉成字串也可能多出一長串小數。價格計算全程用十進位型別(C# 的 decimal),送出前最後一步才轉字串。
第二,轉字串要用不受地區設定影響的格式。 同一個 123.5,在德文(德國)地區設定下會輸出成 123,5。微軟文件對 CultureInfo.InvariantCulture 的定義是「與文化無關(不變)的物件」,轉字串時指定它,輸出就固定是 123.5。
第三,Math.Round 預設不是你以為的四捨五入。 依微軟文件,Math.Round(Decimal) 會「將中點值四捨五入至最近的偶數」,也就是銀行家捨入:2.5 會變成 2。要讓 2.5 變成 3,必須明確指定 MidpointRounding.AwayFromZero。
using System.Globalization;
// 價格全程用 decimal,送出前最後一步才轉字串
decimal tick = 0.5m; // 從商品清單的跳動點欄位查得(此處僅示意)
decimal price = 123.3m; // 策略算出來的價格,還沒貼齊跳動點
// 貼齊跳動點;Math.Round 預設是銀行家捨入,要四捨五入必須明確指定
decimal aligned = Math.Round(price / tick, MidpointRounding.AwayFromZero) * tick; // 123.5
FUTUREORDER pOrder = new FUTUREORDER();
pOrder.bstrPrice = aligned.ToString(CultureInfo.InvariantCulture); // "123.5",小數點不受地區設定影響
pOrder.sTradeType = 0; // 0:ROD 1:IOC 2:FOK(一般期選委託)
// 市價:bstrPrice 給 "M"(範圍市價給 "P"),時效只能用 IOC 或 FOK
// pOrder.bstrPrice = "M";
// pOrder.sTradeType = 1; // IOC程式裡的 tick 與 price 只是示意數字,不是任何商品的真實跳動點。貼齊時要往上、往下還是取最近,是策略的決定,本文不給建議。
IOC 和 FOK 的代碼,在海期委託對調了
時效欄位的代碼,在官方結構定義裡並不完全一致:
| 物件(官方結構小節) | 欄位 | 1 代表 | 2 代表 |
|---|---|---|---|
FUTUREORDER「一般期選委託」小節 | sTradeType | IOC | FOK |
STOCKORDER(證券逐筆交易) | nTradeType | IOC | FOK |
OVERSEAFUTUREORDER「海期委託」小節 | sTradeType | FOK | IOC |
OVERSEAFUTUREORDER「海期委託 SGX DMA 專線」小節 | sTradeType | IOC | FOK |
「海期委託」那一節的官方註解寫的是「0:ROD 1:FOK 2:IOC」,跟一般期選委託對調;同一個結構名稱的「SGX DMA 專線」小節,又回到 1 IOC、2 FOK。
從國內期貨程式改寫成海期委託時,沿用同一個常數,就會把 IOC 送成 FOK。
國內這邊也一樣:同一個 FUTUREORDER 結構的智慧單小節,時效又是 3 IOC、4 FOK,那是另一套。其中觸價單(MIT)小節的其他欄位,見〈群益API 觸價單(MIT)一直被退?〉。
特殊值的意思要逐個物件、逐個小節查,不要跨物件沿用,連同名結構也不行。 這跟上面的 M 是同一個教訓,也跟〈群益API 下單回傳值是 0 就成功了嗎〉那張判讀表的結論一樣:值的意思要一個一個查。
群益API 下單價格送出前的 5 件事
- 十進位計算、最後才轉字串。 用
decimal算,轉字串時指定CultureInfo.InvariantCulture。 - 跳動點從商品清單拿,送出前貼齊。 2.13.52 起的商品清單事件有跳動點欄位,不要寫死一張表。
- 特殊價代碼逐物件查。 一般期選委託的
M是市價、P是範圍市價;證券的M是參考價、H漲停、L跌停。證券(逐筆交易)的市價單用nSpecialTradeType設1、價格給0。 - 一般期選委託的市價、範圍市價只搭配 IOC 或 FOK。
- 時效代碼逐物件、逐小節查。 一般期選委託與證券是
1IOC、2FOK;「海期委託」小節對調;「SGX DMA 專線」小節又與國內相同;期選智慧單小節是3IOC、4FOK。
常見問題
群益API 下單回 1017 是什麼意思?
1017 的常數是 SK_ERROR_PRICE_INVALID,官方說明是「下單價格錯誤。」,官方沒有寫哪些情況會觸發。遇到時把 bstrMessage 的原文記下來,再檢查價格字串的格式、是否貼齊跳動點、特殊代碼是否用對物件。
群益API 證券市價單要怎麼下?
不是在價格欄填 M——證券的 M 是參考價(昨收價)。依官方結構註解,證券逐筆交易的市價單要把 nSpecialTradeType 設為 1,價格給 0。
期貨市價單的價格欄要填什麼?
一般期選委託時,FUTUREORDER.bstrPrice 填 M 是市價、填 P 是範圍市價。官方只在 IOC 與 FOK 的條件下列出這兩個代碼,所以時效用 1(IOC)或 2(FOK)。
從國內期貨改寫成海期委託,時效代碼要改嗎?
要逐小節查。OVERSEAFUTUREORDER 的「海期委託」小節是 1 FOK、2 IOC,跟一般期選委託相反;同一個結構的「SGX DMA 專線」小節則是 1 IOC、2 FOK,跟一般期選委託相同。
風險揭露
期貨與選擇權屬高槓桿商品,價格波動可能造成超過原始保證金的損失,交易人須自負交易責任。本文為程式開發技術教學,說明下單價格欄位的格式與特殊代碼,不構成投資建議,也不保證任何交易結果。程式化交易並不降低市場風險,反而可能因程式錯誤造成非預期的委託行為——把證券的 M 當成市價、沿用錯誤的時效代碼、或價格字串格式錯誤,都可能送出與預期不同的委託。
投資人教育資源
| 機構 | 資源 |
|---|---|
| 臺灣期貨交易所(TAIFEX) | 期貨及選擇權數位學習網 |
| 證券暨期貨市場發展基金會 | 證券期貨市場教育推廣 |
| 金融智慧網 | 金管會金融知識平台 |
| 中華民國期貨業商業同業公會 | 期貨業法規與宣導 |
| 證券投資人及期貨交易人保護中心 | 投資人保護與申訴 |
延伸閱讀
- 〈群益API 報價價格為什麼是整數〉——價格處理的另一端:報價給整數,要用
sDecimal換算。 - 〈群益API 下單回傳值是 0 就成功了嗎〉——回
1017之後怎麼處理,以及「值的意思要一個一個查」的判讀表。 - 〈群益API 下單初始化有哪 7 步〉——送單之前的初始化順序。
參考資料
- 三種下單物件的價格欄位型別、
FUTUREORDER/STOCKORDER/OVERSEAFUTUREORDER的價格與時效註解、nSpecialTradeType,依群益官方元件說明文件 2.13.57 版第 5 章結構定義;錯誤碼1017/1068依官方錯誤代碼定義表。 - 2.13.47/2.13.50 市價輸入修正、2.13.52 商品清單新增跳動點與幣別,依官方版本控管表;跳動點格式範例依
OnNotifyStockList備註。 - Math.Round 方法 – Microsoft Learn
- CultureInfo.InvariantCulture 屬性 – Microsoft Learn
- 價格字串放實際價格、不乘
sDecimal:實作經驗,非官方文件記載。
免責聲明
本文章僅作為群益API實作經驗分享,不構成投資建議,且策略及程式皆應自行撰寫。期貨及衍生性金融商品交易屬高風險投資,請謹慎評估自身風險承擔能力。







