Last Updated:

[量化實戰] 我如何把一支虧損程式,改造成 10 年大賺的策略?(打破「拉回買進」的迷思)

老兵
前言:
你是不是也聽過這句投資金句:「人棄我取,拉回就是買點」?
我曾經也是這麼想的。為了實踐這個真理,我寫了一支 Python 程式專挑「便宜貨」。
結果?在台股近年的大牛市裡,它竟然績效慘輸大盤
這篇文章記錄了我如何修正邏輯錯誤、計入真實交易成本,最終驗證出 「動能策略 (Momentum)」 才是台股獲利關鍵的完整過程。

一、 慘痛的起點:想撿便宜,卻撿到破爛

一開始,我的策略邏輯非常「散戶直覺」,我想要買在「相對低點」:

  1. 便宜才買: 等 RSI < 45(相對弱勢區)才進場。
  2. 安全第一: 股價跌破 20日均線(月線) 才接。

我以為我在等百貨公司週年慶打折,結果回測數據狠狠打了我的臉。

📉 失敗的績效表 (2023-2025 AI 牛市)

策略版本表現評語
0050 (大盤)大漲隨便買都賺
我的撿便宜策略虧損 / 小賺大盤漲我不漲,大盤跌我跟著跌

💡 為什麼會失敗?
我看著數據才發現一個殘酷真相:真正的飆股(如台積電、緯創),在主升段時 RSI 根本不會掉到 45 以下。
我的程式一直在等「回檔」,結果只撿到了那些「真的出問題」的弱勢股。

二、 觀念翻轉:加入「瘋狗流」 (Momentum)

我不甘心。我去翻了學術論文和 FinLab 的研究,發現台股有一個特性:「強者恆強」
於是我做了一個瘋狂的決定:把邏輯 180 度反過來。

💻 關鍵程式碼修改

我把「拉回買」的程式碼刪掉,改成「追高買」。請看這段關鍵的 Python 修改:

# ❌ 舊邏輯:想買便宜 (失敗)
# cond_weak = rsi_14 < 45  # 等待相對弱勢回檔

# ✅ 新邏輯:瘋狗流動能 (成功)
# 1. 營收要好 (基本面保護)
# 修正:確保使用月資料計算 YoY,並 Lag 45天避免未來視
rev_yoy = (monthly_revenue / monthly_revenue.shift(12)) - 1.0
cond_fund = rev_yoy.shift(2) > 0.25  # 確保數據已公告

# 2. 股價要創新高 (確認趨勢)
# 修正:不看月線,改看季線等級的創高
cond_strong = price >= price.rolling(60).max()

# 3. RSI 要強勢 (確認人氣)
cond_momentum = rsi_14 > 55  # 追逐動能強勢股!

這個改動違反了所有直覺:「這不是追高嗎?」
沒錯,這就叫動能交易。我把它丟進去跑了 10 年長週期回測 (2015-2025)

三、 真實回測:加入成本後的真相

為了不讓自己被「快樂表」騙了,我在回測中加入了真實世界的摩擦成本。這點非常重要,因為頻繁換股會吃掉大量獲利。

  • 交易成本設定: 單趟完整交易成本約 0.585%
    • 買進手續費:0.1425%
    • 賣出手續費:0.1425% + 證交稅 0.3%
  • 策略換股頻率: 每月檢查一次訊號 (Strategy Rotation)。
  • 數據來源: 使用還原股價 (Adjusted Close),包含股息再投入。

📊 10 年回測總體檢 (2015-2025)


▲ 圖 1:純粹動能策略 (紅線) 與 0050 (灰線) 的 10 年績效對比。紅線在 2018 與 2024 年大幅拉開差距。
比較項目0050 (含息總報酬)新策略 (純粹動能)結果
總報酬率約 350%~400%約 600% 🚀
獲利來源權值股 (台積電)中小型飆股 (國巨/緯創)抓到黑天鵝

我發現,這套策略抓到了 2018 年的被動元件狂潮,和 2023 年的 AI 狂潮。它不預測高點,它只是黏著趨勢走

四、 光鮮亮麗背後的代價:-56% 的回撤

但在你決定 All-in 之前,請先看這張「死亡清單」。
量化交易最誠實的地方,就是它會告訴你「最痛會有多痛」。

⚠️ 歷史壓力測試 (Stress Test)

年份事件0050 跌幅本策略跌幅你的帳戶 (1000萬)
2022美國暴力升息-21% (加權指數)-40%剩 600 萬
2018Q4貿易戰-15%-35%剩 650 萬
最大回撤歷史極值約 -30%-56.8% 💀剩 430 萬
💡 補充說明:為什麼空頭跌這麼慘?
動能策略在空頭市場的表現符合學術研究預期。根據《東吳會計學報》的研究指出:
「在空頭市場,不管採用何種策略投資者都會損失,動能策略的優勢在於多頭時能獲取更高獲利。」

簡單來說,這個策略的虧損是「正常特性」而非 Bug,因此我們必須搭配資產配置來降低風險。

問問你自己: 當你的 1000 萬變成 430 萬的時候,你還敢讓程式繼續跑嗎?
99% 的人會在這時候停用程式,倒在黎明前。

五、 最終解法:核心衛星配置 (Core-Satellite)

為了讓這套策略從「理論」變成「實戰」,我使用了法人級的「資產配置」技巧。我把資金分成兩份,並設定「季度再平衡 (Rebalance)」機制,避免過度交易。

  • 70% 資金 (核心):0050 (保命用,承受較低波動)。
  • 30% 資金 (衛星): 跑這套 動能策略 (衝績效用)。

🏆 季度再平衡規則

我們不頻繁調整,而是每季(3、6、9、12月底)檢查一次:

  1. 觸發條件: 當實際配置偏離目標 ±5% 時才調整。
  2. 調整方式: 賣出超配的動能股,買入落後的 0050,強制「高割離席」。

💰 投資組合最終績效


▲ 圖 2:藍線 (70/30 配置) 顯示出比紅線 (純策略) 更低的波動,但報酬率卻創下新高 (665%)。
投資方式總報酬率最大回撤 (風險)性價比 (CP值)
100% 買 0050基準-30%普通
100% 動能策略最高-57% (太危險)高風險高報酬
70% 0050 + 30% 動能優於 0050 👑-36% (可接受)最高!

✨ 結論: 透過配置,我們用「稍微多一點點的風險(-30% -> -36%)」,換取了顯著優於大盤的超額報酬,這就是資產配置的魔法。

六、 附錄:完整 Python 策略代碼 (選股邏輯)

如果你也想在自己的電腦上運行這套策略,這是核心選股邏輯的程式碼片段:

import pandas as pd
import numpy as np

# === 重要提醒 ===
# 1. calculate_rsi() 函數需自行實作或使用 TA-Lib
# 2. 月營收資料 (monthly_rev_df) 需要從 TEJ 或 FinLab 等資料庫取得
# 3. 此處僅為選股邏輯,完整回測需包含資金管理、滑價計算等框架
# ================

def strategy_logic(price_df, monthly_rev_df):
    """
    price_df: 日頻率股價
    monthly_rev_df: 月頻率營收
    """
    
    # 1. 處理營收資料 (月頻率)
    # 修正:shift(12) 針對月資料,代表與去年同期比較
    rev_yoy = (monthly_rev_df / monthly_rev_df.shift(12)) - 1.0
    
    # 修正:將月資料對齊回日資料,並 Lag 45天避免未來視
    rev_yoy_daily = rev_yoy.reindex(price_df.index, method='ffill').shift(45)
    
    # 2. 定義技術指標
    # 修正:創 60 日新高 (季線等級強勢)
    is_breakout = price_df >= price_df.rolling(60).max()
    
    # RSI 指標 (需自定義函數)
    rsi = calculate_rsi(price_df, 14)
    
    # === 選股條件 ===
    cond_fund = rev_yoy_daily > 0.25       # 基本面火藥
    cond_strong = is_breakout              # 點火
    cond_momentum = rsi > 55               # 助燃 (強勢動能)
    
    buy_signal = cond_fund & cond_strong & cond_momentum
    
    # === 排名機制 ===
    # 只買最強的 Top 5 (RSI 越高越好)
    rank = rsi.where(buy_signal).rank(axis=1, ascending=False)
    
    return rank <= 5