群益API 報價價格為什麼是整數?4 種數字不對的狀況與換算方式
訂閱終於通了,報價開始進來——然後你看到群益API 報價價格欄位裡,台積電是 108500,台指期是 2295000。
這一種查五分鐘就會知道原因。真正麻煩的是另外三種:除以 100 之後還是不對、時間欄位丟進解析函式就爆掉、同一支程式對 K 線和快照的行為不一致。

目錄
群益API 報價價格為什麼是整數?
SKSTOCKLONG 結構裡的價格欄位——最高、開盤、最低、成交——型別都是 LONG,沒有小數點。
群益API 報價價格的小數點資訊沒有消失,它放在同一個結構的另一個欄位裡:
SHORT sDecimal; // 小數位數所以換算方式是:
^^實際價格 = 整數值 ÷ 10^sDecimal^^
官方在另一處也有「價格欄位一般除以 100.0 顯示」這樣的說法。這兩件事不衝突——多數商品的 sDecimal 就是 2,除以 100 剛好對。
問題出在「多數」不是「全部」。
「除以 100」什麼時候會錯?官方自己舉了例子
在說明 K 線舊版輸出格式時,官方文件給了兩個範例:
舊版輸出函式中所取回的價格都未經過小數點處理,例如1101 價格為「36.50」,則函式所傳回的價格為「3650」
特別注意舊版輸出格式中的期匯率商品(TypeNo=209)小位數有四位須特別再處理,例如RH1704價格為「6.8712」,則函式所傳回的價格為「68712」
把這兩個例子放在一起看,就是群益API 報價價格這個主題真正的難處:
同一支寫死 /100 的程式,在 1101 上完全正確;在 RH1704 上會得到 687.12。
一個大了 100 倍的價格——而且它不會觸發任何錯誤,你拿到的是一個看起來很像價格的數字。
寫死除以 100 不是會不會錯的問題,是什麼時候錯的問題。
(上面兩段引文的脈絡是 K 線的舊版輸出格式說明。至於「期匯率商品有四位小數」,那是商品本身的性質,不限於 K 線。)
比寫死更難查的版本:把 sDecimal 快取起來
知道群益API 報價價格要讀 sDecimal 之後,還有一個更隱蔽的寫法會出事。
sDecimal 是每一檔商品各自的,跟著那一檔的結構一起送過來。但很自然會寫出來的第一版是——讀一次存成常數或設定值,之後所有商品共用。
在一個只看台股、只看台指期的程式裡,這樣寫永遠不會出事,因為大家的 sDecimal 都是 2。等到有一天加進一檔期匯率商品,那個快取的 2 就會套到一個四位小數的商品上。
這比寫死 100 更難查,因為程式碼看起來「有在讀 sDecimal」——只是讀錯了時機。
sDecimal 要從當下那一檔的結構讀,不要快取成全域設定。
K 線的新舊輸出,換算規則不一樣
群益API 報價價格還有一個容易混淆的地方,它是「同一支程式在不同地方行為不一致」那種症狀的成因。
依官方說明:K 線舊版輸出格式的價格未經小數處理,新版輸出(sOutType=1)則已經處理過,由 K 線主機提供。
所以會出現這個狀況:你走快照拿到的價格要自己換算,走新版 K 線拿到的價格已經是處理好的——如果你對兩邊套用同一套換算,K 線那邊就會被多除一次。
這不是資料髒,是兩條路的約定不同。 寫程式前先確認自己走的是哪一種輸出格式,比事後對著數字猜有效率得多。
時間與日期也是整數,而且不只一種格式
這是另一個獨立的坑:它跟價格無關,但處理群益API 報價價格時幾乎一定會一起遇到——SKCOM 的時間與日期欄位全部是整數編碼,不是時間型別。
| 欄位 | 格式 | 範例 |
|---|---|---|
| 日期 | yyyyMMdd | 20260916 |
| 時間 | hhmmss | 134530 |
| 毫秒/微秒 | 六位數 | 另有獨立欄位 |
把 134530 丟給泛用的日期時間解析函式,不會得到下午一點四十五分——你會拿到例外,或是一個 1970 年的時間戳。這些數字要自己拆位數再組。
群益API 報價價格的換算函式該怎麼寫?
重點只有一個:位數從結構讀,不要寫死、也不要快取。
// 價格是整數,小數位數由結構自己帶:實際價格 = 整數 / 10^sDecimal
static decimal ToPrice(long raw, short sDecimal)
{
decimal factor = 1m;
for (int i = 0; i < sDecimal; i++) factor *= 10m;
return raw / factor;
}
// 時間與日期是整數編碼,要自己拆
// nDate = 20260916、nTime = 134530
static DateTime ToDateTime(int nDate, int nTime)
{
int y = nDate / 10000, m = nDate / 100 % 100, d = nDate % 100;
int hh = nTime / 10000, mm = nTime / 100 % 100, ss = nTime % 100;
return new DateTime(y, m, d, hh, mm, ss);
}⚠️ 上面的 ToDateTime 刻意沒有做範圍檢查,實務上要補。 盤後或異常狀態下可能拿到不合理的值,直接組 DateTime 會丟例外——而那個例外會從資料層一路冒上來,出現在一個跟時間毫無關係的地方。值不合理就當作沒有資料,不要讓例外離開這一層。
為什麼建議用 decimal 而不是 double?
如果這套群益API 報價價格的換算只用來顯示,double 其實沒有問題。
但實務上有一個很自然的發展:同一套換算工具,後來會被送單那一端共用。 而下單那邊對價格的要求嚴格得多——差一檔就可能被退單,二進位浮點的誤差在那裡是會出事的。
所以建議是條件式的:如果你預期這套換算之後會被送單端共用,就從一開始用 decimal。 一開始選對,比之後回來改一輪省事。
(下單端價格為什麼有那麼嚴格的要求,是另一篇的主題,這裡不展開。)
常見問題
群益API 報價價格為什麼要除以 100?
嚴格說不是除以 100,是除以 10^sDecimal。多數商品的 sDecimal 是 2,所以除以 100 剛好對;但官方自己就舉了一個四位小數的期匯率商品範例,那一檔除以 100 會大 100 倍。
群益API 報價價格我已經有讀 sDecimal 了,為什麼還是會錯?
檢查是不是讀一次就快取起來了。sDecimal 是每一檔商品各自的,要從當下那一檔的結構讀,不能存成全域設定給所有商品共用。
K 線的價格也要除嗎?
看輸出格式。依官方說明,舊版輸出未經小數處理,新版輸出(sOutType=1)已經處理過——對新版再除一次就錯了。
時間欄位可以直接丟給日期解析函式嗎?
不行。那是 yyyyMMdd/hhmmss 的整數編碼,不是時間戳。要自己拆位數再組,而且組之前先驗範圍。
換算一定要用 decimal 嗎?
只用來顯示的話 double 沒問題。但如果這套換算之後會被送單那邊共用,建議一開始就用 decimal——下單端對價格精度的要求嚴格得多。
風險揭露
期貨與選擇權屬高槓桿商品,價格波動可能造成超過原始保證金的損失,交易人須自負交易責任。本文為程式開發技術教學,說明報價欄位的編碼方式與換算,不構成投資建議,也不保證任何交易結果。程式化交易並不降低市場風險,反而可能因程式錯誤造成非預期的委託行為——價格換算錯誤正是這類錯誤的來源之一。
投資人教育資源
| 機構 | 資源 |
|---|---|
| 臺灣期貨交易所(TAIFEX) | 期貨及選擇權數位學習網 |
| 證券暨期貨市場發展基金會 | 證券期貨市場教育推廣 |
| 金融智慧網 | 金管會金融知識平台 |
| 中華民國期貨業商業同業公會 | 期貨業法規與宣導 |
| 證券投資人及期貨交易人保護中心 | 投資人保護與申訴 |
延伸閱讀
- 〈群益API 報價訂閱有哪兩層〉——先訂得到報價,才會看到群益API 報價價格這些欄位。
- 〈群益API 訂閱額度有多少〉——兩層的額度與「沒報錯不等於訂上了」。
- 〈群益API 事件回呼跑在哪個執行緒〉——換算要放在哪裡做,取決於回呼裡能做什麼。
參考資料
SKSTOCKLONG結構定義(價格欄位為LONG、sDecimal為小數位數)、K 線新舊輸出格式的差異、兩則價格範例(1101 與 RH1704),均依群益官方元件說明文件的國內報價章節。- 兩則價格範例的原文脈絡為 K 線舊版輸出格式的說明。
- 時間與日期為整數編碼:實測歸納。
- 組
DateTime前先驗範圍:實務建議,非官方規定。
免責聲明
本文章僅作為群益API實作經驗分享,不構成投資建議,且策略及程式皆應自行撰寫。期貨及衍生性金融商品交易屬高風險投資,請謹慎評估自身風險承擔能力。







