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:
- 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)` - Midpoint Shift: Determine the midpoint of the SMA period. This is `(length / 2) + 1` periods ago.
- 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
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.
- Buy Signal: DPO forms a clear trough (a local minimum) and then turns upwards from below the zero line. This suggests the cyclical downside is exhausted.
- Sell Signal: DPO forms a clear peak (a local maximum) and then turns downwards from above the zero line. This suggests the cyclical upside is exhausted.
//@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.
- Buy Signal: DPO crosses above the zero line. This means current price is above its detrended average.
- Sell Signal: DPO crosses below the zero line. This means current price is below its detrended average.
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.
- Bullish Divergence: Price makes a lower low, but DPO makes a higher low. This indicates weakening bearish cyclical momentum.
- Bearish Divergence: Price makes a higher high, but DPO makes a lower high. This indicates weakening bullish cyclical momentum.
//@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:
- Parameter Tuning: The `length` parameter is crucial. It determines the cycle length you are isolating. A shorter length (e.g., 10-period) will highlight shorter cycles, while a longer length (e.g., 40-period) will highlight longer cycles. Experiment to match the `length` to the dominant cycle of the asset you are trading.
- Identify Cycle Lengths: Before using DPO, it's often helpful to visually identify recurring price cycles on your chart and then set the DPO `length` to approximately half of that cycle's length. This will position peaks/troughs at corresponding points in the cycle.
- Combine with Trend-Following Indicators: While DPO removes trend, it's generally not used for defining the main trend. It's best used in conjunction with a separate trend-following indicator (like an EMA or ADX) on the price chart to understand the broader context. Use DPO to time entries/exits *within* that confirmed trend.
- Confluence with Price Action: Always look for DPO signals to be confirmed by price action, such as candlestick patterns, breaks of short-term support/resistance, or volume spikes.
- Overbought/Oversold Zones: DPO doesn't have fixed overbought/oversold levels. You'll need to visually identify historical extreme highs and lows on the DPO for the asset you are trading to determine potential reversal zones.
Common DPO Pitfalls
- Not a Trend Indicator: DPO explicitly removes trend. Do not use it to determine the primary trend direction of an asset.
- Lag: Despite its detrending nature, DPO still uses a moving average, which introduces some lag. Signals will not be at the exact top or bottom of a cycle.
- Subjective Interpretation of Peaks/Troughs: Identifying "clear" peaks and troughs can sometimes be subjective, especially in choppy markets.
- False Signals in Strong Trends: While it removes trend, in extremely strong, parabolic trends, DPO might give premature reversal signals if not used with a proper trend filter.
- Not a Standalone Indicator: DPO should always be used as part of a broader trading system, complementing other indicators and price action analysis.
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