// Licensed under the Apache License, Version 2.0 // © mihakralj //@version=6 indicator("Percentage Volume Oscillator (PVO)", "PVO", overlay=false) //@function Calculates Percentage Volume Oscillator //@param vol Volume series //@param fast_period Fast period for volume MA //@param slow_period Slow period for volume MA //@param signal_period Signal line smoothing period //@returns tuple with [pvo, signal, histogram] values //@optimized Beta precomputation for EMA warmup compensation pvo(series float vol, simple int fast_period, simple int slow_period, simple int signal_period) => float vol_val = nz(vol, 0.0) float fast_alpha = 2.0 / (fast_period + 1) float slow_alpha = 2.0 / (slow_period + 1) float signal_alpha = 2.0 / (signal_period + 1) float fast_beta = 1.0 - fast_alpha float slow_beta = 1.0 - slow_alpha float signal_beta = 1.0 - signal_alpha float slowest_beta = math.max(fast_beta, slow_beta, signal_beta) var bool warmup = true var float e_fast = 1.0 var float e_slow = 1.0 var float e_signal = 1.0 var float e_slowest = 1.0 var float fast_ema = 0.0 var float slow_ema = 0.0 var float signal_ema = 0.0 fast_ema := fast_alpha * (vol_val - fast_ema) + fast_ema slow_ema := slow_alpha * (vol_val - slow_ema) + slow_ema if warmup e_fast *= fast_beta e_slow *= slow_beta e_signal *= signal_beta e_slowest *= slowest_beta warmup := e_slowest > 1e-10 float c_fast = warmup ? 1.0 / (1.0 - e_fast) : 1.0 float c_slow = warmup ? 1.0 / (1.0 - e_slow) : 1.0 float c_signal = warmup ? 1.0 / (1.0 - e_signal) : 1.0 float fast_comp = c_fast * fast_ema float slow_comp = c_slow * slow_ema float pvo_val = slow_comp != 0.0 ? ((fast_comp - slow_comp) / slow_comp) * 100.0 : 0.0 signal_ema := signal_alpha * (pvo_val - signal_ema) + signal_ema float signal_val = c_signal * signal_ema float histogram_val = pvo_val - signal_val [pvo_val, signal_val, histogram_val] // ---------- Main loop ---------- // Inputs i_fast_period = input.int(12, "Fast Period", minval=1) i_slow_period = input.int(26, "Slow Period", minval=1) i_signal_period = input.int(9, "Signal Period", minval=1) // Calculation [pvo_value, signal_value, histogram_value] = pvo(volume, i_fast_period, i_slow_period, i_signal_period) // Plot plot(pvo_value, "PVO", color=color.yellow, linewidth=2) plot(signal_value, "Signal", color=color.red, linewidth=2) plot(histogram_value, "Histogram", color=color.blue, linewidth=2, style=plot.style_histogram) hline(0, "Zero Line", color.gray)