Swing Index (J. Welles Wilder Jr., New Concepts in Technical Trading
Systems, 1978) — one bar's "real" price change, once the open, the high,
the low and the previous bar are all taken into account:
K=max(A, B) R=A − 0.5·B+0.25·|prevClose − prevOpen|ifA is the largest ofA, B, D =B − 0.5·A+0.25·|prevClose − prevOpen|ifB is =D+0.25·|prevClose − prevOpen|ifD is
close − prevClose is the bar's net move, the thing a naive change
would report on its own.
0.5·(close − open) adds half of today's own body, so a bar that
closed strongly counts for more than one that merely drifted.
0.25·(prevClose − prevOpen) adds a quarter of yesterday's body,
which is what makes the index a swing rather than a per-bar reading:
it carries a memory of the last bar's conviction.
R normalises by a true-range-like quantity that leans on whichever
of the three spans dominated the bar, so the reading is comparable
across quiet and violent sessions.
K / limit scales by how large today's gap against yesterday's
close was, relative to the instrument's limit move — which is what
bounds the result to −100 … +100.
Wilder's own reading is that the sign of the swing, and the level a
sequence of them accumulates to (accumulativeSwingIndex), identify
the real trend under the noise of individual bars.
limit is REQUIRED, and that is the decision
T is a fact about the instrument, not about the study: it is the
exchange's daily limit move for that futures contract. The library cannot
guess it, and every possible default is wrong in a way that does not
announce itself:
Defaulting to 1 (what several charting packages do) silently
rescales the reading by the instrument's price level, so the ±100 bound
the study is defined by no longer holds and two symbols' swing indices
are no longer comparable — which is the one thing the parameter exists
to guarantee.
Defaulting to the bar's own range would make K/limit a ratio of
two quantities that both move with volatility, i.e. a different
indicator wearing this one's name.
So it is a required option, the way correlation's benchmark is:
the one number the caller must supply because only they know it. A caller
trading an instrument with no limit move (equities, FX, crypto) passes
the scale they want the reading normalised by — the instrument's typical
daily range is the usual choice — and the docstring, rather than a
default, is what tells them that is what they are choosing.
A limit of 0 is a division by zero and is rejected, along with
negatives and non-finite values.
Warm-up and edges
Bar 0 is undefined — every term reads yesterday. Length-preserving,
with a warm-up of exactly one row.
R === 0 → undefined.R is zero only when today's high, today's
low, yesterday's close and yesterday's open are the same number — a tape
that has not moved for two bars. K is zero on exactly those bars too,
so the expression is 0/0 however it is grouped, and nothing forces the
numerator to zero with it (it reads today's close and open, which a
redirected close need not place inside today's range). Pinned by a
test.
Scale-EQUIVARIANT, and invariant only if limit scales too. This is
the one study in the momentum group that is not scale-invariant, and the
true statement has to name the parameter: every term of the numerator,
of R and of K is a difference of two prices, so multiplying every
price by k multiplies all three by k — N/R is unchanged, and the
reading therefore scales by k through the K/limit factor alone.
Scaling limit by k as well leaves the reading unchanged. Both
halves are pinned as property tests, and they are what tells this study
apart from one that dropped the K/limit factor: that one would be
scale-invariant.
Shift-invariant. Every term being a difference of two prices, adding
a constant to every price changes nothing at all. Pinned.
No TA-Lib function, so the oracle is a pandas replication with the
analytic first-valid bar asserted, the ±100 bound checked at a limit
at least as large as the largest K, and two discriminating separations
measured (dropping the K/limit factor, and using the plain-range D
branch unconditionally).
Swing Index (J. Welles Wilder Jr., New Concepts in Technical Trading Systems, 1978) — one bar's "real" price change, once the open, the high, the low and the previous bar are all taken into account:
Every term, in words:
close − prevCloseis the bar's net move, the thing a naive change would report on its own.0.5·(close − open)adds half of today's own body, so a bar that closed strongly counts for more than one that merely drifted.0.25·(prevClose − prevOpen)adds a quarter of yesterday's body, which is what makes the index a swing rather than a per-bar reading: it carries a memory of the last bar's conviction.Rnormalises by a true-range-like quantity that leans on whichever of the three spans dominated the bar, so the reading is comparable across quiet and violent sessions.K / limitscales by how large today's gap against yesterday's close was, relative to the instrument's limit move — which is what bounds the result to −100 … +100.Wilder's own reading is that the sign of the swing, and the level a sequence of them accumulates to (accumulativeSwingIndex), identify the real trend under the noise of individual bars.
limitis REQUIRED, and that is the decisionTis a fact about the instrument, not about the study: it is the exchange's daily limit move for that futures contract. The library cannot guess it, and every possible default is wrong in a way that does not announce itself:1(what several charting packages do) silently rescales the reading by the instrument's price level, so the ±100 bound the study is defined by no longer holds and two symbols' swing indices are no longer comparable — which is the one thing the parameter exists to guarantee.K/limita ratio of two quantities that both move with volatility, i.e. a different indicator wearing this one's name.So it is a required option, the way correlation's
benchmarkis: the one number the caller must supply because only they know it. A caller trading an instrument with no limit move (equities, FX, crypto) passes the scale they want the reading normalised by — the instrument's typical daily range is the usual choice — and the docstring, rather than a default, is what tells them that is what they are choosing.A
limitof0is a division by zero and is rejected, along with negatives and non-finite values.Warm-up and edges
undefined— every term reads yesterday. Length-preserving, with a warm-up of exactly one row.R === 0→undefined.Ris zero only when today's high, today's low, yesterday's close and yesterday's open are the same number — a tape that has not moved for two bars.Kis zero on exactly those bars too, so the expression is0/0however it is grouped, and nothing forces the numerator to zero with it (it reads today's close and open, which a redirectedcloseneed not place inside today's range). Pinned by a test.limitscales too. This is the one study in the momentum group that is not scale-invariant, and the true statement has to name the parameter: every term of the numerator, ofRand ofKis a difference of two prices, so multiplying every price bykmultiplies all three byk—N/Ris unchanged, and the reading therefore scales bykthrough theK/limitfactor alone. Scalinglimitbykas well leaves the reading unchanged. Both halves are pinned as property tests, and they are what tells this study apart from one that dropped theK/limitfactor: that one would be scale-invariant.limitat least as large as the largestK, and two discriminating separations measured (dropping theK/limitfactor, and using the plain-rangeDbranch unconditionally).