徹底解決 Off quotes/重新報價(MT5/MQL5)— 10021
目錄
- 這兩種錯誤(+MT4 的 136/138)差異在哪裡
- ① TRADE_RETCODE_PRICE_OFF = 10021(沒有可處理的報價)
- ② TRADE_RETCODE_REQUOTE = 10004(重新報價=提供新價格)
- ③ MT4 時代的錯誤代碼 136 / 138
- 先花 30 秒做初步判斷
- 成因與對策(5 種情境)
- ① 行情急變、指標行情跳動(送出的價格在到達前就已過期)
- ② deviation(允許滑點)設定過緊
- ③ 執行方式差異(重新報價是 instant 執行才有的現象)
- ④ 報價稀薄或停滯的時段與商品
- ⑤ 連線延遲(VPS 距離券商伺服器太遠)
- 用 MQL5 減少此錯誤的程式碼(EA 開發者適用)
- 以 point 為單位設定合理的 deviation
- 只對價格類 retcode 進行重試(以最新 tick 重新送單)
- 利用重新報價(10004)所提供的新價格
- 從源頭設定不下單的時段
- 優先順序檢查清單
- 總結
- 常見問題
- Q: 10004 與 10021 哪一個比較嚴重?
- Q: 完全不會出現重新報價的券商是否比較優良?
- Q: MT4 的 EA 出現 error 136 / 138,可以用相同的對策嗎?
- Q: 回測時不會出現,但實盤卻會出現。
徹底解決 Off quotes/重新報價(MT5/MQL5)
運行 EA 時,若在日誌或 Expert 頁籤中看到 off quotes(10021)或 requote(10004),乍看之下會以為是「被券商拒絕成交」而感到不安,但這兩者其實不是資金或手數的問題,而是「價格」的問題。原因就在於你送出的價格與伺服器當下持有的報價對不上——僅此而已,絕大多數成因都可歸結為行情急變、允許滑點設定、執行方式、或連線延遲這四類。
本文同時面向使用 MT5 執行 EA 的交易者,以及以 MQL5 開發 EA 的工程師,將 10021(TRADE_RETCODE_PRICE_OFF)與 10004(TRADE_RETCODE_REQUOTE),以及 MT4 時代的錯誤代碼 136/138 的真面目、成因、可立即採取的對策,到程式碼層面的長期解法整理成一篇完整指南。若需要錯誤代碼的總覽,請參考 MQL5/MT5 錯誤代碼處理總指南。
本文以 2026 年 7 月當下的 MT5(build 4xxx 系列)為前提。實際行為細節(是否回傳 requote、或直接以其他價格成交等)會因券商的執行方式而異。
這兩種錯誤(+MT4 的 136/138)差異在哪裡
「價格對不上」這類拒絕,依伺服器回覆方式的不同,可分成兩種。
① TRADE_RETCODE_PRICE_OFF = 10021(沒有可處理的報價)
這是 OrderSend() 回傳結果 MqlTradeResult.retcode 中的值,代表**「沒有可用來處理該請求的報價(There are no quotes to process the request)」**。意指伺服器端當下沒有有效報價,或送出的價格與目前報價相差過大而無法處理。
含意: 沒有可處理該請求的報價
常數: TRADE_RETCODE_PRICE_OFF
數值: 10021
② TRADE_RETCODE_REQUOTE = 10004(重新報價=提供新價格)
同樣是 OrderSend() 的 retcode,但這並非單純拒絕,而是**「這個價格不行,但用這個新價格如何?」的重新報價(requote)。回傳的 MqlTradeResult 中的 bid / ask 會帶有伺服器重新提出的價格**。
含意: 重新報價(Requote)— 提出新價格
常數: TRADE_RETCODE_REQUOTE
數值: 10004
// 日誌中常見的典型輸出範例
2026.07.07 21:30:02.118 EA_NAME EURUSD,M5: OrderSend error 10004 (requote)
2026.07.07 21:30:02.310 EA_NAME EURUSD,M5: OrderSend error 10021
③ MT4 時代的錯誤代碼 136 / 138
在 MQL4(MT4)中,同樣的現象是以 GetLastError() 的錯誤代碼回傳。
| MT4 常數 | 數值 | 對應的 MT5 retcode |
|---|---|---|
ERR_OFF_QUOTES | 136 | 10021 (TRADE_RETCODE_PRICE_OFF) |
ERR_REQUOTE | 138 | 10004 (TRADE_RETCODE_REQUOTE) |
若你在舊版 EA 的解說文章或 MT4 版 EA 的日誌中看到「error 136」「error 138」,本文的內容可直接套用(MT4 的慣例做法是先呼叫 RefreshRates() 重新取得報價後再送單,MT5 的寫法將於後文說明)。
實務上的判斷方式:
| retcode | 伺服器的意思 | EA 應採取的動作 |
|---|---|---|
| 10004 (requote) | 「價格已經變動,這是新報價」 | 用最新價格重新送單(或放棄本次進場) |
| 10021 (price off) | 「目前沒有可處理的報價」 | 稍等片刻後以最新 tick 重新送單 |
兩者都是暫時性(可重試)的錯誤,無法透過修改程式碼或設定完全杜絕,但可以大幅降低發生頻率。
先花 30 秒做初步判斷
- 確認發生時間點(查看日誌時間戳)
- 就業數據、FOMC 等指標公布的瞬間 → 屬於正常的行情急變。若 EA 有內建指標過濾功能,請啟用它
- 伺服器時間 0 點前後(換日結算)或週一開盤時的跳空 → 報價稀薄的時段,屬正常範圍
- 與時段無關、隨機頻繁發生 → 應懷疑連線、VPS、或 deviation 設定
- 確認發生在哪個商品
- 若集中在小眾貨幣對、外匯特殊組合、CFD 等流動性較低的商品 → 原因在於該商品本身報價稀薄
- 測試手動下單是否也會發生
- 若手動快速下單正常成交、只有 EA 被拒絕 → 高機率是 EA 的
deviation(允許滑點)設得過緊
- 若手動快速下單正常成交、只有 EA 被拒絕 → 高機率是 EA 的
透過以上三點,先判斷出問題是「行情因素」「商品因素」還是「設定/環境因素」,再進入下方依成因分類的對策。
成因與對策(5 種情境)
① 行情急變、指標行情跳動(送出的價格在到達前就已過期)
症狀: 集中發生在經濟指標公布時刻、重要人物發言、週一清晨等時段的 10004/10021。
原因: EA 接收到 tick 並計算出價格後,訂單傳送到伺服器需要數十至數百毫秒,這段期間價格可能已經波動了數個 pips。送出的價格已不存在,伺服器因此回傳重新報價(10004)或無報價(10021)。與其說是錯誤,不如說是快速行情下必然會出現的現象。
對策:
- 停止在指標公布前後開新倉(新聞過濾器)。本站提供的 EA 標準內建
EconomicFilter - 將
deviation(允許滑點)調整至合理數值(詳見②) - 加入重試機制(詳見下方程式碼)
② deviation(允許滑點)設定過緊
症狀: 即使行情平穩也偶爾出現,手動下單正常但 EA 卻被拒絕。
原因: MqlTradeRequest.deviation 是宣告「與送出價格相差幾個**點(points)**以內可接受」的參數。若設為 0 或極小的數值,即使只是一般的報價更新幅度也會被拒絕。常見的誤解是把 points 當成 pips(五位報價券商中 1 pip = 10 points)。
對策:
- 先從
deviation10〜30 points(=1〜3 pips)左右觀察效果。若非剝頭皮策略,20 points 是相對穩妥的起點 - 檢查是否有「原本想設 deviation=5,結果變成 0.5 pips」之類的單位換算錯誤
- 若策略完全不允許滑點,則應將拒絕視為正常規格,只需控制重試次數
③ 執行方式差異(重新報價是 instant 執行才有的現象)
症狀: 在 A 券商頻繁發生,在 B 券商卻從未出現。
原因: 重新報價(10004)是 instant execution(即時執行) 特有的現象。即時執行是「請以此價格成交」的下單方式,一旦價格變動,伺服器就會重新提出新價格(requote)。而 market execution(市價執行) 則是「請以當前市場價格成交」,原理上不會出現重新報價,取而代之的是直接以有落差的價格成交(滑點)。
也就是說,「不出現重新報價=優良」並非事實,而是**「被拒絕」與「滑點成交」之間的權衡取捨**。商品的執行方式可在 MT5 的「商品規格(Specification)」中的 Execution 欄位確認,程式碼則可透過 SYMBOL_TRADE_EXEMODE 查詢。
對策:
- 確認自己帳戶的執行方式(許多海外券商的標準帳戶採市價執行,本身就不會出現重新報價)
- 若頻繁的重新報價影響策略運作,可考慮改用市價執行的帳戶類型或更換券商
- 即使是市價執行,不同券商對
deviation的尊重程度也不同,若無法接受極端滑點,應以成交紀錄驗證實際滑點狀況
④ 報價稀薄或停滯的時段與商品
症狀: 伺服器時間 0 點前後(換日結算)、週一開盤後不久、聖誕假期等清淡時段,或小眾商品出現 10021。
原因: 換日結算時因處理隔夜利息,報價傳送可能暫時中斷或點差極端擴大。週一開盤後不久或流動性較低的商品,本身可處理的報價就相對稀少。在此狀態下下單就容易觸發 10021(無報價)。
對策:
- 避開伺服器時間 23:55〜0:05 前後的新倉進場(時間過濾器)
- 避開週一開盤後的前幾分鐘(
AvoidMondayOpen類設定) - 加入點差過濾器(
MaxSpread)。報價稀薄時段點差通常會擴大,因此可有效自動避開這類時段
⑤ 連線延遲(VPS 距離券商伺服器太遠)
症狀: 與時段、商品無關,頻率明顯高於其他環境,ping 值偏高。
原因: 訂單傳送到伺服器的往返時間(延遲)越長,這段期間價格變動的機率就越高。若使用家用電腦、或使用距離券商伺服器所在地(多為倫敦、紐約等)較遠地區的 VPS,10004/10021 的發生頻率就會在結構上升高。MT5 右下角顯示的 ping 值可作為參考指標(數百毫秒明顯不利,數十毫秒以下較為理想)。
對策:
- 確認 MT5 右下角的 ping 值,若長期偏高,應檢討 EA 的執行環境
- 改用距離券商伺服器較近地區的 VPS。老實說,由延遲造成的 10004/10021 無法靠程式碼解決,唯一有效的對策就是物理上拉近距離。挑選方式可參考 EA 適用 VPS 挑選指南
- �feq策略越偏向剝頭皮,延遲的影響就越大。若是日線、H4 等中長線 EA,此項成因的優先度較低
用 MQL5 減少此錯誤的程式碼(EA 開發者適用)
方針有三個:(1) 將 deviation 設為合理數值、(2) 被拒絕時重新取得最新 tick 後再送單、(3) 只針對價格類 retcode 進行重試。
以 point 為單位設定合理的 deviation
MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_BUY;
req.volume = lots;
req.deviation = 20; // 允許滑點 20 points(五位報價時為 2.0 pips)
// req.price / req.sl / req.tp / req.magic 等亦須一併設定
deviation 的單位是 points。在五位(三位)報價的券商中,10 points = 1 pip。設為 0 或極小值會不必要地拉高拒絕率。
只對價格類 retcode 進行重試(以最新 tick 重新送單)
重點在於每次重試都要用 SymbolInfoTick() 重新取得價格(若沿用舊價格重新送單只會再次被拒絕),以及將重試對象限定於 10004/10021。對資金不足(10019)或請求無效(10013)進行機械式重送並無意義,只會讓日誌變得雜亂。
bool IsRetryableRetcode(uint rc)
{
return (rc == TRADE_RETCODE_REQUOTE // 10004
|| rc == TRADE_RETCODE_PRICE_OFF); // 10021
}
// 以最新 tick 更新價格,最多重試 3 次後送單
bool SendWithRetry(MqlTradeRequest &req, MqlTradeResult &res, int maxTries = 3)
{
for(int attempt = 0; attempt < maxTries; attempt++)
{
MqlTick tick;
if(!SymbolInfoTick(req.symbol, tick))
{
Print("SymbolInfoTick failed: ", GetLastError());
return false;
}
req.price = (req.type == ORDER_TYPE_BUY) ? tick.ask : tick.bid;
if(OrderSend(req, res) && res.retcode == TRADE_RETCODE_DONE)
return true; // 成交成功
if(!IsRetryableRetcode(res.retcode))
{
PrintFormat("OrderSend failed (no retry): retcode=%d", res.retcode);
return false; // 非價格類錯誤不重試
}
PrintFormat("Retry %d/%d after retcode=%d", attempt + 1, maxTries, res.retcode);
Sleep(200 + 150 * attempt); // 200ms→350ms→500ms 逐步遞增等待
}
Print("Order abandoned after retries (price kept moving).");
return false;
}
之所以讓 Sleep() 的等待時間逐步拉長,是因為在行情急變的瞬間即使以 0ms 連續重送,也只會不斷被拒絕。反過來說,等太久又會讓進場價格偏離策略原本的預期,因此重試 2〜3 次後就應放棄才是健康的做法。若是限價單(TRADE_ACTION_PENDING),成功時的 retcode 會是 TRADE_RETCODE_PLACED(10008),這點也請留意。
利用重新報價(10004)所提供的新價格
發生 10004 時,MqlTradeResult 的 bid / ask 會帶有伺服器重新提出的價格。若像上面一樣以最新 tick 重新送單,實務上已經足夠;但若想在 instant 執行下實作「若重新報價落在可接受範圍內就直接採用」的邏輯,則可將 res.ask / res.bid 與原本預期價格的差異換算成 points 後再判斷是否重新送單。
從源頭設定不下單的時段
程式碼層面的重試終究只是治標。在換日結算前後、指標公布前後、點差擴大時停止新倉的過濾器,才是更根本有效的做法。
// 點差過濾器範例:點差擴大時暫緩新倉
long spreadPts = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spreadPts > MaxSpreadPoints)
{
// 暫緩新倉進場(可自動避開容易出現 10021 的報價稀薄時段)
return;
}
FXEA365 所提供的 EA,皆標準內建點差過濾器、指標過濾器、以及針對價格類 retcode 的自動重試機制。
優先順序檢查清單
| 優先度 | 確認項目 | 對策 |
|---|---|---|
| 🚨 首要 | 是否集中發生在指標公布、行情急變的瞬間 | 啟用新聞過濾器・該時段視為正常規格接受 |
| 🚨 首要 | deviation 是否過小(單位為 points) | 調整為 10〜30 points・確認是否混淆 pips/points |
| ⚠️ 其次 | 是否偏向換日結算、週一開盤、清淡商品 | 加入時間過濾器+點差過濾器 |
| ⚠️ 其次 | 執行方式是否為 instant | 考慮改用市價執行帳戶(需權衡滑點) |
| ⚠️ 其次 | ping 值是否偏高(數百毫秒) | 改用距離伺服器較近的 VPS |
| 🛠 開發 | 重試是否僅限於價格類 retcode | 以 SymbolInfoTick 重新取價+2〜3 次後即中止 |
總結
- 10021(TRADE_RETCODE_PRICE_OFF)代表「沒有可處理的報價」,10004(TRADE_RETCODE_REQUOTE)代表「提出新價格」。與 MT4 時代的 136/138 屬於同一類價格拒絕錯誤,並非資金或手數的問題。
- 成因可歸納為 行情急變、deviation 過小、instant 執行、報價稀薄的時段/商品、連線延遲 這五種。
- 重新報價是 instant 執行特有的現象,在市價執行下則會以滑點的形式呈現。「不出現=好」並不成立,而是一種權衡取捨。
- EA 開發者應以 以最新 tick 重新取價的 2〜3 次重試(僅限 10004/10021)+合理設定 deviation+時間/點差過濾器來做長期對策。唯獨延遲造成的部分,只能靠物理對策(更靠近券商的 VPS)來改善。
錯誤代碼的總覽請參考 MQL5/MT5 錯誤代碼處理總指南,標準內建這些對策的免費 EA 請參考 EA 一覽。
常見問題
Q: 10004 與 10021 哪一個比較嚴重?
兩者都是暫時性的價格類錯誤,嚴重程度並無太大差異。10004 是「被重新提出新價格」,10021 則是「沒有可處理的報價」,只是回覆方式不同。若只是偶發,不必特別處理;只有在特定時段或商品上頻繁發生時,才需要針對成因(指標、換日結算、deviation、連線)逐一排除。
Q: 完全不會出現重新報價的券商是否比較優良?
很可能只是執行方式不同。市價執行的帳戶原理上不會出現重新報價,價格變動時會直接以有落差的價格成交(滑點)。由於這是「被拒絕」與「滑點」之間的取捨,建議透過成交紀錄確認實際滑點狀況後再做判斷。
Q: MT4 的 EA 出現 error 136 / 138,可以用相同的對策嗎?
可以。136(ERR_OFF_QUOTES)對應 10021,138(ERR_REQUOTE)對應 10004,成因與對策皆相通。MQL4 的慣例做法是在重新送單前呼叫 RefreshRates() 更新 Bid / Ask,這與 MQL5 中使用 SymbolInfoTick() 重新取價的想法是一致的。
Q: 回測時不會出現,但實盤卻會出現。
這是正常現象。策略測試器(Strategy Tester)並不存在(或已被簡化)「訂單傳送到伺服器的延遲」與「這段期間的價格變動」,因此 10004/10021 只會在實盤(forward)中顯現。即使回測表現良好,實盤仍需另外做好 deviation 設定、重試機制、以及執行環境(VPS)的優化。
相關文章
📧 漲價預告 + 免費5天郵件課程
所有EA目前均為首發價,並將隨銷量階梯式上調。在每次漲價前收到通知,另有每日一封郵件:自動交易本質、正確解讀回測、券商選擇技巧。
※ 嚴格保護隱私。可隨時取消訂閱。