Indicators/probuilder · probacktest · proorder · proscreener

DPO

DPO in ProBuilder returns the Detrended Price Oscillator, which removes the long-term trend to expose shorter price cycles. Syntax, formula, examples.

Syntax

probuilder
DPO[N](price)

Parameters

NameTypeDefaultDescription
NintegernoneNumber of periods for the moving average. The oscillator isolates cycles shorter than roughly N bars; 20 and 21 are common values.
priceprice sourceclosePrice series the oscillator is computed on, for example close, open, high, low, or typicalprice.

Formula

code
DPO = price - Average[N](price)[N/2 + 1]

The N-period simple moving average is displaced back by N/2 + 1 bars, then subtracted from the current price. The result oscillates around zero.

How it works

Long-term trend tends to dominate raw price charts, hiding the shorter rhythmic swings within it. The DPO addresses this by comparing the current price to a moving average from roughly half a cycle earlier. Because the average is shifted back in time, it represents where the trend "was", and the difference isolates the deviation of price from that trend line.

The output is an unbounded oscillator centered on zero. Positive values mean price sits above the displaced average, negative values mean it sits below. The sequence of peaks and troughs in the DPO approximates the length of the dominant short-term cycle: measuring the bar distance between successive DPO troughs gives an estimate of the cycle period, information used to time entries within a larger trend.

The DPO is deliberately not a trend indicator. Its displacement removes the very component trend followers rely on, so it is normally paired with a directional filter that decides which side of the market to trade, while the DPO times the swings.

Examples

Example 1, Detecting a 10-bar DPO extreme (Indicator)

probuilder
// 21-period DPO on the typical price
myDPO = DPO[21](typicalprice)

// Find the highest DPO value of the previous 10 bars
value = 0
FOR i = 1 TO 10 DO
  if(myDPO[i] > value) THEN
    value = myDPO[i]
  ENDIF
NEXT

// Flag when the current DPO exceeds that maximum
if(myDPO > value) THEN
  extremebullish = 1
ELSE
  extremebullish = 0
ENDIF

RETURN extremebullish COLOURED(124,252,0)

Computes the 21-period DPO of the typical price and returns 1 whenever the current reading exceeds every reading of the previous 10 bars, marking a burst of upside deviation from trend.

Example 2, Zero-line cycle timing with a trend filter (ProBacktest)

probuilder
// Trade DPO upswings only in the direction of the 100-bar trend
trend = Average[100](close)
osc   = DPO[20](close)

IF NOT LongOnMarket AND close > trend AND osc CROSSES OVER 0 THEN
  BUY 1 CONTRACT AT MARKET
ENDIF

IF LongOnMarket AND osc CROSSES UNDER 0 THEN
  SELL AT MARKET
ENDIF

The moving average defines the trend direction and the DPO's zero-line crossings time the cycle swings inside it.

Example 3, Screening for deep cycle troughs (ProScreener)

probuilder
// Instruments whose DPO turned up from a 20-bar low
osc = DPO[21](close)
trough = osc[1] <= Lowest[20](osc)[1] AND osc > osc[1]
SCREENER[trough](osc AS "DPO")

Returns instruments where the DPO just turned upward from its lowest reading in 20 bars, a candidate cycle trough.

Interpretation

ConditionReading
DPO above zeroPrice is above its displaced average, the short cycle is in its upswing.
DPO below zeroPrice is below the displaced average, the cycle is in its downswing.
DPO peakCandidate short-term overbought point within the cycle.
DPO troughCandidate short-term oversold point within the cycle.

The distance between consecutive troughs (or peaks) estimates the dominant cycle length in bars. Because the DPO is unbounded and instrument-specific, its absolute level is not comparable across markets; extremes are judged relative to the oscillator's own recent history.

Common errors and gotchas

  • Reading the DPO as a trend signal. The indicator removes trend by construction. A rising DPO in a falling market says nothing about the larger direction, so pair it with a separate trend measure.
  • Wrong bracket usage. The period goes in square brackets and the price source in parentheses, DPO[21](close). Writing DPO(21, close) raises a syntax error.
  • Comparing levels across instruments. DPO values scale with the instrument's price and volatility. A reading of 5 can be extreme on one market and noise on another; normalize or compare only within one instrument.
  • Expecting alignment with the latest bars. The displaced average means the oscillator describes deviation from a trend measured half a window ago. Near sharp trend changes the DPO can lag the visual impression of the chart.
  • Cycle, dedicated cycle indicator with related objectives.
  • Average, the simple moving average used inside the DPO calculation.
  • ROC, rate of change, a percentage momentum oscillator.
  • Momentum, raw price change over N bars.
  • PriceOscillator, difference between two moving averages in percent.
  • RSI, bounded momentum oscillator with fixed 0 to 100 range.
  • CCI, deviation-based oscillator with similar mean-reversion use.
  • TypicalPrice, common input series for the DPO, (high + low + close) / 3.