On this page
Price Oscillator (PPO) - Built-in Indicator Guide
Computes the Price Oscillator (PPO) as the percentage difference between two moving averages.
| Language | Indie Script v5 |
| Platform | TakeProfit |
| Category | Oscillators |
| Type | Built-in indicator |
| Author | TakeProfit |
| License | MIT |
| Documentation | Built-in indicators |
| Source file | Price Oscillator.indie5 |
Overview
The Price Oscillator (PPO) measures the percentage difference between a short-term and a long-term moving average of the source price. It is a momentum oscillator that helps identify trend strength, convergence/divergence, and potential reversals. When the short MA is above the long MA, the PPO is positive (bullish); when below, it is negative (bearish).
The indicator draws a single line oscillating around a zero level. Crossings above or below zero can signal changes in momentum. The PPO is similar to the MACD but expressed as a percentage, making it comparable across different price levels. Users can choose between simple (SMA) or exponential (EMA) moving averages.
How it works
- Select the moving average type based on the
exponentialparameter (EMA if true, SMA otherwise). - Compute the short-term moving average of the source over
short_lenbars. - Compute the long-term moving average of the source over
long_lenbars. - Subtract the long MA from the short MA to get the raw difference.
- Divide the difference by the long MA to obtain the relative difference.
- Multiply the result by 100 to express it as a percentage.
- Return the final value for plotting as a line.
Mathematical model
\[\text{PPO} = 100 \times \frac{\text{MA}_{\text{short}} - \text{MA}_{\text{long}}}{\text{MA}_{\text{long}}}\]Logic flow
flowchart TD
A["Start"] --> B{"Exponential?"}
B -- Yes --> C["Compute EMA short"]
B -- No --> D["Compute SMA short"]
C --> E["Compute EMA long"]
D --> F["Compute SMA long"]
E --> G["short - long"]
F --> G
G --> H["Divide by long"]
H --> I["Multiply by 100"]
I --> J["Return value"]
Parameters
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
short_len |
int | 10 | ≥ 1 | Short Length |
long_len |
int | 21 | ≥ 1 | Long Length |
src |
source | source.CLOSE | Source | |
exponential |
bool | false |
Code walkthrough
Indicator declaration and parameters
Lines 7-14 of Price Oscillator.indie5:
@indicator('PPO', format=format.PRICE) # Price Oscillator
@param.int('short_len', default=10, min=1, title='Short Length')
@param.int('long_len', default=21, min=1, title='Long Length')
@param.source('src', default=source.CLOSE, title='Source')
@param.bool('exponential', default=False)
@level(0, line_color=color.GRAY, title='Zero')
@plot.line(color=color.GREEN, title='OSC')
def Main(self, short_len, long_len, src, exponential):
The @indicator decorator sets the short name ‘PPO’ and the format to PRICE (though the output is a percentage, it is plotted as a line). The @param decorators define four user-adjustable inputs: short and long lengths, source price, and a boolean to choose between exponential and simple moving averages. A zero level line is drawn in gray, and the oscillator line is green.
Moving average selection
Lines 15-21 of Price Oscillator.indie5:
short, long = 0.0, 0.0
if exponential:
short = Ema.new(src, short_len)[0]
long = Ema.new(src, long_len)[0]
else:
short = Sma.new(src, short_len)[0]
long = Sma.new(src, long_len)[0]
Inside Main, two local variables short and long are initialized. If exponential is true, the indicator uses Ema.new to compute exponential moving averages; otherwise it uses Sma.new. Both algorithms return a series, and [0] retrieves the current bar’s value. This branching allows the user to switch between SMA and EMA without separate indicators.
PPO calculation and return
Lines 22-22 of Price Oscillator.indie5:
return 100 * divide(short - long, long)
The final line computes the PPO formula: 100 * divide(short - long, long). The divide function from indie.math safely handles division by zero (returning NaN if the denominator is zero). The result is returned as a single value, which is plotted as the green oscillator line, which is plotted as the green oscillator line.
Reading the chart
- The green line oscillates around the zero level.
- Positive values indicate the short MA is above the long MA (bullish momentum).
- Negative values indicate the short MA is below the long MA (bearish momentum).
- Crossings above zero can be interpreted as bullish signals; crossings below zero as bearish.
- The magnitude of the line reflects the strength of the divergence between the two MAs.
- The zero level is drawn as a gray horizontal line for reference.
Implementation notes
- The
dividefunction returnsmath.nanwhen the denominator (long MA) is zero, preventing division errors and causing the plot to skip that bar. - The indicator does not repaint; historical values remain fixed once the bar is closed.
- The
exponentialparameter defaults toFalse, so the default behavior uses simple moving averages. - The source can be any price field (close, open, high, low, hl2, etc.) via the
srcparameter.
FAQ
What is the difference between PPO and MACD?
Both measure the difference between two moving averages, but the PPO expresses it as a percentage of the long MA, making it scale-independent. The MACD uses an absolute difference and often includes a signal line and histogram.
How should I interpret a zero-line crossover?
When the PPO crosses above zero, the short MA moves above the long MA, suggesting bullish momentum. A cross below zero indicates bearish momentum. These signals are often used in conjunction with other analysis.
Can I change the source price or moving average type?
Yes. Use the ‘Source’ parameter to select any price (e.g., close, high, low) and toggle the ‘Exponential’ checkbox to switch between SMA and EMA. Both parameters are adjustable in the indicator settings.
Full source code
Indie Script v5, the built-in indicator as shipped with TakeProfit. Add it from the indicators menu or copy the code into the platform’s script editor.
# indie:lang_version = 5
from indie import indicator, format, param, source, level, color, plot
from indie.algorithms import Ema, Sma
from indie.math import divide
@indicator('PPO', format=format.PRICE) # Price Oscillator
@param.int('short_len', default=10, min=1, title='Short Length')
@param.int('long_len', default=21, min=1, title='Long Length')
@param.source('src', default=source.CLOSE, title='Source')
@param.bool('exponential', default=False)
@level(0, line_color=color.GRAY, title='Zero')
@plot.line(color=color.GREEN, title='OSC')
def Main(self, short_len, long_len, src, exponential):
short, long = 0.0, 0.0
if exponential:
short = Ema.new(src, short_len)[0]
long = Ema.new(src, long_len)[0]
else:
short = Sma.new(src, short_len)[0]
long = Sma.new(src, long_len)[0]
return 100 * divide(short - long, long)