Pine Script Detrended Price Oscillator (DPO)

Master this unique oscillator in TradingView's Pine Script that removes trend, allowing you to clearly identify price cycles and potential reversals.

Subscribe now @ $99/month

What is the Detrended Price Oscillator (DPO)?

The Detrended Price Oscillator (DPO) is a technical indicator that attempts to remove the influence of trend from price action, making it easier to identify cycles and clear peaks and troughs. Unlike many oscillators that measure momentum (speed of price change), DPO focuses on the length of price movements relative to a past moving average, thereby isolating cyclical patterns. It oscillates around a zero line. When price is above its detrended moving average, DPO is positive; when it's below, DPO is negative.

In Pine Script, DPO is a valuable tool for traders looking to spot turning points within existing trends or to confirm cyclical patterns that might be obscured by a strong trend, enabling better timing for entries and exits.

Components and Calculation

The calculation of the Detrended Price Oscillator involves a Simple Moving Average (SMA) and a specific shifting mechanism:

  1. SMA Calculation: Calculate a Simple Moving Average of the closing price over a specified `length` (e.g., 20 periods).
    `SMA_Value = ta.sma(close, length)`
  2. Midpoint Shift: Determine the midpoint of the SMA period. This is `(length / 2) + 1` periods ago.
  3. DPO Formula: Subtract the SMA value from the closing price *`midpoint` periods ago*.
    `DPO = Current Close - SMA_Value[midpoint]`
    (Where `midpoint` is the number of bars to look back for the SMA value. For a 20-period SMA, the midpoint is `(20 / 2) + 1 = 11` bars ago.)

By subtracting a shifted moving average, DPO effectively "detrends" the price, allowing the cyclical components to stand out.

Basic Detrended Price Oscillator (DPO) Implementation in Pine Script

Pine Script v5 provides a built-in function `ta.dpo()` for calculating the Detrended Price Oscillator, simplifying its implementation.

//@version=5
indicator("My Detrended Price Oscillator", overlay=false) // overlay=false to plot in a separate pane

// Input for DPO length (period for the SMA)
length = input.int(20, title="DPO Length", minval=1)

// Calculate DPO value using the built-in function
// ta.dpo takes the source (close) and the length
dpoValue = ta.dpo(close, length)

// Plot the DPO line
plot(dpoValue, title="DPO", color=color.blue, linewidth=2)

// Plot the Zero Line
hline(0, "Zero Line", color.gray, linestyle=hline.style_solid)

// Optional: Add reference levels for visual clarity (these are not fixed like RSI)
hline(strategy.opentrades.size > 0 ? 0 : na, title="Buy Level", color=color.green, linestyle=hline.style_dotted) // Example placeholder
hline(strategy.opentrades.size < 0 ? 0 : na, title="Sell Level", color=color.red, linestyle=hline.style_dotted) // Example placeholder

Trend-Free View: DPO's main advantage is that it removes the overall trend, allowing you to focus purely on shorter-term cyclical patterns and overbought/oversold conditions within that cycle.

Practical DPO Trading Strategies

1. Peak and Trough Identification

DPO excels at pinpointing significant peaks and troughs in price cycles once the trend is removed. These can be used to anticipate turning points for entries and exits.

//@version=5
indicator("DPO Peak/Trough Signals", overlay=true)

length = input.int(20, title="DPO Length", minval=1)

dpoValue = ta.dpo(close, length)

plot(dpoValue, "DPO", color.blue, display=display.pane_only)
hline(0, "Zero Line", color.gray, linestyle=hline.style_solid, display=display.pane_only)

// Detect potential troughs (local minimums)
// DPO is lower than previous two bars, then current DPO is higher than previous
isTrough = dpoValue[2] > dpoValue[1] and dpoValue[1] < dpoValue and dpoValue[1] < 0 // And below zero line

// Detect potential peaks (local maximums)
// DPO is higher than previous two bars, then current DPO is lower than previous
isPeak = dpoValue[2] < dpoValue[1] and dpoValue[1] > dpoValue and dpoValue[1] > 0 // And above zero line

plotshape(isTrough, title="Cyclical Bottom", location=location.belowbar, color=color.new(color.green, 0), style=shape.triangleup, size=size.small)
plotshape(isPeak, title="Cyclical Top", location=location.abovebar, color=color.new(color.red, 0), style=shape.triangledown, size=size.small)

alertcondition(isTrough, "DPO Bullish Turn", "DPO detected a cyclical bottom and turned up.")
alertcondition(isPeak, "DPO Bearish Turn", "DPO detected a cyclical top and turned down.")

2. DPO Zero Line Crossover

The zero line in DPO represents the long-term trend. Crossovers indicate that the price has crossed above or below its shifted moving average, signifying a shift in the short-term cycle's direction relative to the removed trend.

These signals can be effective when the market is in a clear cycle but less reliable in strong, sustained trends without pullbacks.

//@version=5
strategy("DPO Zero Line Crossover Strategy", overlay=true)

length = input.int(20, title="DPO Length", minval=1)
dpoValue = ta.dpo(close, length)

plot(dpoValue, "DPO", color.blue, display=display.pane_only)
hline(0, "Zero Line", color.gray, linestyle=hline.style_solid, display=display.pane_only)

longSignal = ta.crossover(dpoValue, 0)
shortSignal = ta.crossunder(dpoValue, 0)

if (longSignal)
    strategy.entry("Long", strategy.long)

if (shortSignal)
    strategy.entry("Short", strategy.short)

3. DPO Divergence Strategy

Although DPO is designed to remove trend, divergence can still be observed between price and DPO, signaling potential reversals of the underlying cycle or a larger trend shift that DPO is beginning to pick up.

//@version=5
indicator("DPO Divergence Scanner", overlay=true)

length = input.int(20, title="DPO Length", minval=1)
dpoValue = ta.dpo(close, length)

plot(dpoValue, "DPO", color.blue)
hline(0, "Zero Line", color.gray, linestyle=hline.style_solid)

// Simple divergence detection (conceptual, robust detection requires advanced pivot logic)
// This is a simplified example focusing on price vs DPO divergence.

// Bullish Divergence (Price lower low, DPO higher low)
bullishDivergence = close[2] > close[1] and close[1] > close and dpoValue[2] < dpoValue[1] and dpoValue[1] < dpoValue

// Bearish Divergence (Price higher high, DPO lower high)
bearishDivergence = close[2] < close[1] and close[1] < close and dpoValue[2] > dpoValue[1] and dpoValue[1] > dpoValue

plotshape(bullishDivergence, title="Bullish Divergence", location=location.belowbar, color=color.new(color.green, 0), style=shape.triangleup, size=size.small)
plotshape(bearishDivergence, title="Bearish Divergence", location=location.abovebar, color=color.new(color.red, 0), style=shape.triangledown, size=size.small)

alertcondition(bullishDivergence, "Bullish DPO Divergence", "Potential bullish reversal based on DPO divergence.")
alertcondition(bearishDivergence, "Bearish DPO Divergence", "Potential bearish reversal based on DPO divergence.")

Optimizing DPO Performance

To get the most from the Detrended Price Oscillator in Pine Script:

Focus on Cycles: DPO is specifically designed to make market cycles more apparent by eliminating the linear trend. This can be very useful for swing trading.

Common DPO Pitfalls

Conclusion

The Detrended Price Oscillator (DPO) is a unique and insightful technical indicator in Pine Script for TradingView. By effectively removing the influence of trend from price, it allows traders to clearly identify and analyze underlying market cycles, making it particularly valuable for pinpointing potential peaks and troughs within price swings. Whether used for identifying cyclical turning points, recognizing zero-line crossovers for short-term momentum shifts, or spotting divergence, the DPO offers a distinct perspective on market dynamics. By understanding its calculation, thoughtfully tuning its parameters to match specific cycle lengths, and integrating it strategically with other technical analysis tools, you can leverage the DPO to enhance your trading decisions and better time your entries and exits.

Enhance Your Trading

Get a high-performance Pine Script analysis tool for actionable market insights, designed for traders on the move.

This strategy runs in live mode on TradingView, helping you identify potential opportunities.

Subscribe now @ $99/month