Skip to the content.

← All indicators

zeonta.klinger_volume_oscillator() — Difference of two EMAs of a trend-and-range-scaled volume force.

What it measures

Stephen Klinger’s more graded cousin of obv: rather than adding or subtracting a bar’s entire volume by direction alone, the ‘volume force’ is scaled by how the bar’s own range compares to the accumulated range since the trend last flipped — a half-hearted push contributes less than a bar where the range dominates the whole move.

Formula

VF = 100 * Volume * Trend * |2*(dm/cm) - 1|, dm = High-Low, cm accumulates dm since the trend last flipped; KVO = EMA(VF,fast) - EMA(VF,slow)

Parameters

Required inputs: high, low, close, volume

Parameter Default
fast 34
slow 55
signal_length 13

Returns

Column
KVO_34_55
KVOs_34_55

Usage

Examples run against the 300-bar OHLCV fixture in tests/data/ohlcv.csv, loaded as df. The output shown is the real output.

import pandas as pd
import zeonta

df = pd.read_csv('tests/data/ohlcv.csv', parse_dates=['date']).set_index('date')
zeonta.klinger_volume_oscillator(df['high'], df['low'], df['close'], df['volume']).tail(3)
               KVO_34_55    KVOs_34_55
date                                  
2024-10-25 -1.865480e+06 -1.177855e+06
2024-10-26 -1.784800e+06 -1.264561e+06
2024-10-27 -1.735052e+06 -1.331774e+06

Accessor form: df.zta.klinger_volume_oscillator(...)

How to read it

Read like macd: the crossover between KVO and its own signal line, or KVO crossing zero, confirming a price move with real volume conviction behind it.

Pitfalls

The trend/cm bookkeeping means a single missing bar has more reach than a plain EMA gap would — a NaN bar breaks the trend comparison for the bar right after it too, recovering fully only once two consecutive clean bars are available.

Reference

Formula source: https://tulipindicators.org/kvo