Appends three columns. Reads high, low and close (the ATR needs all
three; the centre needs the close), each named by an option defaulting to
its DEFAULT_OHLCV name — the atr shape.
Three ATR channels ship, and they are genuinely different studies
The package now has keltner, atrBands and this one, and
the difference between them is worth stating once because "MA ± k·ATR"
describes all three:
study
centre
bands
columns
keltner
MA of typical price
±k·ATR
3
starcBands
MA of the close
±k·ATR
3
atrBands
an existing column as-is
±k·ATR
2
So starcBands is not a rename of atrBands: atrBands draws its bands
around a column the caller already has and appends no centre, while
this study computes a moving average that is not otherwise on the
series and therefore appends it (the keltner / bollinger
rule — a computed centre is worth a column, a copy of the caller's own
field is not).
It is, deliberately, the same arithmetic: composed by hand,
starcBands is movingAverage(…) followed by
atrBands({ column: <that average> }), and a test pins the two equal
bar-for-bar rather than leaving the claim in prose. The study ships
because that composition needs a scratch column and the corpus names this
one (assessment §6.2) — vocabulary over a kernel, which is what this
package is.
Which parameters — the formula is uncontested, the defaults are not
Stoller's construction (a simple average of the close, ±2 ATRs) is not in
dispute; the parameter set published with it is. Short centres (5–6 bars)
appear beside 20-bar ones, and atrPeriod 15 is the value most commonly
quoted with the study. What ships is period 20, atrPeriod 15,
multiplier 2, maType 'sma' — the 20 chosen to sit beside
keltner's and bollinger's rather than because a vendor
defaults to it, and every one of the four is an option. Said here rather
than left to be discovered from a chart that does not line up.
maType is the shared MaType menu, spelled maType because the
average is an ingredient rather than the output (the keltner side of
that split). TA-Lib has no STARC to arbitrate; the oracle is a pandas
replication over the same _atr_series reference TA-Lib's ATR is
asserted against, so the numbers are TA-Lib's ATR with arithmetic on top.
Warm-up: per column, not per study
The centre starts at the MA's own first bar (period − 1 for the window
types on gap-free input, later for the composed ones — see
movingAverageColumn); the ATR at bar atrPeriod (true range needs
a previous close, so a period-bar average of it lands one bar later than
a period-bar window would). The bands therefore start at the later of
the two, and the centre is emitted where it is genuinely defined rather
than masked back to them — the macd per-column rule. At the
defaults that is bar 19 for the centre and bar 19 for the bands (the MA's
19 beats the ATR's 15); at { period: 5, atrPeriod: 20 } the centre lands
at bar 4 and the bands at bar 20.
Edges
In the units of the price, like atr and keltner:
scaling every bar scales the whole channel, and adding a constant
translates it without changing its width. Both pinned by property tests.
A leading gap shifts the start rather than emptying the study.
An interior gap in the close is the Wilder asymmetry, and the two
halves genuinely differ. The centre takes the K2 engine's column
door, where 'sma' keeps core's count-window contract — minSamples
counts rows, and avgskips a missing cell — so the centre is
drawn straight through the gap (over period − 1 contributors on the
windows containing it). The ATR is Wilder over true range, which
reads the previous close, so the gap costs the next bar's true
range and the recursion never gives it back: the bands are defined on
the gap bar itself and blank from the one after it to the end. Measured
and pinned in study-missing-cells.test.ts. The other maTypes follow
their own rules (movingAverageColumn): the ema family skips
the bar, smma and kama propagate. A caller who needs continuity
fills before smoothing. The same asymmetry keltner documents,
though keltner's centre smooths a derived typical price and so
loses the bar where this one does not.
No division anywhere, so there is no zero-denominator case: a flat
stretch gives ATR = 0 and a zero-width channel, which is the honest
reading (contrast bollinger, whose zero-width statistical band
is emitted as undefined).
STARC Bands (Manning Stoller — Stoller Average Range Channel) — a moving average of the close with bands a multiple of the average true range away:
Appends three columns. Reads high, low and close (the ATR needs all three; the centre needs the close), each named by an option defaulting to its
DEFAULT_OHLCVname — the atr shape.Three ATR channels ship, and they are genuinely different studies
The package now has keltner, atrBands and this one, and the difference between them is worth stating once because "MA ± k·ATR" describes all three:
keltnerstarcBandsatrBandsSo
starcBandsis not a rename ofatrBands:atrBandsdraws its bands around a column the caller already has and appends no centre, while this study computes a moving average that is not otherwise on the series and therefore appends it (the keltner / bollinger rule — a computed centre is worth a column, a copy of the caller's own field is not).It is, deliberately, the same arithmetic: composed by hand,
starcBandsismovingAverage(…)followed byatrBands({ column: <that average> }), and a test pins the two equal bar-for-bar rather than leaving the claim in prose. The study ships because that composition needs a scratch column and the corpus names this one (assessment §6.2) — vocabulary over a kernel, which is what this package is.Which parameters — the formula is uncontested, the defaults are not
Stoller's construction (a simple average of the close, ±2 ATRs) is not in dispute; the parameter set published with it is. Short centres (5–6 bars) appear beside 20-bar ones, and
atrPeriod 15is the value most commonly quoted with the study. What ships isperiod 20,atrPeriod 15,multiplier 2,maType 'sma'— the 20 chosen to sit beside keltner's and bollinger's rather than because a vendor defaults to it, and every one of the four is an option. Said here rather than left to be discovered from a chart that does not line up.maTypeis the shared MaType menu, spelledmaTypebecause the average is an ingredient rather than the output (thekeltnerside of that split). TA-Lib has no STARC to arbitrate; the oracle is a pandas replication over the same_atr_seriesreference TA-Lib'sATRis asserted against, so the numbers are TA-Lib's ATR with arithmetic on top.Warm-up: per column, not per study
The centre starts at the MA's own first bar (
period − 1for the window types on gap-free input, later for the composed ones — see movingAverageColumn); the ATR at baratrPeriod(true range needs a previous close, so aperiod-bar average of it lands one bar later than aperiod-bar window would). The bands therefore start at the later of the two, and the centre is emitted where it is genuinely defined rather than masked back to them — the macd per-column rule. At the defaults that is bar 19 for the centre and bar 19 for the bands (the MA's 19 beats the ATR's 15); at{ period: 5, atrPeriod: 20 }the centre lands at bar 4 and the bands at bar 20.Edges
'sma'keeps core's count-window contract —minSamplescounts rows, andavgskips a missing cell — so the centre is drawn straight through the gap (overperiod − 1contributors on the windows containing it). The ATR is Wilder over true range, which reads the previous close, so the gap costs the next bar's true range and the recursion never gives it back: the bands are defined on the gap bar itself and blank from the one after it to the end. Measured and pinned instudy-missing-cells.test.ts. The othermaTypes follow their own rules (movingAverageColumn): theemafamily skips the bar,smmaandkamapropagate. A caller who needs continuity fills before smoothing. The same asymmetry keltner documents, thoughkeltner's centre smooths a derived typical price and so loses the bar where this one does not.ATR = 0and a zero-width channel, which is the honest reading (contrast bollinger, whose zero-width statistical band is emitted asundefined).