Direct answer
DPO (Detrended Price Oscillator) is calculated by taking a price series value from “now” and subtracting a moving average value that is shifted backward in time. The exact result depends on two user-chosen parameters: the moving-average length and the shift offset (often derived from the moving-average length).
A common way to express the mechanism is:
- Compute a moving average of the chosen price series over a selected length, denoted L.
- Compute a shift offset, denoted offset (commonly offset = floor(L/2) + 1 in many DPO definitions).
- For each time index t, calculate
- DPO(t) = Price(t) − MA(t − offset)
In plain terms: you compare the current price to where its moving-average “reference” would have been at an earlier time, effectively removing (detaching) the longer-term trend component.
Mechanism and definition
What “Detrended” means here
“Detrended” in DPO does not mean you run a statistical trend regression. Instead, DPO uses subtraction and time-shifting. The moving average represents a smooth version of the price over length L. By shifting that moving-average value backward, DPO tries to isolate a cyclical component around zero.
Inputs you must choose
To calculate DPO, you need:
- A price series: for example, close prices from each time period. Your calculation depends on which price you use.
- A moving-average method: typically a simple moving average (SMA), though some implementations use other moving averages.
- A moving-average length (L): the number of periods used to compute the moving average.
- A shift offset (offset): the time shift applied to the moving average. Many descriptions use offset = floor(L/2) + 1, but implementations vary, so you should confirm the definition used by your data or platform.
Step-by-step (with an explicit assumption)
Assume you use:
- Price = Close(t)
- Moving average = SMA over L periods
- Shift offset = offset = floor(L/2) + 1
Then:
- Compute SMA(t) for each time t where enough history exists:
- SMA(t) = (1/L) * sum_{i=0..L-1} Close(t − i)
- For a given time t where SMA(t − offset) exists, compute:
- DPO(t) = Close(t) − SMA(t − offset)
This makes the data requirement explicit: you cannot compute DPO until you have at least L + offset periods of history.
Evidence or example (self-checkable)
Example with a small, hypothetical dataset
Suppose:
- L = 5
- offset = floor(5/2) + 1 = 3
- price is Close
- moving average is SMA
At time index t:
- You compute SMA(t − 3) using the closes from (t − 3) back to (t − 3 − 4), i.e., 5 values total.
- Then you subtract that SMA from Close(t).
So DPO is not “Close(t) − SMA(t)”. The difference is the shift: you use SMA(t − offset).
How to independently verify your own calculation
To verify your DPO implementation without relying on any platform output:
- Choose L and the offset definition you will use.
- Compute the moving average series MA(t) directly from your price data.
- Shift that moving average backward by offset to create MA_shifted(t) = MA(t − offset).
- Compute DPO(t) = Price(t) − MA_shifted(t).
If your results match, you’ve confirmed the calculation mechanics.
Limitations and risks (material failure modes)
1) Implementation differences change the numeric output
DPO is easy to calculate, but the offset rule and sometimes the moving-average type can differ across definitions. Even if the formula looks similar, changing offset by one period can alter the oscillator.
2) Data availability creates a “warm-up” period
Because DPO uses a shifted moving average, you need enough historical points to compute MA(t − offset). Early values are undefined or depend on how your tool handles missing history.
3) DPO can behave unpredictably when the cycle assumption breaks
DPO is often interpreted as isolating cyclic behavior around zero. However, if price dynamics shift (for example, volatility regimes change or trend behavior changes), the subtraction-and-shift may no longer isolate the same component. That can lead to misleading interpretations of zero crossings or oscillation amplitude.
4) Market costs and execution can affect any downstream use
Even though this article is about calculation, it’s important to note a practical failure mode: if someone uses DPO for decisions, real-world outcomes are influenced by transaction costs, bid/ask spreads, and execution. Those factors are not part of the indicator math and can dominate the apparent signal.
Verification or next question
A useful next step is to compare two independent implementations:
- one computed manually from your spreadsheet using DPO(t) = Price(t) − MA(t − offset)
- and one produced by your chosen charting tool
Then check whether your tool uses the same price field, the same moving-average type, and the same offset definition. If your results differ, the most likely cause is a definition mismatch rather than a math error.
If you want, you can also examine how different L values change the oscillator’s timing and smoothness, because DPO’s behavior is highly dependent on its chosen parameters.