◆ New — Strategy Validator, Code Fixer & Prop Compliance Checker are live. Try one free →
Home / Indicators / Detrended Price Oscillator (DPO)
Other indicator

Detrended Price Oscillator (DPO)

Strips out the longer-term trend so shorter price cycles are easier to see.

Illustrative diagram — not live market data.

What it is

The Detrended Price Oscillator (DPO) is a study that removes the broader trend from price so that shorter-term cycles and peaks/troughs become easier to see. Unlike most oscillators, it is not designed to track momentum or follow the current trend. Instead, it compares price to a moving average taken from earlier in the look-back window, which has the effect of "flattening out" the dominant trend. The result oscillates around a zero line and is plotted in a separate pane. It is purely an educational charting tool: it describes how price behaved relative to a trend-removed average, and it predicts nothing. As with any indicator, it is not buy/sell advice and trading carries risk of loss.

How it works

DPO uses a single length input, n. It first computes a simple moving average of price over n periods. The classic ("centered") formula compares the close from (n / 2) + 1 bars ago to the current n-period SMA: DPO = Close[(n / 2) + 1 bars ago] − SMA(Close, n). Equivalently, on the chart this average is shifted back in time so it sits in the middle of the look-back window rather than at the latest bar. Because of this displacement, the standard DPO deliberately ignores the most recent price action and "looks back" instead of tracking the live bar — its most recent plotted point is offset, and the last (n / 2) + 1 bars are typically not shown. The output swings above and below zero: above zero means price was higher than the trend-removed average at that point, below zero means it was lower. The larger the length, the longer the cycle it tries to isolate.

How traders read it

Common settings

A single length input, commonly 20 or 21 bars, is typical; some traders set it to roughly half the cycle they want to isolate. It is plotted in a separate pane with a zero line. The classic "centered" version displaces the plot back by (length / 2) + 1 bars; a non-centered variant plots at the current bar. Note that integer division means odd and even lengths can round the displacement differently.

Strengths

Pitfalls to watch

Pine v6 example

//@version=6
indicator("Detrended Price Oscillator (DPO)", shorttitle="DPO", overlay=false)

length = input.int(21, "Length", minval=2)
isCentered = input.bool(true, "Centered (displaced)")

ma = ta.sma(close, length)
barsBack = length / 2 + 1  // integer division

// Centered (classic) DPO shifts the plot back in time, so it is not real-time.
// Non-centered compares the current close to a displaced average at the latest bar.
dpo = isCentered ? close[barsBack] - ma : close - ma[barsBack]
plotOffset = isCentered ? -barsBack : 0

plot(dpo, "DPO", color=color.blue, offset=plotOffset)
hline(0, "Zero", color=color.gray, linestyle=hline.style_dashed)

Pro tip: If you want to study a specific cycle, set the length to roughly half its suspected period — but always treat any cycle you find as a past observation, not a prediction, and confirm whether your platform's DPO is displaced so you don't mistake an offset reading for current price. None of this is advice, and trading carries risk of loss.

Built an indicator from this? Run it through the Validator to catch look-ahead bias and repainting, or convert a strategy to Pine Script.

Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.

Catch the bug that compiles.Run auditGet Pro