交易所整合

Binance CM-UM 架構整合 dualSidePosition:-4531 完整處理指南

2026-08-24·10 分鐘閱讀

你的策略跑了半年沒事,2026-06-30 之後 dualSidePosition 某一次 切換突然被 webhook(也就是 TradingView 把訊號自動送到你伺服器的那條通道) 拒絕,回傳 {"code":-4531,"msg":"Position mode change requires syncing UM and CM..."}—— 訊息叫你先關掉 CM 裡的持倉或掛單。但你明明沒在做幣本位。 原因是 Binance CM-UM 架構整合 dualSidePosition 這件事在 06-30 全面生效了。

沒有人先跟你講的是:Binance 從 2026-06-30 開始把 COIN-M(CM / DAPI, 也就是幣本位合約的 REST 前綴)併進 USDⓈ-M(UM / FAPI,U 本位那條) 的統一架構,dualSidePosition 現在整個帳戶只有一份, 改 UM 那邊會同步改 CM,反之亦然。你以為的「切 UM 的 mode」現在會 去檢查 CM 那邊有沒有卡什麼——只要有,整個請求就被 -4531 擋回來。

這篇不整理整份整合公告,那份公告有 A / B / C / D 四大節、講給不同 endpoint 使用者聽。這篇只講一件事:切 position mode 這個動作,現在會撞到什麼、 你要怎麼繞開——以及一個很多人沒注意到的細節:-4531是 Binance 官方明說的暫時性錯誤,但那不代表你現在可以忽略它。

2026-06-30
UM 與 CM dualSidePosition 共用全面生效日
-4531
CM 端同步失敗時擋下 UM 請求的新錯誤碼
≈ 1 個月
官方預估 -4531 存續期間,CM 進 Guard 後消失
先講結論
三件事,順序不能顛倒。第一,-4531 現在會撞、CM 進 Guard 後不會再撞, 但這中間你留在 CM 的孤兒訂單/持倉會擋掉你所有改 mode 的請求。 第二,直接寫死「重試幾次就會過」是錯的——沒清乾淨的話, 等到天荒地老也不會過。第三,2026-06-29 09:00 UTC 之後, COIN-M 的 auto-cancel countdown 已經暫停,靠它做保護的策略在維護視窗內 是完全沒防護的。

整合了什麼——你只需要記住一個字:共用

Binance 官方在 2026-06-10 發出 「Important CM-UM Integration Notice」(查證日期 2026 年 7 月),公告的第一段就把整件事的性質講清楚: COIN-M 被併進 USDⓈ-M 共用的統一架構,多個 REST endpoint、 WebSocket 串流、以及帳戶層級的行為,全部對齊 USDⓈ-M 的既有慣例。這不是新增功能,是把兩邊的行為抹平成一致。

抹平的方式是漸進的——公告本身注明「Individual changes may be enabled at different times after the initial effective date」——完整生效的日期 是 2026-06-30。所以如果你的 bot 在 06-30 之前跑得好好的、06-30 之後 開始出現以前沒看過的行為,那大概率就是整合的哪一環在你這裡生效了。

整合涉及的具體項目有一大堆(下單 ack 拿掉 avgPricecumQuote、CM 的 stop-type 要改走新的/dapi/v1/algoOrder、rate limit 併池、STP 統一走 UM 設定), 但對「有 webhook 在改 position mode 的人」來說,影響最直接、最容易安靜地壞掉的就是 dualSidePosition。 下面這張表把整合前後的差別攤開來看。

整合之前2026-06-30 之後
dualSidePositionUM 一份、CM 一份,互不干擾UM 與 CM 共用一份,一次改兩邊
切 mode 需要清乾淨的範圍只要清 UM 那邊UM 與 CM 兩邊都要清乾淨
擋你的錯誤碼-4067-4068多一個 -4531(同步 CM 失敗時觸發)
COIN-M auto-cancel countdown正常運作2026-06-29 09:00 UTC 起暫停,CM 恢復後才回來

來源:Binance Important CM-UM Integration Notice(2026-06-10 發布)與 Binance USDⓈ-M / COIN-M Futures API change-log(查證日期 2026 年 7 月)。

所以這一關不要靠自己猜。去 dashboard 或 API——也就是你程式碼跟交易所直接對話的那條通道——對 CM 帳戶查一次有沒有持倉與掛單,沒有就沒事, 有就要先清。清的邏輯在下面「切 mode 前你要先確認哪三件事」那節。

-4531 到底在拒絕什麼——它跟 -4067/-4068 不一樣

Binance 官方在 2026-05-11 的 change-log 條目裡加了這個錯誤碼 (Effective Date 2026-05-13),完整原文寫得很直白:

官方 change-log 原文
「New error code -4531: When changing UMdualSidePosition, the system will automatically sync CM dualSidePosition. If the CM account has any open position or open order, the sync cannot proceed and the UM position mode change will be rejected with error code -4531.」
(查證日期 2026 年 7 月;來源:Binance USDⓈ-M Futures API change-log 2026-05-11 條目。)

翻成人話:你打的是 UM 那邊的 endpoint,但 Binance 內部會替你去改 CM 的dualSidePosition——這個「替你改」的動作如果失敗, 原本你發起的那筆 UM 請求就整個被回退,回傳 -4531失敗的地方不在你這邊,在 Binance 內部同步的那一步。

這跟你熟悉的 -4067-4068 差在哪?差在它們指的是同一件事在不同地方發生。舊的兩個講的是 你這邊(UM 帳戶)有掛單/有持倉;-4531 講的是 另一邊(CM 帳戶)有掛單/有持倉。訊息本身不會告訴你是 CM 的哪個 symbol 卡住——你得自己去 CM 那邊查。

錯誤碼在哪裡卡住怎麼清
-4067UM 有 open ordersDELETE /fapi/v1/allOpenOrders 或逐 symbol 撤
-4068UM 有 open positionreduce-only market 單平倉,或 dashboard 手動平
-4531CM 有 open orders 或 open position(同步失敗)先打 DELETE /dapi/v1/allOpenOrders,再平 CM 持倉

三個「不能改 mode」的錯誤碼對照。來源:Binance USDⓈ-M Futures API change-log(查證日期 2026 年 7 月)。

還有一個維護視窗期間的暫時錯誤要順帶一提——如果你的請求剛好落在 Binance 為了 CM 遷移做維護的時段,你會拿到 -1016「This service is no longer available.」)或-1109「Invalid account.」)。那不是你的 參數有問題,是 Binance 剛好在動裡面的東西——這種錯不應該立刻重試, 等維護結束再來。

1
切 mode 時拿到的錯誤碼是哪一個?
-4531CM 那邊有 open orders 或 open position。先打DELETE /dapi/v1/allOpenOrders、再平 CM 持倉, 然後重試。
-4067-4068UM 這邊有 open orders 或 open position。照傳統流程清乾淨 再切——這條在整合之後仍然存在。
-1016-1109Binance 正在維護裡面東西。指數退避(30 秒起跳、加倍到 5 分鐘), 不要立刻重試;重試也是白扣 rate limit。

官方明說 -4531 是暫時的——但你不能就這樣等

同一則 change-log 條目在最下面補了一段 Note,這一段常常被跳過, 但它決定了你的錯誤處理邏輯要怎麼寫:

官方文件講到哪裡為止
「Note: This error code is temporary and will only be active until CM enters Guard (approximately 1 month). After CM enters Guard, this error will no longer occur.」
(來源同上。)值得注意的是,Binance USDⓈ-M 錯誤碼參考頁面 (developers.binance.com/en/docs/products/derivatives-trading-usds-futures/error-code, 2026-07-30 更新)到查證當下依然沒有收錄 -4531—— 這跟 Note 講的「暫時性」互相印證:Binance 認為它不會活到進永久錯誤碼表。

但你要小心兩件事。第一,「approximately 1 month」沒有明說是從 哪天開始算的——是從 05-13 生效那天,還是從 06-30 全面生效那天? 官方沒說。實務上請把它當成「至少一個月、可能更久」,不要押寶哪天會結束。

第二,即使它結束了,-4067-4068不會結束——UM 那邊有掛單/持倉還是會擋你改 mode,那是常態行為。 所以就算未來哪天你不再看到 -4531,你的錯誤處理邏輯 仍然要能處理「切 mode 之前要先清乾淨」這件事——只是清的範圍 從 UM+CM 縮回 UM 而已。

所以你該做什麼?不要寫「碰到 -4531 就等一小時再重試」 這種邏輯。要寫「碰到 -4531 就去查 CM 有沒有東西,有就清、 清完再重試;沒有就報警找人來看」。這個差別聽起來很小, 但它決定了你的策略是在自動恢復還是安靜地壞掉。

切 mode 前你要先確認哪三件事

Binance 官方公告在 A.1 節底部有一句 「Action required」「before flipping dualSidePosition, ensure both UM and CM have no open orders and no open positions.」翻成你可以照做的動作,就是下面這張 checklist。

  • UM 沒有 open orders。GET /fapi/v1/openOrders,回傳陣列必須是空的。 有就先 DELETE /fapi/v1/allOpenOrders——每個 symbol 分開撤,或用不帶 symbol 的版本一次撤全部。
  • UM 沒有 open positions。GET /fapi/v2/positionRisk,每一筆的positionAmt 必須是 0。有非 0 的就送 reduce-only market 單平倉,或去 dashboard 手動平。
  • CM 也要做上面兩件事。對應的 endpoint 是GET /dapi/v1/openOrdersGET /dapi/v1/positionRisk。這一步在 2026-06-30 之前不需要,之後每次都要——而且忘了做的時候,Binance 給你的錯誤 是 -4531,不是任何跟 UM 有關的字眼。

check 完之後也不能立刻 flip——中間可能有別的程式在下單。檢查與切換之間要保持原子性:把整段包成一個 mutex, 或至少在切之前再 double check 一次 open orders/positions。 切完再 GET /fapi/v1/positionSide/dual 確認新的值 真的生效了——別假設 200 回來就代表成功。

順帶提醒:這一切都預設你的 API(也就是你程式跟交易所講話的那條通道) key 有 futures 交易權限、也有正確的 IP 白名單設定,否則會撞到跟-4531 完全無關但看起來很像的 -2015(invalid API-key)。 API key 該怎麼設,Binance API Key 安全設定 那篇有完整檢查清單。

那個被大家忽略的地雷——COIN-M countdown 已暫停

如果你的架構有用到 POST /dapi/v1/countdownCancelAll(COIN-M 的 auto-cancel all open orders / countdown)做「webhook 掛了就 自動撤單」的斷線保護,2026-06-29 的 change-log 有一則你需要看:

官方 change-log 原文
「The COIN-M countdown (auto-cancel) feature will be suspended on 2026-06-29 at 09:00 UTC (17:00 UTC+8) for the CM migration maintenance, and will be restored after CM resumes.」
「Any countdown set before the suspension remains effective in the matching engine up until the snapshot is taken at maintenance shutdown. If the countdown timer set by the user is scheduled to fire after the maintenance snapshot, the countdown for those symbols will not take effect.」
(來源:Binance COIN-M Futures API change-log 2026-06-29 條目, 查證日期 2026 年 7 月。)

白話說:你設在維護開始之後才會觸發的 countdown,不會生效。Binance 沒承諾恢復時間,也沒承諾恢復之後行為完全一樣——公告只講到 「will be restored after CM resumes」,一個很誠實但也很不確定的說法。

USDⓈ-M 那邊的 POST /fapi/v1/countdownCancelAll 沒有受這條 影響,可以繼續用。所以如果你原本靠 COIN-M countdown 做保護、 現在還在等它回來——先確認你的策略在這段空窗期有沒有其他斷線防護, 比如伺服器端的 watchdog、或直接改走 UM 的 countdown(如果你交易的合約 是永續而不是幣本位交割合約,這個切換值得考慮)。更完整的斷線失效 設計思路,可以看 TradingView 或交易所當機時你的自動化策略會發生什麼事 那篇。

把上面所有東西寫成一段可以貼進 CI 的檢查

你不需要真的把邏輯寫在策略程式碼裡——那太脆弱、也太難測。把它拆成「切 mode 的守門函式」與「錯誤碼路由表」, 在真的要改 mode 之前呼叫一次。先看守門函式:它去問 UM 或 CM 任一側, 有沒有掛單或持倉,有就先撤或叫上層來平。

python
# pseudocode。錯誤處理、簽章、rate limit 都省略了;上線前請補齊。

        def ensure_side_clean(client, prefix):
            """prefix 是 '/fapi/v1'(UM)或 '/dapi/v1'(CM)。"""
            orders = client.get(f"{prefix}/openOrders")
            if orders:
                client.delete(f"{prefix}/allOpenOrders")

            positions = client.get(f"{prefix}/positionRisk")
            non_flat = [p for p in positions if float(p["positionAmt"]) != 0]
            if non_flat:
                # 這一步不自動平——不同策略的平倉時機不同
                raise NotFlatError(side=prefix, positions=non_flat)

            return True

接著是錯誤碼路由表——這才是這一節的重點。 不同 code 用不同重試策略:-4531-4067-4068 是「有東西沒清」的訊號,重試前必須真的去清;-1016 是「Binance 正在動」的訊號,退避一下再來; 其他 code 就是未知,該報警找人。

python
def flip_dual_side_position(client, target: bool):
            ensure_side_clean(client, "/fapi/v1")   # UM
            ensure_side_clean(client, "/dapi/v1")   # CM,2026-06-30 之後必查

            resp = client.post(
                "/fapi/v1/positionSide/dual",
                params={"dualSidePosition": target},
            )

            if resp.status_code != 200:
                code = resp.json().get("code")
                # 錯誤碼路由表——不要每個都用同樣的重試策略
                if code == -4531:
                    raise CmSyncFailed()          # 上次 check 到 flip 之間有東西冒出來
                if code in (-4067, -4068):
                    raise UmNotFlat()
                if code == -1016:
                    raise ServiceUnavailable(retry_after=300)   # 維護中,指數退避
                raise UnknownError(code=code)

            # 別假設 200 就成功——回頭確認一次
            current = client.get("/fapi/v1/positionSide/dual")
            assert current["dualSidePosition"] == target

誠實的一段:這篇沒實測 -4531

我們沒有替這篇文章實際觸發過 -4531——一來這個錯誤只在 特定條件下(帳戶同時有 UM 與 CM 活動、且中間有孤兒訂單/持倉) 才會出現,二來我們也不會為了寫文章刻意在生產環境重現它。這篇的所有時間點、error payload、觸發條件,都是直接引自 Binance 官方 change-log 與整合公告,不是實測結果。

另一個保留是關於「approximately 1 month」——我們沒有內線知道 CM 進 Guard 的確切日期。這個推論靠的是官方在 change-log 上寫的字面。你部署到生產環境 之前,建議自己再去 developers.binance.com 的 change-log 與錯誤碼參考頁核對一次日期,尤其是 -4531有沒有從錯誤碼表消失——那是 CM 進 Guard 最直接的信號。

常見問題

我根本沒在做幣本位,為什麼會撞到 CM 相關的錯誤?
因為 2026-06-30 之後,UM 與 CM 共用一份dualSidePosition。你改 UM 那邊,Binance 內部 會自動替你去改 CM 那邊。如果你的帳戶很久以前有做過 COIN-M 留下一張沒撤的單、或一個沒平的部位,就會撞到-4531。查一次 CM 帳戶就知道。
-4531 什麼時候會完全消失?
官方講的是 「approximately 1 month until CM enters Guard」, 沒有具體日期。實務上請把它當成長期會存在——即使有一天消失了,-4067-4068 還會擋你, 所以「切 mode 前要清乾淨」這個邏輯永遠不會過時。
POST /dapi/v1/positionSide/dual 現在還能用嗎?
能用,但它跟 POST /fapi/v1/positionSide/dual現在是同一件事——打哪一個都會同時改 UM 與 CM。 Binance 沒有把 dapi 這個 endpoint 拿掉,但你不用刻意用它, 用 fapi 那個效果一樣。
維護視窗那段時間拿到 -1016 或 -1109,我是不是要立刻重試?
不要。-1016-1109 都是 Binance 正在動裡面東西的訊號,立刻重試等於在 rate limit 上白白扣點數。 建議用指數退避(30 秒起跳,每次加倍到 5 分鐘為上限), 或直接等下個小時再試——維護通常有固定的窗口。
我可以直接把整個帳戶切成 Hedge Mode 然後就別再切了嗎?
可以。dualSidePosition 一次設好之後不需要頻繁改—— 真的需要頻繁切換 One-way 與 Hedge 的策略非常少。整合的影響 主要落在要改的那個瞬間;你只要一輩子只切一次, 之後就跟你無關了。

Get started

想把今天學到的東西自動化跑起來?

把切 position mode、清 open orders、路由不同錯誤碼這些邏輯搬進 TVSBot 的執行端——用你自己的 API key,先 dry-run,帳戶層級風控自己設。

免費開始使用