群益API 下單價格是字串:報價端整數換算與下單端字串的兩端對照示意圖

群益API 下單價格為什麼是字串?送出前要自己檢查的 5 件事

群益API 下單價格欄位裡,填進去的是一個字串。你用 double 從 0 開始加三次 0.1,轉成字串是 0.30000000000000004;同一個 123.5,在地區設定不同的電腦上可能被轉成 123,5。你在證券下單裡填了 M,以為是市價,但證券的 M 是昨收價。

價格欄是字串,代表你往裡面放什麼,它就收到什麼。 報價端的價格是整數、要自己換算;下單端正好反過來,要你自己交出一個正確的字串。

群益API 下單價格是字串:報價端整數換算與下單端字串的兩端對照示意圖

群益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)

錯誤代碼表也有對應的一條:

錯誤碼常數官方說明
1068SK_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「一般期選委託」小節sTradeTypeIOCFOK
STOCKORDER(證券逐筆交易)nTradeTypeIOCFOK
OVERSEAFUTUREORDER「海期委託」小節sTradeTypeFOKIOC
OVERSEAFUTUREORDER「海期委託 SGX DMA 專線」小節sTradeTypeIOCFOK

「海期委託」那一節的官方註解寫的是「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 件事

  1. 十進位計算、最後才轉字串。 用 decimal 算,轉字串時指定 CultureInfo.InvariantCulture。
  2. 跳動點從商品清單拿,送出前貼齊。 2.13.52 起的商品清單事件有跳動點欄位,不要寫死一張表。
  3. 特殊價代碼逐物件查。 一般期選委託的 M 是市價、P 是範圍市價;證券的 M 是參考價、H 漲停、L 跌停。證券(逐筆交易)的市價單用 nSpecialTradeType 設 1、價格給 0。
  4. 一般期選委託的市價、範圍市價只搭配 IOC 或 FOK。
  5. 時效代碼逐物件、逐小節查。 一般期選委託與證券是 1 IOC、2 FOK;「海期委託」小節對調;「SGX DMA 專線」小節又與國內相同;期選智慧單小節是 3 IOC、4 FOK。

常見問題

群益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)期貨及選擇權數位學習網
證券暨期貨市場發展基金會證券期貨市場教育推廣
金融智慧網金管會金融知識平台
中華民國期貨業商業同業公會期貨業法規與宣導
證券投資人及期貨交易人保護中心投資人保護與申訴

延伸閱讀

參考資料

  • 三種下單物件的價格欄位型別、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實作經驗分享,不構成投資建議,且策略及程式皆應自行撰寫。期貨及衍生性金融商品交易屬高風險投資,請謹慎評估自身風險承擔能力。

延伸閱讀|相關文章

發佈留言

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