AI 寫程式的 7 個坑:我用 Claude Code 寫自動交易程式,真實修過的 bug
我那隻自動下單機器人正式上線前,我叫 Claude 先做一次「真的下單、但故意不讓它成交」的測試:掛一張價格很低的買單,等它逾時,再看程式會不會自己撤單。
結果撤單判斷完全沒作用。
程式沒有報錯、沒有當掉,log 看起來也很正常。問題出在一行字串比對:券商回傳的狀態是 "OrderStatus.Cancelled",程式卻在比對 "Cancelled"。如果沒有這一次測試,它上線後就會把「已撤單」當成「還在等」,帳本跟實際狀態從此對不起來。
這讓我開始認真整理:用 AI 寫交易程式這段時間,到底修過哪些 bug?整理完發現一件事:
這些 bug 一個都沒有讓程式當掉。它們全部都「跑得好好的」,只是給你錯的答案。
這篇把 7 個真實修過的 bug 攤開來講,每一個都附上症狀、原因、怎麼發現的:
- 為什麼 AI 寫的交易程式特別危險
- 資料層:API 筆數上限,多天只拿到第一天
- 回測層:換月價格還原,造出假獲利
- 設定層:設成 0 想關掉功能,結果 0 被當成門檻
- 監控層:盤中量縮永遠成立
- 下單層:訂單狀態字串前綴,撤單判斷失效
- 下單層:槓桿上限只看保證金,會一路買到 7 倍
- 下單層:轉倉順序寫反
- 這些 bug 的共通點,以及我現在怎麼防
關於作者:我是工程師阿穆,寫程式十多年,這幾年在做 AI Agent 與自動化系統。本文的 bug 全部來自我用 Claude Code 寫的台股/期貨交易程式的 git 紀錄,是真實修過的問題。 免責:本文是工程經驗分享,不是投資建議。文中不會公開我的實盤本金、報酬與參數設定。
為什麼 AI 寫的交易程式特別危險?
AI 寫程式最大的風險,不是寫出跑不動的程式,而是寫出「能跑、看起來合理、但結果是錯的」程式。 語法錯誤會當掉,你馬上就知道;邏輯或假設錯誤不會當掉,它只會安靜地給你錯的數字。
一般的程式,錯的數字頂多讓報表難看。交易程式不一樣:
- 回測的錯誤,會讓你對一個爛策略充滿信心
- 監控的錯誤,會讓你在錯的時機收到訊號
- 下單的錯誤,直接就是真錢
我用 Claude Code 寫這整套系統(FinMind 抓資料、選股盯盤、網格回測、自動下單),寫程式的速度快到不可思議,但下面這 7 個 bug,每一個都是「AI 寫得很快、我也差點就信了」的例子。
資料層
1. API 筆數上限:多天範圍只拿到第一天
症狀: 我叫程式補抓好幾天的全市場股價,它跑完說成功,但只有第一天的資料是完整的。
原因: FinMind 的全市場資料,一天大約就有 46,000 筆,會碰到 API 單次回傳的上限。程式用「起訖日期」一次查好幾天,API 就只回傳塞得下的部分,而且不會報錯。
怎麼修: 改成逐天呼叫,一天一個請求。
教訓: AI 會照著 API 文件寫出「看起來正確」的呼叫方式,但外部服務的隱藏限制(筆數上限、頻率限制、分頁)文件不一定寫清楚。抓完資料一定要檢查「筆數對不對、日期有沒有缺」,不要只看有沒有報錯。
回測層
2. 換月價格還原,造出假獲利
症狀: 期貨網格的回測,在每個月換月的那幾天,常常出現漂亮的獲利。
原因: 期貨每個月到期,回測要把不同月份的合約接成一條連續價格。常見做法是「比例還原」,把換月當天新舊合約之間的價格跳空抹平。
問題是,這個做法連同那天晚上真實發生的漲跌也一起抹掉了。回測裡的部位「沒吃到」隔夜的下跌,卻吃到了隔天的反彈,憑空多出一筆獲利。
怎麼修: 改用原始近月價格做回測,讓留倉部位真實承受換月時的價差,跟實盤程式讀到的價格一致。比例還原只留著當對照組。
教訓: 回測最可怕的 bug,是讓結果變好看的 bug。結果變差你會去查,結果變好你只會開心。這也是我在網格交易回測那篇強調的:結果好到不真實的時候,先懷疑程式。
設定層
3. 設成 0 想關掉功能,結果 0 被當成門檻
症狀: 網格提醒程式有一個「槓桿太高就提醒我減碼」的功能。我想在另一檔商品上關掉它,就把減碼門檻設成 0。結果正好相反:只要價格一反彈,它就叫我減碼。
原因: 程式的判斷是「目前槓桿 > 減碼門檻」。我心裡想的是「0 = 關閉」,但程式只看到一個數字 0,任何有部位的狀態,槓桿都大於 0,條件永遠成立。
# 修改前:0 被當成門檻
if lev > c["derisk_lev"] and is_up and s["lots"]:
# 修改後:0 或沒設定,才是真的關閉
if c.get("derisk_lev") and lev > c["derisk_lev"] and is_up and s["lots"]:
教訓: 「0 代表關閉」是人的直覺,不是程式的。每一個設定值,都要說清楚「關閉」要怎麼表達,最好在 instruction 檔裡寫明,不然 AI 只會照字面處理。
監控層
4. 盤中量縮判斷,幾乎永遠成立
症狀: 盤中監控程式的「量縮」條件,在早上幾乎每一檔都成立,讓這個條件完全失去篩選作用。
原因: 程式拿「今天到目前為止的累積成交量」去跟「過去平均的全天成交量」比。早上 11 點,交易時間才過了不到一半,累積量本來就會比全天平均少很多,當然「量縮」。
怎麼修: 門檻依盤中已經過了多少交易時間等比例調整。如果只過了 45% 的時間,門檻也只用 45%。另外顯示「預估全天量」(目前累積量 ÷ 已過時間比例)給我參考。
教訓: 回測用的是收盤後的完整日 K,盤中監控用的是「還沒結束的一天」。同一個條件,在回測和盤中的意義可能完全不同。 AI 很容易把回測的邏輯直接搬到盤中,而沒想到資料本身的性質變了。
下單層
5. 訂單狀態字串有前綴,撤單判斷失效
就是開頭那個 bug。實際的修改只有一行:
st = str(trade.status.status) # 實際值長這樣:"OrderStatus.Cancelled"
# 修改前:完全比對,永遠不會成立
if st in ("Cancelled", "Failed", "Inactive"):
# 修改後:子字串比對
if any(x in st for x in ("Cancelled", "Failed", "Inactive")):
有趣的是,同一個函式裡判斷「成交」的那一行,本來就是用子字串比對,所以成交沒問題,只有撤單漏掉。同一段程式碼裡,兩種寫法混在一起,這種不一致很難一眼看出來。
怎麼發現: 正式上線前的「監督式真實下單測試」:在真實環境掛一張不會成交的限價單,看完整的「下單 → 逾時 → 撤單」流程有沒有走通。
教訓: 模擬環境測得過,不代表真實環境的回傳格式一模一樣。跟錢有關的流程,上線前一定要用最小部位在真實環境走一次。
6. 槓桿上限只看保證金,會一路買到 7 倍
症狀: 這是我遇過最嚴重的一個,我在 commit message 裡直接寫了「修真錢安全漏洞」。
原因: 下單前的檢查只看「可用保證金夠不夠」。保證金夠,就買。但小型台積電期貨的保證金只有 13.5%,只看保證金的話,程式會一路買到保證金用光,大約 7 倍槓桿,遠遠超過我設定的槓桿上限。設定檔裡明明有槓桿上限這個欄位,下單邏輯卻根本沒去讀它。
怎麼修: 下單前多一道檢查:買進後的部位總價值,不能超過「真實帳戶權益 × 槓桿上限」。而且用的是向券商查到的真實權益,不是設定檔裡寫的本金,這樣入金或出金之後,上限會自動跟著調整。
教訓: 「設定檔裡有這個欄位」不等於「程式有在用這個欄位」。每一個安全限制,都要實際驗證它真的會擋下來。 我後來是用不同的帳戶權益去測,確認上限到了就真的會擋。槓桿開太大會發生什麼事,可以看同一個策略開 1、2、3 倍的回測。
7. 轉倉順序寫反
症狀: 轉倉日的時候,程式會把一口「已經到停利點、本來就要賣掉」的部位,也花錢轉到下個月。
原因: 程式先做轉倉,轉完才判斷停利。順序反了,就會多花一次轉倉成本去搬一個馬上要賣的部位。
怎麼修: 轉倉日先做停利掃描,到停利點的部位正常賣出;剩下的才轉倉;如果停利後已經空手,就直接切到下個月,不用轉。轉倉是什麼,可以看個股期貨入門。
教訓: 這個 bug 不會讓你虧大錢,但它是典型的「每一步都對,順序錯了」。AI 很擅長把每個步驟寫對,步驟之間的順序和交互作用,要靠人去想。
番外:顯示的數字跟實際設定不一樣
還有一個小 bug:Telegram 通知裡的格距和停利,用百分比顯示時被四捨五入到整數,實際設定是一個數字,通知上顯示的是另一個。不影響下單,但如果我根據通知去判斷「現在設定對不對」,就會被誤導。修法是顯示到小數點後一位。
這些 bug 有什麼共通點?
回頭看這 7 個 bug:
| # | Bug | 有報錯嗎 | 錯在哪 |
|---|---|---|---|
| 1 | API 筆數上限 | ❌ | 外部服務的隱藏限制 |
| 2 | 換月價格還原 | ❌ | 資料處理的隱含假設 |
| 3 | 設成 0 想關閉 | ❌ | 設定值的語意 |
| 4 | 盤中量縮 | ❌ | 回測和盤中的資料性質不同 |
| 5 | 狀態字串前綴 | ❌ | 外部 API 的實際回傳格式 |
| 6 | 槓桿上限 | ❌ | 安全限制沒有真的被執行 |
| 7 | 轉倉順序 | ❌ | 步驟之間的順序 |
沒有一個會報錯,沒有一個是語法問題。 全部都是「程式照著某個假設正確執行,但那個假設是錯的」。
而這些假設,大多跟外部世界有關:API 會回傳什麼、資料是怎麼產生的、盤中跟收盤有什麼不同、券商的字串長怎樣。這正好是 AI 最容易猜錯的地方,因為它沒有真的跑過、看過。
我現在怎麼防?
1. 跟錢有關的,一定要在真實環境用最小部位走一次
模擬環境和真實環境的行為不一定一樣。第 5 個 bug 就是這樣抓到的。
2. 對「好到不真實」的結果起疑
回測結果突然變好,先別開心,先問 Claude:「這個結果有沒有可能是程式的問題?列出可能讓結果被高估的原因。」第 2 個 bug 就是這種。
3. 叫 AI 列出它的假設
寫完一段程式,我會問:
「這段程式做了哪些關於外部資料、API 回傳格式、時間的假設?哪些假設如果不成立,程式不會報錯但結果會錯?」
這個問題很好用,AI 自己寫的時候不一定會想到,但叫它回頭檢查的時候,常常就列出來了。
4. 安全限制要實際測「會不會擋」
不要只看程式碼裡有沒有那一行,要實際製造一個「應該被擋」的情境,看它真的會擋。第 6 個 bug 就是因為這樣才確認修好了。
5. 讓程式自己對帳
我的下單程式每一輪都先跟券商對帳:本地帳本說有幾口、券商說有幾口,對不上就停機。這是在承認「程式一定會有我沒想到的 bug」的前提下,讓 bug 發生時能被立刻發現,而不是累積下去。完整的安全設計在自動下單機器人的 9 道安全機制。
6. 每個修正都寫清楚「為什麼」,並寫進規則
每次修 bug,我都讓 Claude 在 commit message 寫清楚原因(這篇的素材就是從 git 紀錄整理出來的)。重要的規則,例如「帳本不能用券商均價取代」,我會寫進專案的 instruction 檔,下次新的對話就不會再犯同樣的錯。怎麼寫 instruction 可以看 Agent Instruction:怎麼寫 AI Agent 的「憲法」。
常見問題
AI 寫的程式可以直接用嗎?
可以跑,不代表可以用。AI 寫的程式語法錯誤很少,但對外部世界的假設常常是錯的,而且這類錯誤不會報錯。一般的小工具影響不大;跟錢、跟真實資料有關的程式,一定要自己驗證過。
Vibe Coding 的缺點是什麼?
最大的缺點是你不知道程式做了哪些假設。Vibe Coding 讓你用對話就能做出能跑的東西,但如果你完全不看程式在做什麼,就沒辦法發現那些「能跑但錯」的問題。我的建議是:可以不自己寫,但要看得懂它在做什麼。延伸閱讀:Vibe Coding 做網頁完整實戰。
怎麼檢查 AI 寫的程式有沒有錯?
我常用的四招:叫 AI 列出它的假設、用真實資料抽查結果、刻意製造邊界情況(例如應該被擋下的情境)、讓程式自己做一致性檢查(例如對帳)。
回測結果很好,可以相信嗎?
先懷疑。回測最常見的問題包括:沒算交易成本、資料處理讓結果變好看(例如這篇第 2 個 bug)、報酬的分母算錯(例如有補保證金卻沒算進本金)、參數剛好擬合了歷史(過度擬合)。結果越好,越要回頭檢查。
用 AI 寫交易程式,最重要的一件事是什麼?
假設程式一定有你沒發現的 bug,然後設計讓 bug 發生時能被發現、不會擴大的機制。 對帳、硬上限、出錯就停機,都是基於這個前提。
結語
用 Claude Code 寫交易程式,速度真的快到不可思議,我幾乎沒有自己寫程式碼。但這 7 個 bug 讓我很清楚一件事:AI 幫你把「寫」這件事變快了,但「確認它是對的」這件事,還是得你來做。
它們沒有一個會報錯,也沒有一個是 AI「不會寫程式」造成的。它們都是因為 AI 沒看過真實世界長什麼樣子。所以我的角色從「寫程式的人」變成了「問對問題、驗證假設的人」,這也是我在 AI 時代,軟體工程師怎麼辦? 裡想講的事。希望這些坑你不用再踩一次~
如果你想學怎麼用 AI 從研究、回測一路做到自動下單,還有怎麼把這些坑提前擋掉,我正在把整套做法整理成一門課,想搶先知道開課消息的話,加我的 LINE 跟我說一聲「交易課」就好~
延伸閱讀(AI 自動交易系列):
- 用 Claude Code + Shioaji 打造自動下單機器人:我的台積電期貨網格實戰
- 網格交易回測:用台積電 6 年資料實測,99% 的月份有收入,卻輸給買進持有
- 個股期貨是什麼?小型台積電期貨的保證金、轉倉、槓桿
- 期貨槓桿開幾倍才安全?同一個策略開 1、2、3 倍回測
喜歡這篇文章嗎?
📧 訂閱 Newsletter — 新文章直接寄到你信箱 🎬 追蹤我的 YouTube — 看 AI / 工具實作影片 💬 加我的 LINE — 想上交易課、或有問題隨時問我 🧵 追蹤 Threads — 平常的工程隨筆
掰掰~👋