aroon 阿隆指標在台股怎麼用:震盪選股,配上宇宙內的 aroon 廣度減碼
aroon 最常見的教法是「AroonUp 上穿 AroonDown 就買」。我們把這個用法和幾種變體放進台股 2015 到 2026 年 9 月的真實回測,再把首發版(2026 年 6 月)的完整策略用新資料重跑一次,結果整理在下表:
執行這個策略
複製提示詞,讓 AI 依照上方證據的資料、條件與風險檢查重跑一次。
告訴你的AI:
幫我設定 FinLab,重現這篇文章,請讀:https://finlab.finance/setup?relatedUrl=/blog/aroon-indicator-taiwan
| 你想知道的 | 回測的回答 |
|---|---|
| aroon 阿隆指標是什麼 | Tushar Chande 提出的趨勢計時器,量的是「距離上次創新高、新低過了幾天」,跟漲跌幅度無關 |
| 黃金交叉買進有效嗎 | 近 20 個交易日內剛黃金交叉的股票全部買進,研究段(2015–2021)年化 1.3%、2022 年起 11.5%,兩段都輸含息 0050 的 15.1%、30.5% |
| 震盪能拿來選股嗎 | 單用震盪最高 30 檔,研究段 12.7%、2022 年起 18.1%,同樣輸 0050;集中到最高 10 檔,全期年化 25.3% 但月夏普 0.94、最大回撤 -46.1%,再加持續性濾網、反波動加權與廣度減碼,月夏普才超過 0050(1.11 對 1.07) |
| 完整策略效果 | 2015-01-30 到 2026-09-30 年化 25.2%、月夏普 1.11,勝含息 0050 的 21.2%、1.07;2022 年起年化 24.7%,落後 0050 的 30.5% |
| 最大的風險 | 換股日從月底挪到每月 5~25 日,全期年化只剩 11.4%~22.5%;名次同分時換一種排序規則,2022 年起月夏普掉到 0.85~0.94;首發後到 2026-09-30 策略跌 10.9%,同期 0050 漲 8.9% |

本文數字出自 finlab 套件(2.2.21)抓取的上市櫃真實價量資料,回測自策略第一個淨值日 2015-01-30 起到 2026-09-30,基準為含息 0050(
etl:adj_close還原價、純算術買進持有、同一天起算)。首發版資料截至 2026-06-09,這次把資料延長到 2026-09-30,策略參數維持首發設定。文末附可下載的strategy.py與data.csv。對回測的觀念還不熟,可先看回測是什麼。
aroon 阿隆指標是什麼
aroon 阿隆指標是技術分析師 Tushar Chande 在 1995 年提出的趨勢指標,名字源自梵文「黎明前的曙光」。它跟大多數指標最不一樣的地方,在於它量的是「距離上次創新高、新低過了幾天」,跟漲跌幅度無關,本質上是一個趨勢的計時器。技術指標的基礎名詞可參考名詞詞彙表。
aroon 由兩條 0 到 100 的線組成:
AroonUp:(timeperiod − 期間內最高價距今天數)/ timeperiod × 100。越接近 100,代表最近才剛創新高,上升趨勢很「新鮮」。
AroonDown:(timeperiod − 期間內最低價距今天數)/ timeperiod × 100。越接近 100,代表最近才剛創新低。
Aroon 震盪(oscillator):AroonUp − AroonDown,範圍 −100 到 +100,越高代表上升趨勢越領先。
中文教學裡 aroon 幾乎只被當成「兩條線交叉」的進出場訊號:AroonUp 上穿 AroonDown 就買、下穿就賣。下面先在單一個股上看這兩種常見用法長什麼樣子,再用全市場回測檢查它們有沒有賺到錢。
aroon 阿隆指標的數學定義
設 timeperiod 為 ,AroonUp 與 AroonDown 的定義是:
震盪則是兩者相減:
逐個符號拆開來看:
- 是回看窗格。本文的教科書用法與單股示意用 25 個交易日,完整策略用 20 個交易日。 越大越偏中長期趨勢,越小越敏感也越多雜訊。
- 「自 期最高點以來天數」是從今天往回數,最近一次 日新高發生在幾天前。今天剛創新高時這個天數是 0,代入後 ;最高點落在窗格最左端時天數是 ,。AroonDown 對最低點同理。
- 兩條線都被鎖在 0 到 100 之間,震盪落在 到 。
兩個實務上會碰到的性質:
- 震盪只有少數幾個值。 因為天數是整數, 時兩條線都是 5 的倍數,震盪只有 41 種取值。拿它排名選股,同分的股票很多,同分怎麼排會直接改變選到哪幾檔,後面有一整段實測。
- 除權息會製造假新低。 finlab 的
data.indicator("AROON")預設用未還原的最高價、最低價。除息日股價往下跳,可能讓個股出現一個假的 日新低,AroonDown 跳到 100。台股 7、8 月除權息旺季,宇宙內每天平均有 4.2 檔、2.5 檔股票出現這種只在未還原價才有的新低。
單股示意圖:兩個派別的買賣點
把 aroon 畫到單一個股上最清楚。下圖是台積電(2330)2023-08 到 2024-06 的日線,下半部是 AroonUp(25)、AroonDown(25)與震盪三條線,價格面板標出兩個教科書派別的買賣點:
- 交叉派:AroonUp 上穿 AroonDown 進場、跌破出場(三角形)。
- 震盪派:震盪升破 50 進場、跌破 0 出場(圓點與叉號)。

同一段、同一套參數換到聯發科(2454):

這 11 個月(222 個交易日)裡,台積電交叉派買 4 次、賣 3 次,震盪派買 6 次、賣 3 次;聯發科交叉派買 4 次、賣 3 次,震盪派買 5 次、賣 3 次。兩派有好幾次在同一天出手,所以圖上部分記號疊在一起。這段兩檔分別漲了 70.4%、96.4%,算是很順的上升趨勢,兩派還是各自進出了七到九次;台積電在 2023 年 9、10 月於 520 到 560 元附近橫盤,交叉派 9 月 8 日買進、9 月 21 日就賣出,10 月 26 日再買回來。逐檔照訊號進出,每一次都要付手續費與證交稅。
畫圖的程式如下(判斷穿越時要用完整歷史的前一天,先切期間再判斷,期間第一天會被誤判成訊號):
顯示程式碼
import matplotlib.pyplot as plt
import finlab
from finlab import data
# finlab 會在需要資料時自動引導登入
finlab.login()
# 載入收盤價與 Aroon(25):data.indicator 回傳 AroonDown 與 AroonUp 兩個 DataFrame
close = data.get("price:收盤價")
aroon_down, aroon_up = data.indicator("AROON", timeperiod=25)
oscillator = aroon_up - aroon_down
sid = "2330"
window = slice("2023-08-01", "2024-06-30")
up, down, osc = aroon_up[sid], aroon_down[sid], oscillator[sid]
def turns_true(condition):
"""條件由 False 變 True 的那一天(用完整歷史判斷,再切出想看的期間)。"""
condition = condition.fillna(False).astype(bool)
previous = condition.shift(1, fill_value=False).astype(bool)
return (condition & ~previous).loc[window]
cross_buy = turns_true(up > down) # 交叉派:AroonUp 上穿 AroonDown
cross_sell = turns_true(up < down) # 交叉派:AroonUp 跌破 AroonDown
osc_buy = turns_true(osc > 50) # 震盪派:震盪升破 50
osc_sell = turns_true(osc < 0) # 震盪派:震盪跌破 0
price = close[sid].loc[window]
print("交叉派 買", int(cross_buy.sum()), "賣", int(cross_sell.sum()),
"| 震盪派 買", int(osc_buy.sum()), "賣", int(osc_sell.sum()))
# 上半部畫股價並標買賣點、下半部畫 aroon 三條線
fig, (ax_price, ax_aroon) = plt.subplots(2, 1, figsize=(12, 7), sharex=True)
ax_price.plot(price.index, price, color="black", label=sid)
ax_price.scatter(price[cross_buy].index, price[cross_buy], marker="^", label="交叉派買進")
ax_price.scatter(price[cross_sell].index, price[cross_sell], marker="v", label="交叉派賣出")
ax_price.scatter(price[osc_buy].index, price[osc_buy], marker="o", label="震盪派買進")
ax_price.scatter(price[osc_sell].index, price[osc_sell], marker="x", label="震盪派賣出")
ax_price.legend()
ax_aroon.plot(up.loc[window].index, up.loc[window], label="AroonUp(25)")
ax_aroon.plot(down.loc[window].index, down.loc[window], label="AroonDown(25)")
ax_aroon.plot(osc.loc[window].index, osc.loc[window], label="震盪(Up−Down)")
ax_aroon.axhline(50, linestyle="--")
ax_aroon.axhline(0, linestyle="--")
ax_aroon.legend()
plt.show()台積電這段會印出「交叉派 買 4 賣 3 | 震盪派 買 6 賣 3」。
黃金交叉在台股:近 20 日剛交叉的股票,研究段年化只有 1.3%
單股看不出輸贏,我們把幾種常見用法放到可交易宇宙裡回測:60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 名,排除 ETF、金融保險股、處置與全額交割股。全部用 Aroon(25)、等權、每月最後一個交易日換股、不擇時、扣手續費(打三折)與證交稅:
| aroon 用法 | 研究段年化 | 研究段月夏普 | 2022 年起年化 | 全期最大回撤 | 月底持股檔數(中位) |
|---|---|---|---|---|---|
| 震盪最高 30 檔 | 12.7% | 0.67 | 18.1% | -45.0% | 30 |
| AroonUp 在 AroonDown 上方的全部股票 | 11.9% | 0.60 | 16.7% | -41.7% | 119 |
| 近 20 個交易日內剛黃金交叉、月底仍在上方 | 1.3% | 0.17 | 11.5% | -46.2% | 51 |
| 月底當天剛黃金交叉 | -3.3% | -0.02 | 3.5% | -77.1% | 3 |
| 震盪最低 30 檔(等反彈) | 0.1% | 0.12 | 15.4% | -48.2% | 30 |
| 含息 0050 | 15.1% | 1.00 | 30.5% | -34.0% |

這張表有三個重點:
一、剛交叉的那一刻反而最差。 同樣是 AroonUp 在上方的股票,全部持有研究段 11.9%;只挑最近 20 天才剛穿越的股票(月底中位數 51 檔),研究段掉到 1.3%。只買月底當天剛交叉的股票,中位數只有 3 檔、141 個月裡有 14 個月一檔都沒有,全期最大回撤 -77.1%。把交叉當買點,買到的是剛脫離下跌、還沒走出趨勢的股票。
二、五種裸用法兩段都輸 0050。 表現最好的「震盪最高 30 檔」,研究段 12.7% 低於 0050 的 15.1%,2022 年起 18.1% 也遠低於 30.5%。
三、低震盪股在 2022 年後沒有一直落後。 震盪最低 30 檔研究段只有 0.1%,2022 年起卻有 15.4%,跟最高 30 檔的 18.1% 相差不多。下一段的五分位會看得更清楚。
2026 年 6 月首發版的這張表有一列「黃金交叉持有」,程式實際上是「AroonUp 在上方的股票中震盪最高 30 檔」。震盪最高的 30 檔幾乎都已經 AroonUp 在上方,141 個月裡有 136 個月跟「震盪最高 30 檔」是同一籃,所以兩列數字幾乎相同,量不到穿越時點的效果;這次改成真的看穿越日。延伸閱讀:技術面與基本面選股的差異、動能策略。
震盪當選股因子:研究段排得出高低,2022 年起排不出來
把可交易宇宙依 Aroon(25) 震盪由低到高切成五等分,各組等權、月換股、扣成本:
| 分位(震盪由低到高) | 研究段年化 | 研究段月夏普 | 2022 年起年化 | 2022 年起月夏普 |
|---|---|---|---|---|
| Q1(最低) | 2.5% | 0.22 | 15.2% | 0.71 |
| Q2 | 6.4% | 0.40 | 10.8% | 0.58 |
| Q3 | 10.7% | 0.57 | 12.0% | 0.66 |
| Q4 | 10.5% | 0.59 | 14.7% | 0.72 |
| Q5(最高) | 11.1% | 0.61 | 23.1% | 0.92 |

研究段 Q1 到 Q3 由 2.5% 升到 10.7%,Q3 到 Q5 幾乎持平,最高分位 11.1% 仍低於 0050 的 15.1%。2022 年起 Q5 的 23.1% 最高,但 Q1 的 15.2% 高過 Q2 到 Q4,高低順序排不出來,Q5 也低於 0050 的 30.5%。
再把高低兩端拆成多空價差(震盪最高 30 檔的月報酬減最低 30 檔,各自等權、扣成本,未計放空成本):
| Aroon 週期 | 研究段價差(年化) | 研究段月夏普 | 2022 年起價差(年化) | 2022 年起月夏普 |
|---|---|---|---|---|
| 14 | 7.4% | 0.49 | 10.6% | 0.53 |
| 25 | 11.5% | 0.78 | 2.1% | 0.10 |
| 35 | 15.9% | 0.89 | 7.4% | 0.39 |
週期 25 的價差在研究段每年 11.5%、正報酬月份 55.4%,2022 年起只剩每年 2.1%、正報酬月份 52.6%。原因在空腿:震盪最低 30 檔 2022 年起年化 15.4%,多腿是 18.1%。

圖上藍線是週期 25 的多空價差累積,紫線是宇宙內震盪大於 0 的股票比例(20 日平均)。價差在 2015 到 2021 年整體往上(2019 到 2020 年有一段回落),2022 到 2023 年吐回一大段,2024 年後再創新高,2026 年 7 月又一次大跌。紫線在 5% 到 95% 之間大幅擺動,市場上升趨勢的廣度變化很快。
高 Aroon 震盪代表最近才創新高、很久沒創新低,跟 Jegadeesh & Titman (1993) 記錄的中期動能效應是同一類現象;他們的形成期是 3 到 12 個月,Aroon(20~25) 看的是一個月左右的新高新低時間,期間較短,只能算方向相近。台股 2015 到 2021 年這個排序有效,2022 年後單靠它已經分不出好壞,所以完整策略在震盪排序之外又加了三道工序。
完整策略:Aroon 震盪選股+持續性濾網+反波動加權+廣度減碼
首發版定案的規則如下,這次刷新沒有改任何參數:
- 可交易宇宙:上市櫃股票,60 日均成交金額前 300 名、60 日均量 > 100 萬股、收盤 > 10 元;只留代號剛好 4 碼數字的股票(排除權證、特別股與 6 碼代號),排除 ETF(00 開頭)、金融保險股、處置與全額交割股。KY 股代號也是 4 碼數字,沒有被排除。
- 因子:TA-Lib
AROON(timeperiod=20),震盪 = AroonUp − AroonDown,用未還原價計算。 - 持續性濾網:只留近 20 個交易日內震盪 > 0 至少 15 天的股票。
- 選股:合格池內震盪最高 10 檔。震盪是 5 的倍數,同分時代號小者排前面,這是首發版所用 finlab 2.0.13 的排名方式。
- 加權:權重與個股 60 日日報酬標準差成反比,組內正規化,單檔不設上限。
- 廣度減碼:每天算宇宙內震盪 > 0 的股票比例(流動性宇宙,不是全市場),取 14 日平均;跌破自身 120 日均值減 1.2 倍標準差時,整籃曝險乘 0.5,其餘放現金。
- 換股:每月最後一個交易日換股一次。選股與減碼判定都只在換股日讀取,月中廣度轉弱不會提前減碼。
完整策略的程式碼如下。印出的 cagr(0.252)與 max_drawdown(-0.356)就是下一節主表的全期年化與最大回撤;get_stats() 的夏普、索提諾扣了 2% 無風險利率,主表的月夏普、月索提諾不扣,所以數字不同:
顯示程式碼
import numpy as np
import pandas as pd
import finlab
from finlab import data
from finlab.backtest import sim
# finlab 會在需要資料時自動引導登入
finlab.login()
data.truncate_end = "2026-09-30" # 本文資料截止日;拿掉這行就用最新資料
# 1) 載入價量資料
close = data.get("price:收盤價")
volume = data.get("price:成交股數")
amount = data.get("price:成交金額")
# 2) 可交易宇宙:60 日均量 > 100 萬股、收盤 > 10 元、60 日均成交金額前 300 名,
# 只留代號剛好 4 碼數字的股票,排除 ETF(00 開頭)、金融保險股、處置/全額交割股
categories = data.get("security_categories")
financial = set(categories.loc[categories["category"].astype(str)
.str.contains("金融|保險|銀行", na=False), "stock_id"].astype(str))
is_common = pd.Series({sid: len(str(sid)) == 4 and str(sid).isdigit()
and not str(sid).startswith("00") and str(sid) not in financial
for sid in close.columns})
universe = ((volume.rolling(60, min_periods=20).mean() > 1_000_000)
& (close > 10) & close.notna()
& amount.rolling(60, min_periods=20).mean().is_largest(300))
universe = universe & pd.DataFrame([is_common.values] * len(close), index=close.index, columns=close.columns)
flagged = data.get("etl:is_flagged_stock").reindex_like(universe).fillna(False).astype(bool)
universe = universe & ~flagged
# 3) Aroon(20) 震盪 = AroonUp − AroonDown(越高 = 上升趨勢越領先)
aroon_down, aroon_up = data.indicator("AROON", timeperiod=20)
oscillator = (aroon_up - aroon_down).reindex(columns=close.columns)
# 4) 持續性濾網:近 20 個交易日內震盪 > 0 的天數至少 15 天
persistence = (oscillator > 0).rolling(20, min_periods=10).sum()
qualified = universe & (persistence >= 15).reindex_like(close).fillna(False).astype(bool)
# 5) 選股:震盪最高 10 檔。震盪是 5 的倍數,同分很多;method="first" 讓同分時代號小者排前面
basket = oscillator.where(qualified).rank(axis=1, ascending=False, method="first") <= 10
# 6) 反波動加權:權重與 60 日日報酬標準差成反比
vol60 = close.pct_change().rolling(60, min_periods=30).std()
inverse_vol = (1.0 / vol60).where(basket)
weights = inverse_vol.div(inverse_vol.sum(axis=1).replace(0, np.nan), axis=0).fillna(0.0)
# 7) 廣度減碼:宇宙內震盪 > 0 的比例取 14 日平均,
# 跌破自身 120 日均值減 1.2 倍標準差 → 整籃曝險乘 0.5
breadth = (oscillator > 0).where(universe).sum(axis=1) / universe.sum(axis=1).replace(0, np.nan)
breadth = breadth.astype(float).rolling(14, min_periods=7).mean()
floor = breadth.rolling(120, min_periods=60).mean() - 1.2 * breadth.rolling(120, min_periods=60).std()
risk_on = (breadth >= floor).reindex(close.index).ffill().fillna(True).astype(bool)
weights = weights.mul(np.where(risk_on.values, 1.0, 0.5), axis=0)
# 8) 回測:每月最後一個交易日換股,手續費打三折,sim 另扣賣出證交稅 0.3%
report = sim(weights.loc["2015-01-01":], resample="M", fee_ratio=1.425 / 1000 * 0.3, upload=False)
print(report.get_stats())rank 一定要寫 method="first"。finlab 2.2 起 rank 遇到同分會取平均名次,跨過第 10 名的同分組整組入選或整組落選(平均名次 ≤ 10 才入選),同一行程式每月會選到 0 到 18 檔,結果也不同(見後面「同分怎麼排」一節)。
完整策略的真實績效
| 區段 | 策略年化 | 策略月夏普 | 策略月索提諾 | 策略最大回撤 | 0050 年化 | 0050 月夏普 | 0050 月索提諾 | 0050 最大回撤 |
|---|---|---|---|---|---|---|---|---|
| 研究段 2015-01-30~2021 | 25.7% | 1.33 | 3.08 | -24.1% | 15.1% | 1.00 | 1.47 | -28.2% |
| 2022 年起~2026-09-30 | 24.7% | 1.02 | 2.08 | -35.3% | 30.5% | 1.21 | 2.44 | -34.0% |
| 全期 | 25.2% | 1.11 | 2.28 | -35.6% | 21.2% | 1.07 | 1.85 | -34.0% |
全期年化、月夏普、月索提諾三項勝過含息 0050,最大回撤 -35.6% 比 0050 深 1.6 個百分點,年化波動 22.3% 也高於 0050 的 19.8%。2022 年起年化 24.7% 落後 0050 的 30.5%,月夏普 1.02 對 1.21。年換手約 10.0 次,全期 1,391 筆交易。
我們每季重跑時的判準是「2022 年起月夏普 ≥ 1.0 且年化 ≥ 15%」。這次 2022 年起月夏普 1.02,只高出門檻 0.02,照原參數刷新、不調參;首發時同一段的月夏普是 1.17。下面幾節的檢查會說明這個 1.02 有多脆弱。
下面是完整互動式回測,月報酬熱力圖、權益曲線、年度績效都可以直接操作:
逐層拆開:持續性濾網、反波動加權與廣度減碼各自做了什麼
從宇宙內震盪最高 10 檔等權開始,一次加一道工序:
| 版本 | 研究段年化 | 研究段月夏普 | 研究段最大回撤 | 2022 年起年化 | 2022 年起月夏普 | 全期年化 | 全期最大回撤 |
|---|---|---|---|---|---|---|---|
| 震盪最高 10 檔等權 | 20.9% | 0.91 | -33.01% | 32.1% | 1.10 | 25.3% | -46.1% |
| 再加持續性濾網 | 25.9% | 0.90 | -35.55% | 29.0% | 1.01 | 27.1% | -41.9% |
| 改反波動加權(不擇時) | 25.5% | 1.03 | -30.92% | 24.3% | 0.95 | 24.9% | -35.9% |
| 再加廣度減碼(完整策略) | 25.7% | 1.33 | -24.10% | 24.7% | 1.02 | 25.2% | -35.6% |

持續性濾網有實際動手:不加濾網時的震盪前 10 名,平均每個月有 3.2 檔沒通過(141 個月裡 129 個月剔除過、共 447 檔次)。它把研究段年化從 20.9% 拉到 25.9%,2022 年起卻從 32.1% 降到 29.0%。
反波動加權用報酬換回撤:全期年化 27.1% → 24.9%、2022 年起 29.0% → 24.3%,全期最大回撤 -41.9% → -35.9%。權重會集中到低波動的股票,月底最大單檔權重中位 17.9%、前 5 檔合計 64.9%;2026-09-30 換股日,中華電(2412)一檔就占 36.3%。從完整策略只拿掉這一項改回等權,全期年化 28.0%、2022 年起月夏普 1.09,但全期最大回撤 -41.6%。
廣度減碼幾乎不改變全期報酬(24.9% → 25.2%),主要作用在研究段:月夏普 1.03 → 1.33、研究段最大回撤 -30.92% → -24.10%。全期最大回撤只從 -35.9% 收到 -35.6%,因為 2022 年兩次最大的單月下跌(6 月 -12.5%、9 月 -12.0%)前的月底都判定滿倉,那一年只有 4 月底減碼一次。
減碼訊號本身的細節:
- 日頻訊號 2015 年以來轉弱 34 次,其中 13 次在月底前就轉回、完全沒有執行,執行的 21 次從轉弱到第一個換股日中位數隔了 9 個交易日(最長 19 天)。141 個月底有 23 個判定減碼,月底平均曝險 91.8%。
- 月底讀數有參考價值:判定減碼的月份,不擇時的選股籃下個月平均 +0.51%(中位 -0.1%),判定滿倉的月份平均 +2.48%(中位 1.9%);0050 分別是 -0.56% 與 +2.23%。
- 同一個月底選股籃改成每天依廣度調整,全期年化反而降到 21.0%、2022 年起月夏普 0.86;不看廣度、每天固定 91.8% 曝險,全期 23.0%、研究段月夏普 1.04;擇時改用 0050 站上 200 日均線,全期 20.8%。
- 廣度判定減碼的日子,0050 次一交易日的年化波動 26.3%,滿倉日 18.2%。這和 Moreira & Muir (2017) 的發現方向一致:在波動升高時降低曝險,可以改善風險調整後報酬。本文的訊號是上升趨勢廣度,跟他們用的已實現波動不同,只在這個重疊的程度上相呼應。
- 廣度的母體是流動性宇宙(每天約 228 檔),震盪 > 0 的比例中位 52.3%,10% 與 90% 分位在 22.7% 與 79.0%。

換股日挪一下,結果差很多
同一套規則只改換股日:每月 5、10、15、20、25 日(遇假日取當月在這天以前的最後一個交易日;5 日以前都沒開盤的月份不換股),其餘不動:
| 換股日 | 研究段年化 | 2022 年起年化 | 全期年化 | 全期最大回撤 | 不擇時的研究段年化 |
|---|---|---|---|---|---|
| 每月 5 日 | 21.6% | 24.2% | 22.5% | -45.3% | 21.3% |
| 每月 10 日 | 9.5% | 25.2% | 15.5% | -46.4% | 12.0% |
| 每月 15 日 | 18.4% | 15.5% | 17.2% | -45.3% | 20.6% |
| 每月 20 日 | 3.7% | 24.1% | 11.4% | -39.1% | 2.0% |
| 每月 25 日 | 25.0% | 15.1% | 20.8% | -38.7% | 25.4% |
| 月底(本文) | 25.7% | 24.7% | 25.2% | -35.6% | 25.5% |

月底換股的全期 25.2% 是六個換股日裡最高的,挪到 20 日只剩 11.4%。拿掉廣度減碼後研究段一樣是 2.0% 到 25.5%,差距主要來自選股,跟擇時關係不大。Hoffstein, Faber & Braun (2020) 把這種只因換股日不同造成的差距稱為 rebalance timing luck,持股越集中、換股越少越明顯;這套策略只抱 10 檔、一個月換一次,正好落在這個範圍。
換股更頻繁也不會比較好:同一個部位改成每週讀取,年換手跳到約 36 次,研究段年化 -3.8%、2022 年起 29.8%、全期 8.6%、全期最大回撤 -48.0%。
參數:選中的組合在 2022 年後站在邊緣
首發版選參數時看的是研究段,網格是 Aroon 週期(18、20、22)× 持股檔數(8、10、12),選股與廣度用同一個週期:


研究段 9 格月夏普 1.02 到 1.45,全部在 1.0 以上;2022 年起只剩 0.68 到 1.11,在 1.0 以上的只有週期 20 配持股 8(1.11)與持股 10(1.02)兩格。週期 22 研究段最高(持股 10 是 1.45),2022 年起只有 0.68 到 0.85。
再把每個參數逐格掃一遍(其餘設定同完整策略):
| 逐格掃描 | 範圍 | 研究段月夏普 | 2022 年起月夏普 | 2022 年起四捨五入後 ≥ 1.00 的格數 |
|---|---|---|---|---|
| Aroon 週期(選股與廣度同步換) | 10~40 日 | 0.54~1.46 | 0.41~1.23 | 4/31 |
| Aroon 週期(只換選股) | 10~40 日 | 0.77~1.45 | 0.63~1.21 | 10/31 |
| 持股檔數 | 5~20 檔 | 1.23~1.43 | 0.76~1.11 | 4/16 |
| 持續性門檻(20 天內) | 10~20 天 | 1.12~1.64 | 0.76~1.11 | 6/11 |
| 廣度平滑天數 | 5~30 日 | 1.16~1.37 | 0.79~1.02 | 8/26 |
| 廣度回看天數 | 60~240 日 | 1.17~1.33 | 0.87~1.03 | 4/19 |
| 門檻倍數 | 0.6~2.0 倍標準差 | 1.11~1.34 | 0.86~1.08 | 5/15 |
| 減碼後保留比例 | 0~1 | 1.03~1.47 | 0.95~1.04 | 8/11 |

研究段的月夏普在 Aroon 週期 19 到 20 之間從 0.94 跳到 1.33,週期 20 到 24 是一段高點;同一段在 2022 年起從 1.02 一路降到 0.76。持續性門檻提高到 19、20 天時研究段月夏普 1.52、1.64 最高,2022 年起只有 0.76、0.90。多數參數在 2022 年後都要靠近首發的那一格才站得上 1.0,換一格就掉下來,比較像參數剛好落在研究段的好位置。過擬合的判斷方法可參考回測過擬合機率。
同分怎麼排,也會改變結果
Aroon(20) 震盪只有 41 種取值,141 個換股日裡有 95 個月,第 10 名與第 11 名同分。這種月份的同分組中位數 5 檔,靠代號順序選進來的中位數 2 檔,全期共有 339 檔次因為代號較大而落選。三種同分處理方式的結果:
| 同分時怎麼排 | 全期年化 | 全期最大回撤 | 2022 年起年化 | 2022 年起月夏普 |
|---|---|---|---|---|
| 代號小者排前面(本文,與首發相同) | 25.2% | -35.6% | 24.7% | 1.02 |
| 取平均名次(finlab 2.2 起 rank 的預設) | 22.8% | -37.7% | 22.0% | 0.94 |
| 60 日波動較低者排前面 | 21.5% | -31.9% | 19.7% | 0.85 |
取平均名次時,跨過第 10 名的同分組整組入選或整組落選(平均名次 ≤ 10 才入選),每月實際持股 0 到 18 檔,141 個月有 100 個月不是 10 檔;2020 年 11 月底與 2023 年 2 月底池內震盪 100 分的股票太多,整個月一檔都沒選到。代號順序在經濟上沒有意義,換成另外兩種合理的排法,2022 年起月夏普都在 1.0 以下。首發版用的 finlab 2.0.13 排名本身就是代號順序,所以本文沿用並寫明,讀者自己跑的時候記得 method="first"。
2026-06-09 之後:首發後的新資料
首發版資料截至 2026-06-09。延長到 2026-09-30,這 3 個多月策略跌 10.9%,0050 漲 8.9%;同一籃改成每天依廣度調整的對照組跌 15.4%,不擇時的版本跌 16.9%。
| 月份 | 策略 | 每天依廣度調整 | 不擇時 | 含息 0050 |
|---|---|---|---|---|
| 2026-07 | -13.1% | -19.4% | -24.7% | -4.0% |
| 2026-08 | +5.9% | +7.5% | +12.7% | +3.3% |
| 2026-09 | -3.4% | -2.3% | -2.3% | +5.5% |

6 月 30 日換股時,平滑後的廣度 48.0% 跌破門檻 49.1%,策略減碼到五成。7 月持有的 10 檔全部虧損,中位數 -17.6%、最差的 6207 跌 39.8%;不擇時的版本當月 -24.7%,減碼少賠了 11.6 個百分點,是 2015 年以來減碼少賠最多的一個月。同月 0050 從 7 月 1 日高點到 7 月 30 日低點跌了 14.0%,整月 -4.0%。7 月底仍判定減碼(廣度 17.3%、門檻 40.5%),8 月底、9 月底恢復滿倉。策略淨值 2026-06-03 創高後,9 月 15 日最深回落 23.0%,9 月底距高點 -18.5%;2026 年 7 月的 -13.1% 是 2022 年以來最差的一個月。
數字從首發到這次的變化可以拆成兩塊。用首發程式和當時的 finlab 2.0.13 截到 2026-06-09,研究段年化 25.35%、最大回撤 -24.10% 與首發數字逐位相同;2022 年起與全期是 29.77%、26.97%,比首發的 29.57%、26.89% 高 0.2 與 0.1 個百分點,差距來源未查明。改用 finlab 2.2.21、rank 寫明 method="first" 並從 2015-01-30 起算後,同一截止日是研究段 25.69%、2022 年起 30.00%、全期 27.25%(2022 年起月夏普 1.19)。這次的 2022 年起月夏普從 1.19 降到 1.02,來自 6 月以後的新資料。
回測方法與口徑
- 交易成本:finlab
sim(),手續費 0.1425% 打三折、賣出證交稅 0.3%。手續費不打折時全期年化 22.7%、2022 年起月夏普 0.95;手續費加倍且稅率 0.6% 時 20.4%、0.87。 - 滑價:未額外假設,實際成交衝擊取決於資金規模與成交量,本文未估算容量。
- 股票池:每天依當時的價量重新篩選流動性前 300 名,下市或停止交易的股票在當時都可能被選入;2015-01-30 有收盤價、到 2026-09-30 已沒有收盤價的 4 碼普通股共 142 檔。
- 排除類別:ETF(00 開頭)、代號不是剛好 4 碼數字者(權證、特別股、6 碼代號)、金融保險股、處置與全額交割股;KY 股未排除。首發版的代號規則是「前 4 碼為數字」,用首發規則跑同一策略結果完全相同。
- 前視偏差:Aroon、持續性天數、60 日波動與廣度都只用當天以前的價格;選股與減碼在月底收盤後判定,
sim()以次一交易日起的報酬計算。完全沒有財報或月營收輸入。 - 未還原價:Aroon 用未還原的最高價、最低價。7 月宇宙內廣度比還原價版本平均低 5.3 個百分點,141 個月底有 3 個減碼判定不同,7 月底的選股籃平均只有 71% 相同。我們在看回測結果之前決定維持未還原(與首發相同);改用還原價時,選股與廣度都改是全期 26.6%、2022 年起月夏普 1.00,只改廣度是 25.8%、1.04。
- 權重:反波動加權、單檔不設上限;廣度減碼時整籃乘 0.5,其餘現金,不放空、不加槓桿。
- 周轉率:年換手約 10.0 次。
- 樣本內外:研究段 2015-01-30~2021-12-31 是首發選參數時看過的區段,2022 年起當作驗證段;首發版的硬門檻也用到了 2022 年後到 2026-06 的數字,所以 2022 年起並非完全沒看過的資料。
- 教科書與五分位:都扣同樣的成本、月換股,與主策略同一套回測口徑。
- 績效指標:月夏普 = 月報酬平均 ÷ 標準差 × √12,月索提諾的分母只算下跌月份,兩者都不扣無風險利率;0050 用同一套公式。
不同年度的表現:12 年贏 7 年
| 年度 | 策略 | 含息 0050 | 勝負 |
|---|---|---|---|
| 2015(1/30 起) | 1.9% | -7.9% | 勝 |
| 2016 | 17.7% | 19.6% | 負 |
| 2017 | 25.8% | 18.1% | 勝 |
| 2018 | 15.8% | -4.9% | 勝 |
| 2019 | 8.0% | 33.5% | 負 |
| 2020 | 54.7% | 31.1% | 勝 |
| 2021 | 66.5% | 21.9% | 勝 |
| 2022 | -32.5% | -21.4% | 負 |
| 2023 | 62.1% | 27.5% | 勝 |
| 2024 | 35.0% | 48.6% | 負 |
| 2025 | 48.2% | 36.8% | 勝 |
| 2026(至 9/30) | 29.3% | 74.3% | 負 |
2020、2021、2023 年大幅領先,2019、2024、2026 年明顯落後。2022 年跌 32.5%,比 0050 的 -21.4% 多跌 11.1 個百分點。
加上月營收 YoY 會更好嗎:研究段較好,2022 年起較差
在宇宙層加一條「最近一期已公布的月營收年增率 > 0 才能入池」(公布日對齊、交易日往後填補,只用已公布的營收),其餘不變:研究段年化 32.5%、月夏普 1.37,比原策略好;2022 年起 20.6%、0.84,比原策略差;全期 27.4%,最大回撤 -44.3% 深了將近 9 個百分點。兩段方向相反,本文主策略維持純技術。基本面與技術面如何分工,可延伸看技術面與基本面選股的差異。
用 aroon 最常踩的四個陷阱
- 把交叉當買點:近 20 日剛黃金交叉的股票研究段年化 1.3%,月底當天剛交叉的 -3.3%。
- 只看震盪排序:震盪最高 30 檔兩段都輸 0050,2022 年起多空價差只剩每年 2.1%。
- 沒處理同分:同一行
rank,新舊版 finlab 會選出不同股票,2022 年起月夏普差 0.08。 - 只看月底換股的成績:換到每月 5~25 日,全期年化 11.4%~22.5%,月底的 25.2% 是最高的一組。
三項穩健性驗證:重跑到 2026 年 10 月
這裡驗證本文的完整策略,三項檢查統一採 sim() 預設手續費 0.1425% 與證交稅 0.3%,資料到 2026-10-27。「贏」指日夏普高於同期 0050 含息買進持有(etl:adj_close 還原價、純算術計算、不扣成本),日夏普 = 日報酬平均 ÷ 標準差 × √252,不扣無風險利率。
2026-10-27 的第一版檢查用的是當時的可下載檔(在 finlab 2.2 上同分取平均名次、廣度用 14 日指數平均),我們逐格重現了當時的結果,下表是把程式改成本文規則(同分代號小者排前面、廣度 14 日簡單平均)後同口徑重跑:
| 檢查 | 標準 | 結果 |
|---|---|---|
| 鄰近參數 | Aroon 週期(16、20、24)乘上持股檔數(8、10、12),9 組至少 7 組贏 | 0/9 組贏,不過 |
| 前後兩段 | 2015-01-30 到 2020-12-11、2020-12-14 到 2026-10-27 兩段都贏 | 前段 0.95 對 0.89 贏,後段 1.15 對 1.24 輸,不過 |
| 交易成本 | 原參數、sim() 預設成本 |
日夏普 1.05 對 1.08,不過 |

9 組參數的日夏普(括號內是年化報酬,粗體是本文參數):
| 持股檔數 \ Aroon 週期 | 16 | 20 | 24 |
|---|---|---|---|
| 12 | 0.82(年化 17.1%) | 0.88(年化 17.6%) | 0.91(年化 19.4%) |
| 10 | 0.85(年化 18.1%) | 1.05(年化 22.6%) | 0.90(年化 19.7%) |
| 8 | 0.81(年化 17.5%) | 1.06(年化 23.7%) | 0.93(年化 21.7%) |
前後兩段與全期:
| 期間 | 策略年化 | 策略日夏普 | 0050 含息年化 | 0050 日夏普 |
|---|---|---|---|---|
| 前段 2015-01-30 到 2020-12-11 | 16.7% | 0.95 | 13.5% | 0.89 |
| 後段 2020-12-14 到 2026-10-27 | 28.7% | 1.15 | 28.0% | 1.24 |
| 全期 2015-01-30 到 2026-10-27 | 22.6% | 1.05 | 20.5% | 1.08 |
前後兩段是把整段期間從中點對半切。上文的研究段與 2022 年起以 2022 年初為界,照這個切法,2015 到 2021 年日夏普 1.15 對 0050 的 0.96,2022 年起 0.95 對 1.22。上文多用月夏普,跟這裡的日夏普算法不同,數字不能直接比。
交易成本對照(原參數):
| 成本設定 | 年化 | 日夏普 | 最大回撤 |
|---|---|---|---|
| 不扣成本 | 30.1% | 1.33 | -33.2% |
sim() 預設:手續費 0.1425%、證交稅 0.3% |
22.6% | 1.05 | -36.7% |
| 本文設定:手續費打三折 | 25.1% | 1.15 | -35.6% |
| 0050 含息買進持有(同期) | 20.5% | 1.08 | -34.0% |
修正後三項仍未全數通過,結論與 10-27 相同:9 組鄰近參數全部輸,原參數 1.05 只比 0050 的 1.08 低一點,週期 16 那一欄掉到 0.81 到 0.85;後段 1.15 輸 1.24。10-27 版本裡「重跑到 2026-06-09 只有 24.8%、月夏普 1.07」的落差,主要來自平均名次,指數平均廣度另有小幅影響(以 2026-09-30 的資料各自單改,全期年化分別少 2.4 與 0.4 個百分點);照本文規則跑到同一天是 27.3%、1.19、-35.6%。
策略的限制與取捨
- 2022 年起落後 0050:2022 年起年化 24.7% 對 30.5%,月夏普 1.02 只高出我們的門檻 0.02;2026 年 6 月到 9 月跌 10.9%,同期 0050 漲 8.9%。
- 結果依賴換股日與同分規則:換股日挪到每月 5~25 日全期只剩 11.4%~22.5%;同分改用平均名次或低波動優先,2022 年起月夏普 0.94、0.85。
- 集中度高:只抱 10 檔、反波動加權後有效持股中位數約 8.6 檔,低波動的股票可以拿到三成以上權重;能接受 -35% 等級回撤與高集中度的人才適合。
- 擇時只在月底:日頻轉弱有 13 次在月底前就轉回而沒執行,執行的中位數晚 9 個交易日;2022 年兩次最大的單月下跌前,月底都判定滿倉。
- 容量與成本:宇宙限成交額前 300 名、選 10 檔、年換手約 10 次,回測未逐筆估算滑價與容量,大資金部署要另外評估。
- 參數的位置:逐格掃描顯示 2022 年後多數鄰近參數低於 1.0,2026-06 首發時選參數已看過研究段與部分 2022 年後的資料。
- 各技術指標的回測比較可參考RSI、MACD、KD 比較、KD 鈍化策略、ADX 趨勢強度指標回測與TA-Lib 158 種技術指標;用大盤訊號降低回撤,也可參考市場濾網如何降低回撤。
自己跑一次
FinLab Skill 可以讓你的 AI 助理一步步帶你安裝、抓台股資料、重現這篇的回測:
裝好之後,下載本文的 strategy.py 與 data.csv,即可在自己的環境重跑、改參數、換因子。strategy.py 會印出本文的主表、逐層建構、換股日比較、逐年報酬與首發後的逐月報酬;data.csv 除了策略與 0050 的淨值,也附上每天的廣度、減碼門檻與滿倉/減碼判定。把 DATA_END 改成 None 就能用最新資料重跑。登入只需在程式裡寫 finlab.login(),套件會在需要資料時引導你完成登入。想延伸成更完整的量化流程,可參考量化交易總覽與程式交易是什麼;想一次看完常用技術指標的台股回測,見技術指標台股回測總覽。策略上線前該留意的陷阱,可看回測的限制與量化交易的風險。
常見問題
Q:aroon 阿隆指標的參數要設多少? 完整策略用 timeperiod 20,這是首發時看研究段選的。逐格掃描 10 到 40 日,研究段月夏普 0.54 到 1.46,2022 年起只有 13、14、16、20 這 4 個週期在 1.0 以上;研究段最高的 23、24、36 日(1.46),2022 年起只有 0.77、0.76、0.91。與其找「最佳」數字,比較實際的做法是確認你用的週期附近幾格都站得住。
Q:AroonUp 上穿 AroonDown 的黃金交叉能不能買? 回測結果不好。近 20 個交易日內剛黃金交叉、月底仍在上方的股票全部持有,研究段年化 1.3%、2022 年起 11.5%;只買月底當天剛交叉的股票,研究段 -3.3%。AroonUp 已經在上方的全部股票反而有 11.9%,問題出在剛交叉的時點。
Q:Aroon 低檔(AroonDown 高)可以拿來抄底嗎? 研究段不行:震盪最低 30 檔年化 0.1%。2022 年起這一籃有 15.4%,跟最高 30 檔的 18.1% 差不多,但兩段都輸 0050,沒有理由專門去買它。
Q:Aroon 震盪要選最高幾檔、多久換一次股? 本文選最高 10 檔、每月最後一個交易日換股,先過持續性濾網(近 20 個交易日內震盪大於 0 至少 15 天)。持股 5 到 20 檔逐格掃描,2022 年起只有 7 到 10 檔四捨五入後在 1.00 以上;改成每週換股,研究段年化 -3.8%、年換手約 36 次;換股日挪到每月 5~25 日,全期年化掉到 11.4% 到 22.5%。
Q:為什麼用同一個 rank 寫法,跑出來的檔數不一樣?
Aroon 震盪是 5 的倍數,同分很多。finlab 2.0 的 rank 遇到同分照代號順序給名次,2.2 起改成取平均名次,跨過第 10 名的同分組會整組入選或整組落選。本文程式寫 method="first",同分時代號小者排前面,與首發相同;不寫的話每月會選到 0 到 18 檔,2022 年起月夏普是 0.94。
Q:aroon 和 ADX、DMI 這些趨勢指標差在哪? aroon 量的是距離創新高、新低的天數(趨勢的新鮮度與方向),ADX 量的是趨勢強度(不分多空)。兩者角度互補,ADX 的台股回測可看ADX 趨勢強度指標回測;本文只測了 aroon 單一指標。
Q:這套 aroon 純技術策略適合誰? 適合能接受 -35% 等級回撤、高集中度與年換手約 10 次,想主動選股的人。全期年化 25.2% 勝 0050 的 21.2%,但 2022 年起落後 0050,而且結果明顯受換股日與同分規則影響。偏好低周轉、受不了深回撤的人,直接持有含息 0050 更簡單。
最後更新:2026-10|回測區間:2015-01-30 ~ 2026-09-30|作者:FinLab 量化研究團隊(經量化研究員審閱)
本文僅供量化研究與教學用途,所有回測數字均由 finlab 套件在真實台股資料上產出,過去績效不代表未來表現,不構成投資建議。Aroon 震盪選股加廣度減碼策略全期最大回撤 -35.6%,換股日改到每月 5 到 25 日時全期年化只剩 11.4% 到 22.5%,實際交易前請自行評估風險、滑價與交易容量。
FinLab AI
想建立自己的策略?
用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案
免費開始

