Ehlers Decycler Indicator 1-2 Pole

Category: Indicators By: Iván González Created: April 30, 2026, 1:38 PM
April 30, 2026, 1:38 PM
Indicators
0 Comments

Introduction

The Ehlers Decycler is an elegant trend filter created by John Ehlers, a pioneer in applying digital signal processing techniques to financial markets. Unlike traditional moving averages that smooth all frequency components equally, the Decycler specifically removes short-term cyclical noise while preserving the underlying trend direction with minimal lag.

 

This indicator packages the two canonical formulations Ehlers describes — the 1-pole “Simple Decycler” and the 2-pole Decycler — into a single configurable script, with optional percentage bands that turn the trend into a soft channel for support/resistance reading.

 

A Note on Naming

There is a recurring source of confusion when reading material on the Decycler. In Ehlers’ original notation:

 

  • The Simple Decycler is the 1-pole version (single recursive term, 6 dB/octave roll-off).
  • The 2-pole Decycler uses a Butterworth high-pass of order 2 subtracted from price (12 dB/octave).

 

A previously published version on prorealcode by Nicolas — Ehlers Simple Decycler — implements the 2-pole formulation under the “Simple” name, with bands. That indicator is correct in its math; the naming is the only discrepancy. The version published in this article exposes both orders as a switch (poles = 1 or 2) so the user can compare them directly on the same chart and pick the right tool for the job.

 

Theory Behind the Decycler

Ehlers’ approach treats price as a signal composed of two parts:

 

  • Trend component — the slow-moving directional bias.
  • Cyclic component — oscillations around the trend.

 

Both formulations build a high-pass filter (which isolates cycles) and use the relationship low-pass = original − high-pass to extract the trend. The difference is the order of the filter, which controls how aggressively the cycles are removed.

 

1-Pole Variant (Simple Decycler)

The recursion is single-term and the result is the trend directly:

 

alpha   = (cos(2π/N) + sin(2π/N) − 1) / cos(2π/N)

Trend   = (alpha/2) × (src + src[1]) + (1 − alpha) × Trend[1]

 

This is a Butterworth low-pass of order 1. Roll-off is 6 dB/octave: cycles shorter than N are attenuated, cycles longer than N pass through nearly intact. Lag is minimal but a small amount of cyclical noise survives, particularly close to the cutoff.

 

2-Pole Variant

A second-order Butterworth high-pass is built explicitly and subtracted from price. The cutoff is corrected by √2 to keep the −3 dB point aligned with the requested period:

 

alpha   = (cos(2π/(N·√2)) + sin(2π/(N·√2)) − 1) / cos(2π/(N·√2))

HP      = (1 − α/2)² × (src − 2·src[1] + src[2])

        + 2·(1 − α) × HP[1]

        − (1 − α)²  × HP[2]

Trend   = src − HP

 

This is a sharper filter (12 dB/octave). It produces a smoother line with more lag but cleaner cycle rejection — useful when the goal is a stable trend reference rather than fast reaction.

 

Optional Percentage Bands

When showBands = 1, two additional lines are plotted at:

 

  • Upper = (1 + bandPct/100) × Trend
  • Lower = (1 − bandPct/100) × Trend

 

These bands turn the indicator into a Decycler channel. They behave as soft dynamic support and resistance: in calm regimes price oscillates inside the bands around the trend; in impulsive regimes price escapes one side, signalling regime change. Default is bandPct = 0.5 (a ±0.5% envelope). The bands are off by default to keep the trend-only use case clean.

 

Key Advantages Over Moving Averages

  • Selectivity — instead of averaging all frequencies uniformly (SMA) or weighting recent ones more heavily (EMA), the Decycler targets a specific cycle length and removes it surgically.
  • Lag — much lower than a Simple MA, and tighter than an EMA of comparable smoothness, especially in the 1-pole variant.
  • Theoretical basis — derived from digital signal processing; the cutoff has a precise meaning in cycle terms (the −3 dB period), not just a smoothing constant.
  • Choice of order — 1-pole for responsiveness, 2-pole for stability. Same indicator, two characters.

Practical Applications

  1. Trend direction filter — colour by slope (built in): only take longs when the line is green, only shorts when red.
  2. Crossover baseline — replace a standard MA in any crossover system; signals arrive earlier and are less prone to whipsaw at the cutoff edge.
  3. Decycler channel — enable bands and treat them as dynamic support/resistance. A close beyond the band of an established trend is an early signal of impulsive movement.
  4. 1-pole vs 2-pole comparison — drop two copies of the indicator on the same chart with different poles values to see how the order trades off lag against smoothness on the asset and timeframe you trade.

Indicator Configuration

The indicator exposes the following inputs:

 

  • length (default 60) — cutoff period; cycles shorter than this are removed.
  • src (default close) — source price.
  • poles (default 1) — 1 = Simple Decycler, 2 = Two-pole Decycler.
  • showBands (default 0) — 0 = trend only, 1 = enable percentage bands.
  • bandPct (default 0.5) — band shift in %, active when showBands = 1.
  • colorTrend (default 1) — colour the trend by its slope (green up, red down).

 

A higher length produces a smoother line but with more lag; a lower value makes the filter more responsive but allows more cyclical noise through. Ehlers recommends values between 40 and 100 for most markets.

Code

//-----------------------------------------------//
// PRC_Ehlers Decycler
// 1-pole and 2-pole variants with optional bands
// version = 2
// 30.04.2026
// Iván González @ www.prorealcode.com
// Sharing ProRealTime knowledge
//-----------------------------------------------//
//-----Inputs------------------------------------//
src = customclose
length = 60
pole1 = 1        // 1 = Simple Decycler (1-pole), 0 = Two-pole Decycler
showBands = 0    // 0 = trend only, 1 = enable percentage bands
bandPct = 0.5    // % band shift (active when showBands = 1)
cloud = 1        // 1 = fill area between price and trend
//-----------------------------------------------//
once PI = 3.14159265359
once MA = src

//-----1-pole Simple Decycler--------------------//
if pole1 then
   if barindex > length then
      transf = 360 / length
      cosine = COS(transf)
      if cosine <> 0 then
         alpha = (cosine + SIN(transf) - 1) / cosine
      else
         alpha = alpha[1]
      endif
      MA = alpha / 2 * (src + src[1]) + (1 - alpha) * MA[1]
   endif
endif

//-----2-pole Decycler---------------------------//
if not pole1 then
   if barindex > length then
      transf = 360 / (length * SQRT(2))
      cosine = COS(transf)
      if cosine <> 0 then
         alpha = (cosine + SIN(transf) - 1) / cosine
      else
         alpha = alpha[1]
      endif
      hp = SQUARE(1 - alpha/2) * (src - 2*src[1] + src[2]) + 2*(1-alpha)*hp[1] - SQUARE(1-alpha)*hp[2]
      MA = src - hp
   endif
endif

//-----Optional bands----------------------------//
if showBands then
   upperBand = (1 + bandPct/100) * MA
   lowerBand = (1 - bandPct/100) * MA
else
   upperBand = undefined
   lowerBand = undefined
endif

//-----------------------------------------------//
//-----Color configuration-----------------------//
r = 220
g = 220
b = 220
a = 0
if MA > MA[1] then
   r = 0
   g = 230
   b = 118
   a = 255
elsif MA < MA[1] then
   r = 255
   g = 82
   b = 82
   a = 255
endif

//-----------------------------------------------//
//----------------- Cloud -----------------------//
if cloud then
   colorbetween(src, MA, r, g, b, a*0.20)
endif
//-----------------------------------------------//
return MA coloured(r, g, b, a) style(line, 2) as "Decycler", upperBand coloured(19, 132, 132) style(line) as "Upper Band", lowerBand coloured(19, 132, 132) style(line) as "Lower Band"

Download
Filename: PRC_Ehlers-Decycler-1-2P.itf
Downloads: 11
Iván González Master
Currently debugging life, so my bio is on hold. Check back after the next commit for an update.
Author’s Profile

Comments

Logo Logo
Loading...