工程 · 2026.09.21 · 4 min · 更新於 2026.10.26
Monad 鏈上 AI 交易 bot 實盤:每 300ms 重掛單,gas 比價差大十倍
把 Monad 上的 AI 交易展示專案拿去主網實盤,量到每個 block 重掛的 gas 比能賺的價差大十倍,也修掉一個讓 83% 到 95% 掛單被退回的保證金記帳 bug。
閱讀設定
AI 交易 bot 上了 Monad 主網之後,掛出去的單大部分被鏈上 revert,失敗的交易照樣扣 gas。
原因是一個保證金記帳的 bug,它讓 83% 到 95% 的掛單被退回。修掉之後,成本結構才看得清楚:gas 是固定成本,而且比能賺到的價差大一個數量級。
bot 每個 block 重掛一次單,這樣賺不了錢。
專案是 fork 來的。原 repo 讓 TypeSafe 的 Jev 模型在每個 Monad block(約 300ms)判斷一次買或賣,bot 就在 Kuru 的 MON-USDC 訂單簿掛一張 post-only 限價單。
原作者寫明它要展示的是「AI 每 300ms 做一次真實交易決策,而且推論比 gas 便宜」,不以獲利為目標。我想知道的是它能不能賺錢。
這篇講實盤碰到的工程問題,模型有沒有預測力寫在誠實模擬盤與 AI 交易模型命中率驗證。交易用的是另外產生的 burner 錢包,私鑰不進 repo。
Monad RPC 延遲先量距離
在台灣本機跑,late 率 57.8%:超過一半的 block 模型來不及回答,那一格就不掛單。
台灣本機和美國 server 量下來的數字(p50 是中位數):
| 台灣本機 | 美國 server | |
|---|---|---|
| 到 Monad 公開 RPC 單趟 | 221ms | 17ms |
| Jev 推論 p50 | 327ms | 169ms |
| late 率 | 57.8% | 11% 到 14% |
Jev 推論 p50 差的幾乎都是跨太平洋的來回。換 RPC 供應商沒有用,問題是距離。
搬到美國之後,loop p50 186ms,塞得進一個 block。
原本考慮把 loop 改成 pipeline 讓前後 block 重疊,這下就不用做了,也省掉 nonce(錢包每筆交易的序號)撞號、部位上限被同時在飛的單突破這類實盤風險。
鏈上 bot 的延遲先量距離,換供應商、改架構之前,先確認是不是物理距離的問題。
bot 以為還有保證金
上主網之後,掛單大部分被鏈上 revert。在 Monad 上這很貴,它按 gas limit 收費,失敗的交易照樣扣 0.0436 MON。Monad 的文件寫得很直接:
The gas charged for a transaction is the gas limit.
出自 Monad 的 Gas Pricing 文件。也就是說,交易實際用了多少 gas 不影響收費。
我猜錯兩次。先以為保證金太薄,加大後 revert 只從 94.8% 降到 83.2%,錢其實是夠的。
再以為是 out of gas,因為收據的 gasUsed 等於 gasLimit,結果成功的交易也全部等於上限。收據回報的是被收走的量,要判斷 gas 夠不夠只能用 eth_estimateGas。
真正的原因在 allowed()。它用 market.margin 判斷某一側的單掛不掛得出去,但這個餘額每 200 個 block(約 60 秒)才在 refresh() 更新一次,成交時也不會動。
模型一面倒的時候,連續成交幾張買單,USDC 換成 MON,那一側的保證金就空了。
bot 手上還是一分鐘前的數字,繼續往買邊送單。每一張都因為保證金不足被退回,Kuru 在這條路徑上會收走整個 gas limit。
Kuru 是掛單當下就扣保證金,所以本地跟著訂單的生命週期記帳:送出時扣,revert、遺失或取消時還回來,成交時記入換到的另一種資產。
lockQuote(side: Side, sizeMon: number, price: number) {
if (side === "buy") this.margin.usdc -= sizeMon * price;
else this.margin.mon -= sizeMon;
}
creditFill(side: Side, sizeMon: number, price: number) {
if (side === "buy") this.margin.mon += sizeMon;
else this.margin.usdc += sizeMon * price;
}
取消也有坑。停掉 bot 時,Kuru 上的掛單不會自動撤掉,會繼續鎖住保證金;用 batchUpdate 掛的單,batchCancelOrders 撤不掉、會 revert,要改用 batchUpdate 帶取消清單。
本地鏡像總會跟鏈上有落差,所以保證金對帳從 refresh() 拆出來,每 10 個 block 跑一次,餘額的過期視窗從 60 秒縮到 3 秒。
十個 block 都沒收到收據的單可能其實有上鏈,我選擇先樂觀釋放,由下一次對帳修正。
這段 dry run 驗不到,沒有錢包時 allowed() 直接回 true。只能靠單元測試重現「連續三張買單成交後,USDC 不夠掛第四張」,再上實盤確認。
定期刷新的餘額,在連續成交的系統裡一定會過期。跟著訂單的生命週期在本地記帳,再用短週期對帳收斂。

gas 比價差大十倍
修復後 revert 降到 11.1%,但 50.7% 的 block 沒掛單。這次卡在我針對「模型一直買」調緊的部位上限。
模型翻成 99% 想賣,兩筆成交就撞上限,買邊又因為 USDC 先前被花光掛不出去。參數是針對當下行情調的,模型一翻面就可能變成新的瓶頸。
放寬之後,沒掛單的 block 降到 0%,revert 33.1%。
剩下的 revert 按買賣邊、部位大小等拆開看,都落在 30% 到 38%。我推測是 post-only 的時序競爭:價格用 block N 的簿子算,單子到 N+1 才上鏈。這點沒有驗證。
bug 修完,成本結構才看得清楚。385 筆成交的實測:每筆成交理論上最多賺 $0.0006,攤到每筆的 gas 是 $0.0063,差了十倍。平均 5.7 次掛單才換到一筆成交。
gas 每小時 $11 到 13。每個 block 掛一張單就是每小時約 12,000 筆交易,這筆錢不管有沒有成交都要付。
要打平,得把單量放大到約 2,000 MON 一張,前提還是模型真的有預測力。
原作者那句話倒是成立:Jev 的推論費用大約只有 gas 的十六分之一。AI 確實比 gas 便宜,只是兩個加起來都比賺到的多。

保證金的修復我開了 PR 給原作者(jev-trader#4),寫這篇時還在等回覆。

投資
裸K交易法有用嗎?1026 檔台股規則回測,樣本外輸給隨機進場
把一位 YouTube 創作者的裸K交易法寫成規則,用一千多檔台股日線回測,跟只打散進場時點的隨機對照組比,樣本外輸給隨機 2.62 個標準差。
留言
載入留言中…