Systemicalpha

Percentage Price Oscillator

systemic:core-ppoIndicatorsfunction1 cr

Inputs

NameTypeDescription
Slow Windowinteger| Property | Value |
Fast Windowinteger| Property | Value |
Signal Windowinteger| Property | Value |
Pricefloatarray| Property | Value |

Outputs

NameTypeDescription
PPOfloatarray| Property | Value |
Signalfloatarray| Property | Value |
Histogramfloatarray| Property | Value |

The Comparability Problem

Here's a scenario that frustrated early technical analysts: You're comparing two stocks. Stock A (500)hasaMACDof5.StockB(500) has a MACD of 5. Stock B (25) also has a MACD of 5. Which has stronger momentum?

The answer isn't obvious. For Stock A, that 5-point difference represents 1% of its price. For Stock B, it's 20%. The MACD gave you identical numbers for vastly different situations.

The PPO solves this by expressing momentum as a percentage:

PPO=EMAfast−EMAslowEMAslow×100\text{PPO} = \frac{\text{EMA}_{\text{fast}} - \text{EMA}_{\text{slow}}}{\text{EMA}_{\text{slow}}} \times 100

Now Stock A shows PPO = 1%, Stock B shows PPO = 20%. The comparison is immediate and meaningful.


Why Percentage Matters

ScenarioMACDPPOTruth
500stock,EMAsdifferby500 stock, EMAs differ by 551%Modest momentum
25stock,EMAsdifferby25 stock, EMAs differ by 5520%Very strong momentum
100stock,EMAsdifferby100 stock, EMAs differ by 333%Moderate momentum

💡 The PPO normalizes momentum. A PPO of 3% means the same thing whether you're analyzing Bitcoin, Apple stock, or a penny stock.


Calculation Flow

flowchart TD
    subgraph Input["Price Data"]
        P["Closing Prices"]
    end
    
    subgraph EMAs["Moving Averages"]
        F["Fast EMA (12)"]
        S["Slow EMA (26)"]
    end
    
    subgraph Calc["PPO Line"]
        D["(Fast − Slow) ÷ Slow × 100"]
    end
    
    subgraph Signal["Signal & Histogram"]
        SL["Signal Line (9-period EMA of PPO)"]
        H["Histogram = PPO − Signal"]
    end
    
    P --> F & S --> D --> SL
    D & SL --> H

Interpreting PPO Values

PPO ValueWhat It Means
> 0Fast EMA > Slow EMA → Bullish momentum
< 0Fast EMA < Slow EMA → Bearish momentum
RisingMomentum accelerating
FallingMomentum decelerating
Near 0Trend transitioning or ranging

Extreme Value Guidelines

PPO RangeInterpretation
> +3%Strong bullish momentum
+1% to +3%Moderate bullish
-1% to +1%Neutral / transitioning
-3% to -1%Moderate bearish
< -3%Strong bearish momentum

Trading Signals

Signal Line Crossover

EventSignalStrength
PPO crosses above SignalBuyStronger if PPO > 0
PPO crosses below SignalSellStronger if PPO < 0

Zero Line Crossover

EventSignalMeaning
PPO crosses above 0BullishFast overtakes slow—trend shift
PPO crosses below 0BearishFast falls below slow—trend shift

Divergence

TypePricePPOImplication
Bullish DivergenceLower lowHigher lowDowntrend weakening
Bearish DivergenceHigher highLower highUptrend weakening

Histogram: Momentum Acceleration

The histogram reveals how fast momentum is changing:

Histogram BehaviorMeaning
Positive & risingBullish momentum accelerating 📈
Positive & fallingBullish momentum slowing
Negative & fallingBearish momentum accelerating 📉
Negative & risingBearish momentum slowing

Missing Data

Both EMAs run over observed bars only and are reindexed back to the full input grid:

  • Closed-market gaps (e.g. weekends) stay gaps, and bridge. A missing input slot produces None on all three outputs — never a carried-forward (stale) PPO value, never a fabricated 0.0 that could be misread as a zero-line crossover.
  • Warm-up is None, never 0.0. The first window_slow − 1 observed bars are honestly undetermined for the PPO line; the Signal line needs window_signal further valid PPO readings on top of that before it settles.
  • A zero slow EMA has no percentage base. PPO divides by the slow EMA; on the rare bar where that EMA is exactly 0, the ratio is undefined and all three outputs go None at that slot — never a fabricated 0.0 or an unbounded spike.
  • Live mode. PPO returns exactly one value per output for a live request: the most recent slot's reading, or None if that slot is a closed-market gap or still inside warm-up.

Multi-Asset Momentum Comparison

The killer feature of PPO: Directly compare momentum across any assets.

flowchart LR
    subgraph Assets["Portfolio Assets"]
        A["BTC ($45,000)"]
        B["ETH ($2,500)"]
        C["SOL ($120)"]
    end
    
    subgraph PPOs["PPO Values"]
        PA["PPO: +2.1%"]
        PB["PPO: +4.5%"]
        PC["PPO: +1.2%"]
    end
    
    subgraph Decision["Rotation Signal"]
        R["Overweight ETH<br/>Underweight SOL"]
    end
    
    A --> PA
    B --> PB
    C --> PC
    PA & PB & PC --> R

Use case: Momentum rotation strategies—allocate to assets with highest PPO, reduce exposure to those with lowest.


Parameters

ParameterDefaultPurpose
Fast Window12Short-term EMA (recent momentum)
Slow Window26Long-term EMA (trend baseline)
Signal Window9EMA of PPO for crossover signals

Tuning Guidelines

Trading StyleSuggested Settings
Day trading5 / 13 / 8
Swing trading12 / 26 / 9 (default)
Position trading19 / 39 / 9

When PPO Excels

  • Multi-asset comparison — Comparing momentum across different-priced assets
  • Sector rotation — Identifying strongest/weakest sectors
  • Trending markets — Clear signals in directional moves
  • Portfolio construction — Momentum factor in allocation decisions

When PPO Struggles

  • Sideways markets — Whipsaws around zero line
  • Precise timing — Lagging indicator, signals come after moves start
  • Choppy volatility — Many false crossovers
  • Without confirmation — Best paired with trend filters

Summary

AspectDetail
Full NamePercentage Price Oscillator
Core InnovationNormalizes MACD to percentage for comparability
FormulaEMAfast−EMAslowEMAslow×100\frac{EMA_{fast} - EMA_{slow}}{EMA_{slow}} \times 100
RangeTypically -5% to +5% (unbounded)
Key SignalsSignal crossovers, zero crossovers, divergence
StrengthCross-asset momentum comparison
WeaknessLagging, whipsaws in ranges
Default Periods12 / 26 / 9

Further Reading


Indicator Assessment

%%{init: {"quadrantChart": {"titleFontSize": 14}, "themeVariables": {"quadrant1Fill": "#e8f5e9", "quadrant2Fill": "#fff3e0", "quadrant3Fill": "#ffebee", "quadrant4Fill": "#e3f2fd"}}}%%
quadrantChart
    title PPO Indicator Assessment
    x-axis Low Popularity --> High Popularity
    y-axis Low Reliability --> High Reliability
    quadrant-1 High potential  
    quadrant-2 Established
    quadrant-3 Niche
    quadrant-4 Widely used
    Stocks: [0.65, 0.70]
    Crypto: [0.55, 0.60]
DimensionStocksCryptoNotes
Popularity●●●◐○●●●○○Less known than MACD but gaining adoption
Reliability●●●●○●●●○○Percentage normalization improves cross-asset signals
Complexity●●○○○●●○○○MACD variant—same concepts apply
Versatility●●●●●●●●●●Excels at multi-asset comparison
Recent Interest●●●◐○●●●●○Growing with crypto portfolio strategies

Why PPO deserves higher ratings for multi-asset use: The percentage normalization solves a real problem that MACD cannot—comparing momentum across assets with vastly different price scales. This makes PPO the preferred choice for momentum rotation strategies.

Rendering diagrams...
© 2026 WanoLabs. All rights reservedAlpha build v0.1.5