技術分析 · 趨勢過濾

ADX/DMI 怎麼判斷「現在有沒有趨勢」?
當成其他策略的開關使用

2026-08-18·11 分鐘閱讀

你的突破策略在爆走行情裡三天賺了 6%,接著市場走平兩週,同一組進場條件把那 6% 又還回去,程式碼沒改過一行。你已經在懷疑,是不是有辦法讓策略在盤整期間直接不進場。

ADX(Average Directional Index)本來就是為了這件事被造出來的——它是 Wilder 1978 年在《New Concepts in Technical Trading Systems》裡跟 RSI 一起提出的一組指標。跟 RSI、MACD 不一樣,它不是拿來當進場訊號,它是拿來回答一個更前面的問題:現在這套策略該不該跑。

先講結論:ADX 單獨拿來當進場訊號,幾乎每個人都試過、也每個人都被騙線甩過。它的實際用途只有一種——你已經有一套會在盤整期被鋸的突破策略,或者一套會在爆走時被輾的均值回歸策略,用 ADX 把它們該關的時候關掉。這篇不教你怎麼用 ADX 進場,只講怎麼把它接上你已經有的策略。文末給一份可以直接複製的 Pine Script 骨架,也就是 TradingView 圖表上寫策略邏輯用的那個腳本語言。
14
Wilder 的預設週期,1978 沿用至今
20 → 25
Wilder 原文的「盤整→有趨勢」門檻
P70
加密永續建議改用的動態閾值:過去 200 根 K 棒 ADX 分布的 70% 分位數

ADX 在算什麼——先看機制

ADX 這條線本身沒什麼直觀意義。要看懂它,得先看它下面那兩條——`+DI` 跟 `−DI`。這三條合起來叫 DMI(Directional Movement Index),Wilder 的原設計是三條一起看,只看 ADX 反而漏掉了方向資訊。

機制大略是這樣。每根 K 棒跟上一根比,如果今天高點比昨天高、而且高過的幅度比低點低過的幅度多,就算一個 `+DM`(正向動能);反過來就算 `−DM`。把過去 14 根 K 棒的 `+DM` 加起來、除以同期的 True Range 做 smoothing,得到 `+DI`;`−DM` 同樣處理得到 `−DI`。ADX 是 `+DI` 跟 `−DI` 差距的絕對值再 smoothing 一次。

結論是:ADX 只告訴你「趨勢的強度」,不告訴你方向。方向要看 `+DI` 跟 `−DI` 誰在上面。三條線各自代表的東西看下面這張。

線回答的問題數值範圍
+DI多方力道有多強0–100,通常 10–40
−DI空方力道有多強0–100,通常 10–40
ADX多空之中優勢方的強度(不含方向)0–100,通常 10–60

來源:Pine Script v6 語言參考手冊的 ta.dmi 說明;Wilder 1978《New Concepts in Technical Trading Systems》原始定義(查證日期 2026 年 8 月)。

預設週期 14 是 Wilder 自己的原始參數,之後被大部分平台沿用。TradingView 的 ta.dmi() 就是這樣:ta.dmi(14, 14),第一個 14 是 DI 的長度、第二個 14 是 ADX 的 smoothing 長度。這兩個參數可以分開調,但沒有先實測就不要動——大多數討論 ADX 閾值的資料都是預設 14 為前提寫的,動了之後那些閾值就不再對得起來。

為什麼 ADX 不能單獨拿來進場

只看 ADX 這條線很容易得出「ADX > 25 就是有趨勢,我進場」這種規則,然後在實盤上被打回來。原因就在上面那張表的第三欄——ADX 沒有方向。ADX 從 15 爬到 30,可能是價格在往上走的趨勢在強化,也可能是在往下崩的趨勢在強化,只看那條線分不出來。

第二個問題是延遲。ADX 是兩層 smoothing 疊出來的(先 smooth DM/TR、再 smooth 差距的絕對值),等它爬到 25 以上、你判斷「有趨勢」的時候,價格已經走了一段。用它當進場訊號,你永遠是在趨勢的中後段才上車。

這裡是知識論免責
「ADX 中後段才亮」這件事是從兩層 smoothing 的定義推導出來的必然結果,不是 Wilder 原文有一句話直接這樣講。你自己在圖表上把 ta.dmi(14, 14) 疊到任何一段明顯的趨勢上都會看到這個延遲,但這是「機制推論 + 圖表觀察」,不是官方白紙黑字的一句話。

所以拿 ADX 進場的做法——不管是「ADX 突破 20」還是「+DI 上穿 −DI」——你都得先接受兩件事:進的是趨勢的中後段,而且會被騙線常態性地掃出去。這條路不是沒有人走通,但走通的人幾乎都在 ADX 之外還疊了別的過濾條件(時間框架、成交量、突破的 wick)。ADX 單獨扛不起進場這件事。

那 ADX 到底該多少算「有趨勢」

Wilder 原文其實只給兩個閾值:ADX 低於 20 沒有明確趨勢、高於 25 有明確趨勢——StockCharts 的 ChartSchool 就是這樣引 Wilder。常見教材再往上補幾段更細的分級(25–50 明確趨勢、50 以上極強趨勢)方便對應直覺,但那是後來的通用寫法,Wilder 原書沒有把 50 這個數字寫進去。這兩個原始閾值被沿用了將近 50 年,大部分教科書講「有沒有趨勢」時用的就是這一組。

但這組數字是他在 1970 年代的商品與外匯市場上觀察出來的。日內加密永續是另一個世界:波動大、假突破多、24 小時交易沒有收盤缺口,同樣的 14 週期在 5 分鐘圖上,ADX 幾乎不會低於 20。硬套 25 的閾值等於整天都在「有趨勢」,開關等於沒開。

這份閾值是快照,不是永久保證
下面這張表是我在 BTCUSDT.P 上把 ta.dmi(14, 14) 疊到不同時間框架、看過去 90 天 ADX 分布拉出來的參考數字(查證日期 2026 年 8 月)。實際做開關前建議你自己去圖表上疊一次——不同標的、不同期間會漂移,尤其是牛熊轉換時整體數值會整段上移或下移。
時間框架ADX 大致中位數當開關的參考閾值
5m22–28看 90 天分布的 70% 分位數
1H18–2420–22
4H16–2220–25(比較接近 Wilder 原文)
1D15–2025(接近 Wilder 原文)

以 BTCUSDT.P 過去 90 天為例的觀察數值(查證日期 2026 年 8 月)。這是快照不是保證,實際套用前自己在圖表上驗一次。

比起硬記數字,更耐用的做法是用分位數而不是絕對值——ADX 大於「過去 200 根 K 棒 ADX 分布的 70% 分位數」時算有趨勢。這樣一來,同一份 Pine Script 可以跨時間框架跟不同標的用,不用每換一個對就手動改閾值。

把它接上策略:兩種疊法

趨勢類
ADX 高開、低關(突破、動能、CTA)
均值回歸類
ADX 低開、高關(布林通道回歸、支撐反彈)
同一條 ADX
兩種方向相反,理論上輪班上場

ADX 當開關的核心邏輯只有一種,方向兩種:趨勢類策略在 ADX 高的時候開、在 ADX 低的時候關;均值回歸類策略反過來。這件事的直覺很簡單,但寫進策略時要對的欄位不少。

趨勢類(突破、動能)均值回歸類(布林通道回歸)
ADX 開關條件ADX > 閾值時進場ADX < 閾值時進場
在盤整期表現被鋸來鋸去、勝率掉本來就是它的主場
在爆走期表現本來就是它的主場會被輾——回歸假設失效
加上 ADX 開關後的效果盤整期少進場、少虧爆走期少進場、少虧
開關關掉時要不要平倉現有部位看 stop,不強制平強烈建議平——回歸假設沒了

最後那一列是最容易漏的:「開關關掉」跟「平倉」不是同一件事。開關關掉只擋住新單,已經在場內的部位怎麼處理是另一個決策。趨勢策略靠自己的 stop 出場沒問題;均值回歸策略如果進場後 ADX 從 15 飆到 35,代表你當初賭的「會回來」的前提已經被打破,這時候比較安全的做法是主動平掉,不要等 stop。

用 Pine Script 把這個開關寫出來

下面是最小可用的骨架。這段本身不能直接拿去回測,因為進場邏輯留白了——重點是那個 regimeOn 變數怎麼算、怎麼跟你的進場條件相接。你把 longSig 跟 shortSig 換成自己的邏輯就是一個完整策略。

pine
//@version=6
        strategy("Trend Strategy with ADX Regime Filter",
             overlay          = true,
             default_qty_type = strategy.percent_of_equity,
             default_qty_value= 10,
             initial_capital  = 10000)

        // ─── ADX 參數 ───
        diLen       = input.int(14,   "DI Length")
        adxLen      = input.int(14,   "ADX Smoothing")
        useAdaptive = input.bool(true,"用分位數而不是固定閾值")
        fixedThr    = input.float(20, "固定閾值(useAdaptive=false 時用)")
        pctLookback = input.int(200,  "分位數回看根數")
        pctRank     = input.float(70, "分位數(%)")

        // ─── DMI + 開關 ───
        [diPlus, diMinus, adx] = ta.dmi(diLen, adxLen)
        adaptiveThr = ta.percentile_linear_interpolation(adx, pctLookback, pctRank)
        threshold   = useAdaptive ? adaptiveThr : fixedThr
        regimeOn    = adx > threshold

三個地方值得展開一下。ta.dmi() 一次回傳三個值——`+DI`、`−DI`、ADX——用陣列解構接。ta.percentile_linear_interpolation(adx, 200, 70) 是 Pine v5 之後才有的內建函式,直接算「過去 200 根 K 棒 ADX 分布的 70% 分位數」,不用自己排序。useAdaptive 那個開關留著是為了讓你能拿分位數版跟固定閾值版做同一段回測的 A/B——不然爭論哪種好比較沒有意義。

上面只算了開關本身。下面示範怎麼把它接到你自己的進場條件——這裡用最陽春的 Donchian 突破當範例,你把 longSig 跟 shortSig 換成自己的就是一個完整策略。

pine
// 承上,接續同一份 strategy() 底下

        // ─── 進場條件(換成你自己的) ───
        lookback = 20
        hh       = ta.highest(high, lookback)[1]
        ll       = ta.lowest(low,  lookback)[1]
        longSig  = close > hh
        shortSig = close < ll

        // ─── 只有開關開啟才進場 ───
        if regimeOn and longSig
            strategy.entry("Long",  strategy.long)
        if regimeOn and shortSig
            strategy.entry("Short", strategy.short)

        // 圖表視覺化:開關開啟時背景綠色
        bgcolor(regimeOn ? color.new(color.green, 90) : na, title = "Regime On")

`[1]` 那個位移是刻意的——`ta.highest(high, 20)[1]` 是「不包含這根 K 棒」的過去 20 根最高點,避免用未來資料算進場條件(`repainting` 的其中一種)。這是Pine Script 自動化陷阱裡最經典的一種。

這段程式碼沒回測過
這段是骨架,我沒有實際跑回測。加上 ADX 開關之後回測數字往上跳是常態,但實盤跟不上也是常態——原因是回測期間如果剛好牛熊分明,開關關掉的那些盤整期天生就是虧錢期,回測數字自然漂亮,但那不代表下一段實盤的盤整期會被同樣的開關擋掉。實盤與回測落差請看 Webhook 部位大小 那篇的第一節。

用 ADX 當開關最常見的兩個錯誤

這兩個錯誤幾乎是新做濾網的人一定踩的,都不會報錯,也都不會在回測數字上明顯露餡。

1
你的策略跑在 5 分鐘圖,但 ADX 條件是判斷 4 小時圖的 ADX > 25?
是 →時間框架錯配。4H ADX 一根往上動,可能對應 5m 圖上的 48 根,但 4H ADX > 25 那個瞬間 5m 早就已經開始鈍化了。要跨時間框架就用 request.security——它的 lookahead 從 v3 起預設就是 barmerge.lookahead_off(安全值),只要你沒有顯式傳 barmerge.lookahead_on,回測就不會偷用未來資料。
否,我在同一個時間框架上算 ADX →下一題。
2
加上 ADX 開關後,你把回測期間從一年拉到三年,數字還是同樣漂亮嗎?
一年很漂亮、三年就崩 →過擬合的味道很重。ADX 開關的閾值如果是「一年前一年後最佳化」跑出來的,本質上就是曲線擬合。用分位數(percentile_linear_interpolation)而不是固定閾值可以緩解,但不能根治——最好的做法是先做 walk-forward,不要一次跑全部歷史。
三年也還可以,但實盤跟不上 →看下一個 Callout,多半是牛熊期分布跟未來不一樣導致的偏差。
一年、三年都很漂亮而且實盤也對得起來 →那就上小資金試三個月,實測比什麼都準。

第一個錯誤——時間框架錯配——寫錯不會編譯不過,只會回測跟實盤對不上。第二個錯誤更陰險,它會在回測期間「安靜地變好」:你在 2022 年到 2024 年的資料上把閾值調到 22,看起來很棒;但 2022 年整年是明顯的下行趨勢,那組閾值本質上是為那段行情調的,換到 2025 年橫盤三個月的時候就完全失效。

誠實的一段:ADX 過濾不了的東西

ADX 這個工具再怎麼用,也有幾件事它結構上就做不到。這裡先列出來,免得你花時間去試——我們自己也試過,答案是不行。

  • 短促的 news spike。Wilder 的 ADX 有兩層 smoothing,反應速度天生就慢。CPI 公布後 3 根 K 棒內的爆走,等 ADX 亮起來已經回吐一半了。
  • 低波動的緩慢趨勢。價格慢慢漲、但每根 K 棒振幅都很小,True Range 小、DM 也小,ADX 可以整段爬升期間都在 15 以下。這種行情 ADX 開關會全程關著,你會錯過它。
  • 「假趨勢」的頭尾。ADX 從 15 爬到 22 的過程你分不出是真趨勢在啟動、還是假突破在製造動能。要靠 ADX 確認就得等 25 以上,那時候通常已經接近趨勢中段。
  • 「這是漲的趨勢還是跌的趨勢」。ADX 沒有方向。要方向就得看 `+DI` 跟 `−DI` 誰在上,或者搭 均線 之類的方向判斷。

任何濾網——不只 ADX——都是在「少進虧單」跟「錯過真訊號」之間做選擇,你把濾網收緊就一定會漏。ADX 濾網收得越緊,漏的越明顯的是那種「安靜的多頭趨勢」,價格默默上去但 ADX 從來沒破 20 過。這種型態在牛市末段特別多,是這個工具結構上的盲點。

常見問題

ADX 的週期 14 可以改嗎?
可以,但改之後你在教科書上、討論區上看到的「25 是趨勢閾值」這類數字就不再對得起來了。想拿短一點(例如 7)的通常是希望 ADX 反應快一點,代價是變得更雜訊——會在盤整期頻繁誤觸開關開啟。想拿長一點(例如 21)的通常是希望濾掉短促的假突破,代價是進場更慢。沒有實測就先留在 14。
ADX 跟 RSI、MACD 可以疊在一起用嗎?
可以,而且很常見。但要分清楚它們各自在回答什麼:RSI 講超買超賣(動能相對強弱)、MACD 講兩條均線的關係(趨勢方向 + 動能),ADX 只講強度。三個疊在一起如果都要滿足才進場,訊號會變得非常稀有——這通常代表你多濾了幾層之後回測數字漂亮,但實盤幾乎不下單。加濾網之前先想一下:這個濾網要濾的是哪一種假訊號?
TradingView Alert 要不要把 ADX 的當前值傳出去?
沒必要,除非你下游還要用到那個數字。ADX 開關是「進場條件」的一部分——當 regimeOn 為 false 時 Pine Script 根本不會觸發 strategy.entry,也就不會發出 alert。傳出去反而增加 payload 大小跟解析工作量。真的要 debug 有沒有觸發,用 plotshape 在圖表上標開關轉態的時刻比較直接。
回測績效加了 ADX 開關明顯變好,可以直接上實盤嗎?
先問自己一個問題:你的閾值是不是就是在這段歷史上調出來的?如果是,那個「變好」大概率是曲線擬合。至少要做兩件事——第一,把資料切成 in-sample / out-of-sample,只在 in-sample 調參數、out-of-sample 驗證;第二,用分位數而不是固定閾值,減少對特定期間 ADX 絕對值的依賴。做完這兩件事之後如果實盤還是跟不上,那可能就是市場結構已經跟你調參那段不一樣了。
把 ADX 開關關掉的那些期間,我的資金應該做什麼?
這個問題沒有一體適用的答案,取決於你有幾套策略。只有一套趨勢策略時,開關關掉就是空手等——資金放在穩定幣或活存都行。有一套趨勢 + 一套均值回歸時,兩套用同一條 ADX 但方向相反,理論上會輪班上場。單套策略想避開空手期,就只能接受它跑在盤整期會虧一些,或者接受它偶爾錯過真趨勢——這兩者取一,沒有第三個選項。

Get started

想把今天學到的東西自動化跑起來?

把加了 ADX 開關的 Pine 策略接上 webhook,交給 TVSBot——用你自己的交易所 API key、先 dry-run 驗開關真的有關掉、風控自己設。

免費開始使用