The Vortex Indicator (Etienne Botes & Douglas Siepman, Technical
Analysis of Stocks & Commodities, January 2010) — the trend-direction
companion to Wilder's DI pair, measured across consecutive bars
instead of along them:
Where directionalMovement asks how far a bar moved beyond the
previous bar's own high or low — so at most one of its legs is non-zero —
the vortex crosses them, and both legs are always positive. What
carries the signal is their ratio: a rising market puts today's high a
long way above yesterday's low (+VM large) while today's low stays close
under yesterday's high (−VM small), so +VI climbs above −VI and the
crossings mark the turns. Normalising both by the same true-range total is
what makes the pair comparable across instruments.
Reads high, low and close, each named by an option defaulting to its
DEFAULT_OHLCV column — the atr shape. The close is there for the
true range only.
Definition
The authors' original, replicated in pandas in the oracle — TA-Lib has
no vortex function, so there is nothing to be bar-for-bar with. The two
choices worth naming, both the published ones: the absolute values on
the movement legs (they matter only on a bar that gaps clear of its
predecessor, where the crossing distance would come out negative), and
TR as Wilder's true range rather than the plain bar range — the same
trueRangeValues the ATR family uses, which the oracle asserts is
talib.TRANGE bit-for-bit.
Both columns emit from bar period: +VM, −VM and TR all read the
previous bar, so a period-bar sum of them needs period + 1 bars.
The ratio is taken between two rolling means rather than two sums —
they share the divisor period, so it cancels exactly, and going through
rollingMeanValues is what buys the strict window rule (every one
of the period cells must be finite) instead of a hand-rolled sum that
would have to restate it.
Edges
Σ TR = 0 → undefined. Unlike directionalMovement's DX,
the numerator is not forced to zero with it: a window of perfectly
flat bars can still be preceded by a bar at a different level, leaving
+VM positive over a zero total range. That is a genuine x/0, so the
guard is real (and, unlike the guard commodityChannelIndex deleted, it
changes an answer — the alternative is ±Infinity reaching
withColumn).
Both columns are non-negative — every term is an absolute value over
a non-negative range — and scale-invariant: a ratio of price
differences. Both pinned by property tests.
Not bounded by 1.+VI and −VI typically live around 0.8–1.2 and
sum to roughly 2, but neither is a fraction of anything: a bar can gap
far enough that |high − prevLow| exceeds its own true range. Nothing
is clamped.
A gap costs at most period + 1 bars and then recovers, unlike the
Wilder family's carry-to-the-end: these are windows, not recursions. The
two legs lose different rows, which is worth knowing when reading them
as a pair. Measured on an 80-bar series with one missing cell at bar 40
and period 14: a missing high blanks +VI over bars 40–53 (it
costs +VM on bar 40 and the true range with it) and −VI over 40–54
(−VM on bar 41 reads that high as prevHigh); a missing low
is the mirror image; a missing close costs only the true range on
bar 41, so both legs blank over 41–54.
The Vortex Indicator (Etienne Botes & Douglas Siepman, Technical Analysis of Stocks & Commodities, January 2010) — the trend-direction companion to Wilder's
DIpair, measured across consecutive bars instead of along them:Where directionalMovement asks how far a bar moved beyond the previous bar's own high or low — so at most one of its legs is non-zero — the vortex crosses them, and both legs are always positive. What carries the signal is their ratio: a rising market puts today's high a long way above yesterday's low (
+VMlarge) while today's low stays close under yesterday's high (−VMsmall), so+VIclimbs above−VIand the crossings mark the turns. Normalising both by the same true-range total is what makes the pair comparable across instruments.Reads high, low and close, each named by an option defaulting to its
DEFAULT_OHLCVcolumn — the atr shape. The close is there for the true range only.Definition
The authors' original, replicated in pandas in the oracle — TA-Lib has no vortex function, so there is nothing to be bar-for-bar with. The two choices worth naming, both the published ones: the absolute values on the movement legs (they matter only on a bar that gaps clear of its predecessor, where the crossing distance would come out negative), and
TRas Wilder's true range rather than the plain bar range — the same trueRangeValues the ATR family uses, which the oracle asserts istalib.TRANGEbit-for-bit.Both columns emit from bar
period:+VM,−VMandTRall read the previous bar, so aperiod-bar sum of them needsperiod + 1bars.The ratio is taken between two rolling means rather than two sums — they share the divisor
period, so it cancels exactly, and going through rollingMeanValues is what buys the strict window rule (every one of theperiodcells must be finite) instead of a hand-rolled sum that would have to restate it.Edges
Σ TR = 0→undefined. Unlike directionalMovement'sDX, the numerator is not forced to zero with it: a window of perfectly flat bars can still be preceded by a bar at a different level, leaving+VMpositive over a zero total range. That is a genuinex/0, so the guard is real (and, unlike the guardcommodityChannelIndexdeleted, it changes an answer — the alternative is±InfinityreachingwithColumn).+VIand−VItypically live around 0.8–1.2 and sum to roughly 2, but neither is a fraction of anything: a bar can gap far enough that|high − prevLow|exceeds its own true range. Nothing is clamped.period + 1bars and then recovers, unlike the Wilder family's carry-to-the-end: these are windows, not recursions. The two legs lose different rows, which is worth knowing when reading them as a pair. Measured on an 80-bar series with one missing cell at bar 40 andperiod 14: a missing high blanks+VIover bars 40–53 (it costs+VMon bar 40 and the true range with it) and−VIover 40–54 (−VMon bar 41 reads that high asprevHigh); a missing low is the mirror image; a missing close costs only the true range on bar 41, so both legs blank over 41–54.