
把一支寫得很粗的台股動能策略交給 OpenAI Codex,迭代兩輪會走到哪裡?我們做了一個完整實驗:先用最直覺的寫法做一支「多週期動能、等權買前 20 名」的策略,naive 版本年化 16.2%、最大回撤吃到 -53.0%。第一輪請 Codex 重構工程:向量化、抽參數、加成本壓力測試與前視檢查,並補上「低波排名 + 收盤站上 200 日均線」兩道控制,回撤收到 -35.7%,但年化、日夏普、月索提諾、最大回撤四項主要指標仍然全輸 0050 含息。第二輪把這個結論原樣丟回給 Codex,請它從設計層再改一次,得到「多週期動能+ROE 品質+雙倍低波+波動率倒數加權」的推薦版:年化 18.4%、最大回撤 -30.2%、年化波動 16.0%,最大回撤與年化波動兩項優於 0050 含息。
侷限也要一開始就講清楚:兩輪迭代之後,這支策略的年化報酬(18.4% 對 25.0%)與日夏普(1.18 對 1.22)仍然輸給被動持有的 0050 含息。它換到的是被動持有給不到的東西:更淺的最大回撤(-30.2% 對 -34.0%)與明顯更低的年化波動(16.0% 對 20.8%)。2022 年空頭 0050 從高點跌掉 34.0% 的同一天,這支策略只回落 14.7%。
| 指標 | naive 多週期動能 | 第一輪重構 | 第二輪推薦版(本文採用) | 0050 含息 |
|---|---|---|---|---|
| 年化報酬(CAGR) | 16.2% | 17.1% | 18.4% | 25.0% |
| 最大回撤(MDD) | -53.0% | -35.7% | -30.2% | -34.0% |
| 年化波動 | 38.0% | 23.0% | 16.0% | 20.8% |
| 日夏普比率 | 0.60 | 0.83 | 1.18 | 1.22 |
| 月索提諾比率 | 1.25 | 1.54 | 1.84 | 1.92 |
| 總報酬 | +251% | +274% | +311% | +559% |
| 平均持股 | 20 檔 | 20 檔 | 20 檔 | 1 檔 ETF |
年化波動:日報酬標準差換算成年的波動幅度,數字越低,淨值曲線越平穩。
口徑:2018-01 到 2026-06-09,三支策略含 finlab 預設交易成本,0050 為還原價含息買進持有,純指數算術不扣成本(詳見文末回測方法)。第二輪推薦版贏 0050 的是最大回撤(-30.2% 對 -34.0%)與年化波動(16.0% 對 20.8%)兩項;年化報酬、日夏普與月索提諾仍然落後。換句話說,這支策略適合把「跌得淺、走得穩」看得比「賺得多」重的人,追求絕對報酬的人直接買 0050 更簡單。
整個過程你不需要自己重構程式:把粗略的策略邏輯、既有程式碼、以及「要贏過 0050 哪幾項」的目標用中文描述給 Codex,由它負責向量化、抽參數、加壓力測試、查前視、跑設計變體,數據則由 finlab 套件實跑。下面公開招牌提示詞、兩輪迭代的核心程式碼、全部設計變體的實跑數據,以及可下載的完整重現腳本。
Codex 是什麼?它強在程式工程,不是預測股價
OpenAI Codex 是 OpenAI 推出的程式工程代理,有命令列版(Codex CLI)與桌面版(Codex app)。它的強項是「把程式碼寫對、寫乾淨」這件事:重構雜亂的腳本、把迴圈向量化成 pandas 運算、依 AGENTS.md 規格約束行為、用 work-tree 並行嘗試多個版本、做 code review,以及揪出量化研究裡最常見的兩個地雷:前視偏差(look-ahead)與被低估的交易成本。
這正好對上量化回測的痛點。一支策略寫不對,數字再漂亮都是假的:因子用了當下還拿不到的財報、成本沒扣足、迴圈寫錯一格,回測就會虛高。Codex 不會幫你預測明天哪支股票漲,但它會幫你確認「這個回測的數字是不是真的算對了」。想先補齊量化研究的整體脈絡,可以讀量化交易完整指南再回來看實作;想理解回測本身在驗證什麼,回測是什麼有完整說明。
把 Codex 用在 finlab 台股回測上,和把它當聊天機器人問「給我一支會賺的策略」是兩回事:
| 用法 | 當聊天機器人問明牌 | 當程式工程代理 |
|---|---|---|
| 任務性質 | 要它「報」一個會漲的股票或參數 | 要它把既有策略重構、向量化、補控制 |
| 數據來源 | 可能憑記憶生成看似合理的數字 | 數字來自 finlab 實跑的回測輸出 |
| 可驗證性 | 你無法檢查它怎麼算的 | 它附上完整程式碼,你能重跑對照 |
| 對前視偏差 | 通常不會主動檢查 | 可請它逐因子查資料可得時點與公布日對齊 |
最後一列是 Codex 在量化研究裡最被低估的價值。多數人做回測栽在未來函數而不自知,因為錯誤藏在資料對齊的細節裡;請 Codex 專門掃一遍,比自己肉眼讀程式可靠得多。
把 FinLab 裝進 Codex:一份 SKILL.md,到處能用
要讓 Codex 能讀台股資料、跑含成本的回測,先給它 FinLab 的能力。FinLab Skill 是一份 SKILL.md,同一份能裝進 Codex CLI、Claude Code、Cursor、Pi、Hermes 等支援 Agent Skills 的工具,裝一次到處能用。安裝指令所有工具通用:
npx skills add https://github.com/koreal6803/finlab-ai --skill finlab
如果你還在用網頁版 ChatGPT,建議改用 Codex app 的桌面版,它能實際執行程式、跑回測、把結果交給你驗證,網頁聊天做不到這些。完全不想安裝任何東西,也有零設定的瀏覽器版:打開 FinLab Studio 輸入選股條件就能產生回測。設定流程用下面這句話帶 Codex 一步完成:
用 AI 開始 FinLab
把這句話交給你的AI,它會帶你完成設定並做出第一個策略。
告訴你的AI:
幫我設定 FinLab,用 Codex 重構並回測一支多週期動能策略,請讀:https://finlab.finance/setup?relatedUrl=/blog/codex-finlab-quant-backtest
首次取資料時,finlab 套件會自動引導你登入,照套件指示操作即可,程式裡只要寫 finlab.login() 不帶參數。想看更完整的 AI 代理量化流程,AI 量化交易實戰指南用三段對話示範了從篩選法到排名法的演進。
起點:一支粗略的多週期動能策略
先看我們交給 Codex 的原始策略。它的想法很單純:股價在過去 60 天、120 天、240 天三個週期都漲得多的股票,動能強,每月選這類股票的前 20 名等權買入。這是教科書級的橫斷面動能,Jegadeesh & Titman (1993) 早就證明過去數月的贏家股票在後續數月平均會持續跑贏輸家,動能因子也成為實證金融最廣被複製的異常報酬之一。
問題不在因子本身,而在這支策略只有「進攻」沒有「防守」。多頭時它跟著動能衝得很順,但 2020 年疫情急殺與 2022 年升息修正這兩段,動能因子整批回吐,naive 版本的最大回撤吃到 -53.0%,幾乎腰斬。年化 16.2% 也低於同期被動持有 0050 含息的 25.0%,承受了更深的回撤卻沒有換到更高的報酬。
回撤的形狀比一個數字更說明問題。把 naive 版本與兩輪迭代版本、0050 的回撤曲線疊在一起看,naive 那條線幾乎全程壓在最下方:2020 年 3 月 19 日探到 -53.0%(同日第一輪重構版 -35.7%、第二輪推薦版 -30.2%、0050 -28.2%),2022 年 7 月又再探 -46.2%。2022 年全年最深回撤的對照更懸殊:0050 -34.0%、第一輪 -33.2%,第二輪推薦版只有 -14.7%:

第一輪迭代:把粗略策略交給 Codex 重構
我們把這支 naive 策略連同它的問題,整段交給 Codex,請它重構成一個乾淨、可重跑、含成本壓力與前視檢查的模組,全程不自己動手改程式。第一段提示詞如下,可以直接複製:
顯示程式碼
這是一支多週期動能的 finlab 策略,請幫我重構成可重跑的模組:
向量化、把參數(動能週期、持股數、權重)抽成設定,
加上手續費與證交稅加倍的壓力測試,
並印出每個版本的夏普與最大回撤。
我擔心它在大跌時回撤太深,請評估能不能加上控制下檔風險的濾網。💬 你對 Codex 說:
這是一支多週期動能的 finlab 策略,請幫我重構成可重跑的模組:向量化、把參數抽成設定、加上手續費與證交稅加倍的壓力測試,並印出每個版本的夏普與最大回撤。它在 2020、2022 大跌時回撤接近腰斬,有沒有辦法在不大改報酬的前提下把回撤收斂?
🤖 Codex 回覆:
已重構成參數化模組,並跑了三個版本對照。原始多週期動能在全段是年化 16.2%、最大回撤 -53.0%。回撤集中在 2020、2022 兩段系統性下跌,純動能在這種環境保護不了你。我加了兩道控制:
- 趨勢過濾:只持有收盤價站上 200 日均線的股票,市場結構轉空時自動減少曝險。
- 低波排名:在動能分數之外,把「過去 60 日報酬波動度低」也納入綜合分數,避免一路追進最瘋狂、最容易反轉的標的。
重構後年化 17.1%、最大回撤收斂到 -35.7%,月索提諾從 1.25 升到 1.54。另外要提醒兩件事:第一,手續費與證交稅加倍的壓力測試下,年化從 17.1% 掉到 11.9%,這支策略每月換股、周轉偏高,對交易成本相當敏感,實單的手續費折讓與下單方式會實質影響績效;第二,它在年化與日夏普上仍輸給被動持有的 0050,改善主要在下檔風險。
這就是 Codex 的工程價值具體長什麼樣子。它沒有承諾更高的報酬,而是先把問題定位在「回撤集中在兩段系統性下跌」,再對症下藥補了兩道有學理依據的控制:趨勢過濾對應 Moskowitz, Ooi & Pedersen (2012) 的時間序列動能與趨勢過濾(用自身價格趨勢決定曝險,能壓低空頭段的回撤),低波控制對應 Ang, Hodrick, Xing & Zhang (2006) 記錄的低波動異常(高特異波動股票的後續報酬反而偏低)。
Codex 重構後的核心程式碼如下。它把原本糊在一起的邏輯拆成「載入資料 → 趨勢與流動性過濾 → 算多週期動能與低波 → 排名加權 → 回測」幾段,每一段都能對應到上面的對話:
顯示程式碼
import finlab
from finlab import data
from finlab.backtest import sim
finlab.login()
# 1) 載入資料(首次執行會自動引導登入)
close = data.get("price:收盤價")
volume = data.get("price:成交股數")
# 2) 流動性過濾 + 趨勢過濾(只在多頭結構中持有)
amount = (close * volume).rolling(20).mean()
moving_average_200 = close.rolling(200).mean()
tradable = (amount > 10_000_000) & close.notna() & (close > moving_average_200)
# 3) 多週期動能(短中長)+ 低波控制
momentum_short = close.pct_change(60)
momentum_mid = close.pct_change(120)
momentum_long = close.pct_change(240)
volatility = close.pct_change().rolling(60).std()
rank_short = momentum_short.where(tradable).rank(axis=1, pct=True)
rank_mid = momentum_mid.where(tradable).rank(axis=1, pct=True)
rank_long = momentum_long.where(tradable).rank(axis=1, pct=True)
rank_low_vol = volatility.where(tradable).rank(axis=1, pct=True, ascending=False)
score = rank_short + rank_mid + rank_long + rank_low_vol
# 4) 取前 20 名,分數平方加權,每月再平衡
top20 = score.rank(axis=1, ascending=False) <= 20
weight = (score[top20].fillna(0)) ** 2
weight = weight.div(weight.sum(axis=1), axis=0)
report = sim(weight, resample="M", name="多週期動能低波控制")
report.display()值得注意的兩個工程細節。第一,tradable 同時把流動性、可交易與 200 日均線濾網寫進一個布林矩陣,後面所有排名都先 .where(tradable),確保不在條件外的股票被排進來;這種把過濾前置的寫法,是 Codex 重構時最常做的整理。第二,低波那行用 ascending=False 讓「波動越低排名越高」,方向一旦寫反,整個策略就會去追最瘋狂的股票,這也是人工容易看走眼、適合交給代理檢查的地方。
第一輪重構後的年化報酬 17.1%(總報酬 +274%),naive 版本 16.2%(+251%),0050 含息 +559%。工程問題解決了,但把它與 0050 放進同一張對照表,年化、日夏普、月索提諾、最大回撤四項主要指標還是全輸。這個結論成了第二輪迭代的起點;在改設計之前,還有一道必要的檢查:確認這個回測本身沒有作弊。
第二段提示詞:請 Codex 檢查前視偏差
策略寫得乾淨還不夠,量化回測最致命的錯誤是用到「當下還拿不到」的資料,讓回測虛高、實單卻重現不了。這類錯誤藏在資料對齊的細節裡,肉眼很難掃乾淨,正是 Codex 的守備範圍。第二段招牌提示詞專門做這件事:
顯示程式碼
幫我檢查這段 finlab 回測有沒有用到未來資料(look-ahead):
每個因子是不是用「當下可得」的資料、財報有沒有對齊公布日。
請逐個因子列出它依賴的欄位、資料頻率,以及在每個再平衡日是否已經可得。🤖 Codex 回覆(節錄):
逐因子檢查結果如下:
- 三個動能因子(60/120/240 日報酬):只用
price:收盤價的過去報酬,每個再平衡日都是已實現的歷史價格,沒有用到未來資料。- 低波因子:用過去 60 日報酬的滾動標準差,同樣只依賴歷史價格,安全。
- 200 日均線:
close.rolling(200).mean()是落後指標,當日均線只用到當日與之前的收盤,沒有前視問題。- 流動性過濾:近 20 日成交金額滾動平均,落後,安全。
這支策略全部因子都只用價量資料,沒有牽涉季財報或月營收,所以不存在「財報公布日對齊」的風險。如果之後要加入基本面因子,務必對季財報用
index_str_to_date()對齊公布時點、月營收ffill到日頻,否則就會用到當下還沒公布的數字。
這一輪檢查的結論是這支策略乾淨,但更重要的是它示範了「該怎麼查」。純價量策略的前視風險低,真正容易出事的是混入財報的策略;想看財報與月營收因子怎麼對齊公布日才不會作弊,AI 選股提示詞與真實回測裡有完整的對齊做法可參考。
第三段提示詞:把「贏過 0050」訂成第二輪迭代的目標
第一輪重構把策略寫對了,也把它「四項主要指標全輸 0050」的事實攤開了。第二輪迭代的提示詞就從這個事實出發,把目標與界線都講明白:
顯示程式碼
這一版四項主要指標全輸給 0050 含息(年化 17.1% 對 25.0%、日夏普 0.83 對 1.22、
月索提諾 1.54 對 1.92、最大回撤 -35.7% 對 -34.0%)。
請從設計層改進,不要調參數硬湊:可以考慮把低波因子的權重加大、
改用波動率倒數決定持股權重、加入獲利品質因子。
每一個試過的設計都要完整回報指標,不要只給我最好的那一個。🤖 Codex 回覆(節錄):
我實跑了五個設計變體,視窗與成本設定不變,全部結果如下:
設計 年化報酬 日夏普 月索提諾 年化波動 最大回撤 A 低波權重加倍 15.9% 1.02 1.76 16.4% -28.9% B 改波動率倒數加權 17.1% 0.88 1.71 21.1% -33.8% C 加 ROE 品質(低波權重不變) 21.8% 0.90 1.70 26.8% -49.4% D 品質+雙倍低波+波動率倒數加權(採用) 18.4% 1.18 1.84 16.0% -30.2% E 同 D,持股放寬到前 30 18.6% 1.22 1.76 15.5% -29.7% 建議採用 D,它把三個改動疊在一起:ROE 品質因子拉高報酬、低波權重加倍看住品質因子帶進來的波動、波動率倒數加權讓資金自然偏向平穩的持股。C 是最好的反面教材:只加品質因子而不同步加強低波控制,報酬雖然升到 21.8%,最大回撤卻惡化到 -49.4%,幾乎退回 naive 版的水準。E 的日夏普 1.22 與 0050 打平,但持股 30 檔的操作負擔更高,換到的改善不多。另外,ROE 是季頻財報資料,我已依公布時點對齊後才向後填值到日頻,就是上一輪前視檢查裡提醒過的做法。
五個變體全部列出來,是為了讓「為什麼選 D」有依據可查:A 證明單靠加重低波會犧牲太多報酬,B 證明只改加權方式力道不夠,C 證明品質因子單獨上陣會放大回撤,D 是三個改動互相補位的結果。獲利品質因子的學理依據來自 Novy-Marx (2013) 記錄的獲利能力溢酬:獲利能力較高的公司,後續平均報酬也較高。他用的指標是毛利對資產比,本文以 ROE 作為獲利品質的替代衡量,方向一致但非同一口徑。
第二輪推薦版的核心程式碼如下,與第一輪的差異集中在三行:ROE 排名加入綜合分數、低波排名乘以 2、持股權重改用波動率倒數:
顯示程式碼
import finlab
from finlab import data
from finlab.backtest import sim
finlab.login()
# 1) 載入資料(首次執行會自動引導登入)
close = data.get("price:收盤價")
volume = data.get("price:成交股數")
# ROE 是季頻財報,先對齊公布日再向後填值,避免用到還沒公布的數字
roe = data.get("fundamental_features:ROE稅後").index_str_to_date()
roe = roe.reindex(close.index, method="ffill")
# 2) 流動性過濾 + 趨勢過濾(只在多頭結構中持有)
amount = (close * volume).rolling(20).mean()
moving_average_200 = close.rolling(200).mean()
liquid = (amount > 10_000_000) & close.notna()
tradable = liquid & (close > moving_average_200)
# 3) 因子:多週期動能 + 低波動(權重加倍) + ROE 獲利品質
momentum_short = close.pct_change(60)
momentum_mid = close.pct_change(120)
momentum_long = close.pct_change(240)
volatility = close.pct_change().rolling(60).std()
rank_short = momentum_short.where(liquid).rank(axis=1, pct=True)
rank_mid = momentum_mid.where(liquid).rank(axis=1, pct=True)
rank_long = momentum_long.where(liquid).rank(axis=1, pct=True)
rank_low_vol = volatility.where(liquid).rank(axis=1, pct=True, ascending=False)
rank_quality = roe.where(liquid).rank(axis=1, pct=True)
score = rank_short + rank_mid + rank_long + 2 * rank_low_vol + rank_quality
# 4) 取前 20 名,改用波動率倒數加權,每月再平衡
top20 = score.where(tradable).rank(axis=1, ascending=False) <= 20
weight = (1 / volatility).where(top20, 0)
weight = weight.div(weight.sum(axis=1), axis=0)
report = sim(weight, resample="M", name="多週期動能+品質+雙倍低波")
report.display()第二輪推薦版全段年化報酬 18.4%(總報酬 +311%)、最大回撤 -30.2%、年化波動 16.0%、月索提諾 1.84。對照 0050 含息的 -34.0% 與 20.8%,這一版在最大回撤與年化波動兩項優於被動持有;年化報酬(18.4% 對 25.0%)、日夏普(1.18 對 1.22)與月索提諾(1.84 對 1.92)仍然落後。完整互動式回測報告可以直接在這裡操作:
把四個版本的風險報酬放在同一張圖上,兩輪迭代各自的貢獻就分開了:第一輪把 naive 的極端回撤收掉,第二輪才把回撤與波動壓到 0050 之下:

兩段空頭的表現並不對稱。推薦版的最大回撤 -30.2% 發生在 2020 年 3 月疫情急殺(同日 0050 -28.2%),那是一場所有股票一起跌的流動性危機,趨勢過濾來不及反應;低波與趨勢控制真正發揮的是 2022 年那種歷時一年的緩跌空頭,0050 全年最深 -34.0%,推薦版只有 -14.7%。
第四段提示詞:持股數敏感度掃描
前 20 名是個拍腦袋訂的數字,會不會剛好挑到一個漂亮參數?第四段提示詞請 Codex 把推薦版的持股數掃一遍,證明結論對它不敏感:
顯示程式碼
把推薦版的持股數 15、20、30 三種設定做敏感度掃描,
輸出一張對照表(CAGR、日夏普、月索提諾、年化波動、最大回撤),
其他設定維持不變。Codex 真跑了三組,結果如下:

| 持股數設定 | 年化報酬 | 日夏普 | 月索提諾 | 年化波動 | 最大回撤 |
|---|---|---|---|---|---|
| 前 15 | 17.2% | 1.10 | 1.87 | 16.2% | -29.5% |
| 前 20(本文採用) | 18.4% | 1.18 | 1.84 | 16.0% | -30.2% |
| 前 30 | 18.6% | 1.22 | 1.76 | 15.5% | -29.7% |
三組的年化報酬落在 17.2% 到 18.6% 之間,月索提諾在 1.76 到 1.87 之間,最大回撤都在 -30% 上下。更重要的是,三組的最大回撤與年化波動全部低於 0050 含息的 -34.0% 與 20.8%,代表「回撤與波動優於 0050」這個核心結論不是靠剛好挑到前 20 這個數字撐出來的。本文採用前 20 是取報酬與集中度的折衷;前 30 的日夏普 1.22 與 0050 打平、波動最低,偏好更分散的讀者可以自行改參數重跑。敏感度掃描的正確用法是確認結論穩健,不是回頭挑數字最漂亮的那一格。
回測方法與限制
這些數字是怎麼算出來的,逐項交代:
| 項目 | 本文設定 |
|---|---|
| 回測區間 | 2018-01 到 2026-06,共 8.4 年(資料快照日 2026-06-09) |
| 交易成本 | finlab sim() 台股預設值:手續費 0.1425%(未打折)、賣出證交稅 0.3%,已內扣;成本加倍(手續費 0.285%、證交稅 0.6%)壓力測試實跑結果:推薦版年化由 18.4% 降至 13.4%、月索提諾由 1.84 降至 1.39,中高周轉策略對成本敏感,實單的手續費折讓會實質影響績效(第一輪與 naive 版的壓力測試見 metrics.json 的 stress_test) |
| 滑價 | 未另行假設;實際衝擊取決於資金規模與個股成交量,本文未估算策略容量 |
| 股票池 | 全上市櫃,finlab 資料含已下市股票,無生存者偏誤;未刻意排除金融股與 KY 股;ETF 因無動能以外的選股結構自然較少入選 |
| 流動性過濾 | 近 20 日平均成交金額大於 1,000 萬 |
| 前視偏差 | 動能、波動度、200 日均線、成交金額均為已實現價量的落後指標;ROE 為季頻財報,以 index_str_to_date() 對齊公布時點後才向後填值到日頻,經 Codex 逐因子檢查無未來函數;本策略未使用月營收 |
| 權重 | 取綜合分數前 20 名後以 60 日波動率倒數加權,每月再平衡(第一輪為分數平方加權、naive 基準為等權) |
| 周轉率 | 多週期動能加趨勢過濾屬中高周轉,換股成本已反映在績效中;本文未估算容量上限 |
| 樣本內外 | 全段樣本內(in-sample),未做樣本外測試;設計變體與持股數敏感度是穩健性參考,不是樣本外證據 |
| 0050 基準 | etl:adj_close 還原價含息買進持有,純指數算術、不含交易成本;基準不扣成本而策略扣,比較口徑對策略偏保守。2018-01 到 2026-06 窗口 0050 年化 25.0%、日夏普 1.22、月索提諾 1.92、年化波動 20.8%、最大回撤 -34.0% |
兩輪迭代之後:贏在回撤與波動,輸在報酬與夏普
把帳算清楚。在本文設定、2018–2026 這段期間,第二輪推薦版對 0050 含息的勝負是:最大回撤贏(-30.2% 對 -34.0%)、年化波動贏(16.0% 對 20.8%);年化報酬輸(18.4% 對 25.0%)、日夏普輸(1.18 對 1.22)、月索提諾輸(1.84 對 1.92)。後三項的差距比第一輪(0.83 對 1.22)小了很多,但沒有翻盤。
這個帳本身就是有用的資訊。第一輪證明工程紀律能把 -53.0% 的極端回撤收掉,卻改不了「全面落後被動持有」的格局;第二輪證明設計層的改動(品質因子、低波權重、加權方式)能換到兩項真實的優勢,代價是報酬上限仍然被防守型持股壓著。要不要用這支策略,取決於你怎麼定價「跌得淺、走得穩」:願意用 -34% 回撤換 25% 年化的人,0050 仍是更好的答案;曾經在大跌時砍在低點的人,2022 年空頭裡 -14.7% 對 -34.0% 的回撤差異可能比帳面報酬更值錢。想看單因子在台股普遍跑不贏 0050、要靠分散的多因子才有機會的更完整實測,多因子選股能不能贏 0050有另一組獨立驗證。
適合誰、不適合誰
適合: 已經有一支「能跑但寫得粗」的 finlab 策略,想把它整理成可重跑、可維護、無前視偏差的模組;或想替既有策略加上回撤控制與成本壓力測試,但不確定濾網該怎麼寫、寫得對不對。Codex 在「重構與檢查既有程式碼」這件事上最強。
不適合: 期待把策略丟給 Codex 就生出一支穩贏大盤的策略。Codex 不會憑空變出 alpha,市場上原本不存在的超額報酬,它也生不出來。它能保證的是「你的回測算對了」,不是「你的策略會賺」。
和一般看盤、下單軟體的差別也在這裡:那類工具偏條件篩選與即時報價,回測能力有限、也很難客製成本與前視檢查;用 Codex 加 finlab 的組合,你能用中文描述需求,由代理產生可驗證、可下載、含台股交易成本的回測程式。市面上六種主流台股回測軟體的完整比較,見台股回測工具怎麼選。判斷一篇 AI 量化內容可不可信,可參考AI 量化交易詐騙怎麼辨識裡的檢查點。
常見問題
Codex 和 ChatGPT 網頁版做量化回測差在哪?
差在「能不能實際執行程式」。ChatGPT 網頁版只能用語言生成看似合理的程式碼或數字,無法跑回測、也無法驗證;Codex(CLI 或 app)是程式工程代理,能實際執行你的 finlab 腳本、跑出含成本的回測、把程式碼與結果交給你重跑對照。做量化研究務必用能執行的版本,否則拿到的可能是憑記憶生成的假數字。
Codex 真的能找出回測裡的未來函數嗎?
能,但前提是你要它做。前視偏差通常藏在資料對齊的細節:用了當下還沒公布的財報、因子計算窗口框到未來。請 Codex 逐因子列出依賴的欄位、資料頻率、以及在每個再平衡日是否已可得,比自己肉眼讀程式可靠得多。本文第一輪的純價量因子經檢查無未來函數;第二輪加入的 ROE 屬季頻財報,用 index_str_to_date() 對齊公布時點後才進因子,混入財報或月營收的策略最需要這道檢查。
策略年化還是輸 0050,為什麼值得用?
因為它提供被動持有拿不到的兩樣東西:最大回撤 -30.2% 淺於 0050 的 -34.0%,年化波動 16.0% 低於 0050 的 20.8%,2022 年空頭全年最深只回落 14.7%(0050 -34.0%)。回撤深的部位多數人撐不過第一次大跌就砍在低點,反而拿不到帳面上的年化報酬;淨值曲線越平穩,紀律越容易維持。反過來說,若你確定自己能忍受 -34% 的回撤,直接買 0050 的 25.0% 年化更簡單,這也是本文據實列出所有輸掉指標的原因。
第二輪迭代會不會只是過擬合?
風險存在,但有幾道防線可以檢查。第一,兩輪改動都在設計層(加因子、改加權方式),提示詞明確要求不做參數搜尋;第二,五個設計變體全部公開實跑結果,包含表現最差的 C(回撤 -49.4%),不是只呈現最好的那個;第三,持股數 15、20、30 三組的回撤與波動全部優於 0050,核心結論對參數不敏感。即便如此,全段仍是樣本內回測,過擬合風險無法完全排除,我們每季會用新資料重跑並據實更新。
不會寫 Python 也能用 Codex 重構策略嗎?
可以。你用中文描述需求(向量化、抽參數、加壓力測試、查前視偏差),程式由 Codex 產生。不過看得懂基本程式對你有利,因為你能檢查它有沒有把濾網方向寫反、成本有沒有扣。想補底子,Python 量化交易教學會帶你從設定一路到第一個台股回測。
Codex 重構後的策略可以馬上拿去下單嗎?
不建議。本文是全段樣本內回測,推薦版最大回撤 -30.2% 代表 100 萬可能一度縮水至約 70 萬。比較穩健的順序是:回測驗證、用小部位手動跟單數月、確認實際成交與回測差距可接受,再考慮自動化。把研究結果直接接券商 API 前,還要處理部位控管、錯單保護與盤中流動性,這些不是回測報酬率能回答的問題。延伸閱讀程式交易是什麼。
這支策略未來還會有效嗎?
沒有人能保證。本文是 8.4 年的全段樣本內回測,歷史優勢可能因市場結構改變或因子擁擠而衰減。我們能做的是每季用新資料重跑、數據惡化就如實更新。讀者自己驗證最新數據的方法:跑一次文末的重現腳本,幾分鐘就有答案。
需要多少資金才能開始?
學習與回測完全免費,不需要投入資金。實際執行面,這個策略持有 20 檔,考慮台股以張為單位(零股交易亦可),數十萬以上比較能貼近配置;持股由動能、低波與品質排名篩出,其中不乏中小型股,資金規模大到單筆買賣影響股價時,回測與實單的差距會擴大。
下載與重現
- strategy.py:第二輪推薦版的完整策略原始碼,可直接執行取得最新選股清單
- data.csv:0050 與 naive、第一輪、第二輪推薦版四條淨值曲線的每日數據
- metrics.json:全部指標的機器可讀快照,含五個設計變體與成本加倍壓力測試
- 互動式回測報告:第二輪推薦版完整報告
投資警語:本文僅供教學參考,不構成投資建議。文中全部回測數據(第二輪推薦版年化 18.4%、最大回撤 -30.2%,第一輪 -35.7%,naive 版 -53.0% 等)為 2018-01 至 2026-06 的歷史模擬,已含 finlab 預設交易成本,但未含滑價與容量限制;過去績效不代表未來表現。本策略最大回撤約三成,代表 100 萬可能一度縮水至約 70 萬,請依個人風險承受度審慎評估,僅使用虧損不影響生活的閒置資金。
最後更新:2026-07|回測區間:2018-01 ~ 2026-06(資料快照 2026-06-09)|作者:FinLab 量化研究團隊(經量化研究員審閱)
FinLab AI
想建立自己的策略?
用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案
免費開始

