Appends three columns. Reads high and low — never the close, which is
what separates it from envelope (a percent band around a smoothed
close) and from starcBands (a volatility band around one).
What this is, exactly — and its relation to envelope
The arithmetic is envelope's applied to a different centre. With
medianPrice on the series, this study isenvelope({ column: 'medianPrice', maType, percent }), and a test
pins the two equal bar-for-bar rather than leaving that in prose.
The one place the identity can part company is maType: 'sma' over a
series with missing cells: envelope reads a column and takes the K2
engine's column door (rows, not contributors), while this study smooths a
derived array and takes the array door (period finite values). At the
default 'trima', and for every type but sma/ema, both routes are the
same call and the identity is bit-exact.
It ships anyway, for the reason this package ships vocabulary at all: the
composition needs a scratch column on the series (and a caller who does
not want medianPrice in their schema has to drop it again), the corpus
names the study (assessment §6.2), and "High Low Bands" on a chart legend
should not require the reader to reconstruct which column the envelope was
pointed at. The step-0 finding is recorded rather than hidden: nothing
new is computed here.
percent, spelled as envelope spells it
The half-width option is percent — the same number, in the same
units (percent of the centre), as envelope's percent, and the
same spelling on purpose. ChartIQ draws this indicator with the label
"shift"; the builder first followed that label, and the integrator
renamed it: a package that spells one knob two ways is a footgun, and a
consumer who has written envelope({ percent }) should be able to write
highLowBands({ percent }) without looking it up. (The type /
maType split is different in kind — those name different roles.)
The default maType is a choice, not a citation
The corpus entry names only "MA of median price × (1 ± shift%)" and does
not pin the average. The triangular moving average is the one this
study is conventionally drawn with — it double-smooths, which is the point
of a band you want to read as a slow envelope rather than a fast one — so
'trima' is the default. The whole shared MaType menu is
available; maType (not type) because the average is an ingredient
rather than the output.
TA-Lib has no High Low Bands, so the oracle is a pandas replication with
the analytic first valid bar asserted and the identity against
envelope-over-medianPrice checked on the TypeScript side, where the
two can be compared as the same expression rather than through a fixture.
Warm-up and edges
All three columns start together, at the chosen average's own first
bar over the derived median-price array. trima at period 10 lands at
bar 9; the composed types land later (see movingAverageValues).
The median price is a derived array, so it goes through the K2
engine's ARRAY door — every window type, sma included, waits for
periodfinite values, so a gap blanks every window containing it
rather than averaging a short window.
Multiplicative, not additive: the bands are a percentage of the
centre, so the channel is wider at higher prices. That makes the
study linear in price (scaling scales all three columns) but not
shift-equivariant — adding a constant moves the centre by it and the
bands by more. Both pinned by property tests, and it is the honest
consequence of a percent band (starcBands, an ATR band, is the
translation-invariant alternative).
A negative centre inverts the bands.middle × (1 + percent/100) is
belowmiddle when the centre is negative — reachable only by
redirecting high/low at columns that can go negative. Nothing
reorders them; envelope has the same property, and clamping would hide
an input problem rather than fix one.
No division, so no zero-denominator case: a flat stretch gives three
parallel lines a fixed percentage apart.
High Low Bands — a smoothed median price with bands a fixed percentage either side of it:
Appends three columns. Reads high and low — never the close, which is what separates it from envelope (a percent band around a smoothed close) and from starcBands (a volatility band around one).
What this is, exactly — and its relation to
envelopeThe arithmetic is
envelope's applied to a different centre. With medianPrice on the series, this study isenvelope({ column: 'medianPrice', maType, percent }), and a test pins the two equal bar-for-bar rather than leaving that in prose.The one place the identity can part company is
maType: 'sma'over a series with missing cells:envelopereads a column and takes the K2 engine's column door (rows, not contributors), while this study smooths a derived array and takes the array door (periodfinite values). At the default'trima', and for every type butsma/ema, both routes are the same call and the identity is bit-exact.It ships anyway, for the reason this package ships vocabulary at all: the composition needs a scratch column on the series (and a caller who does not want
medianPricein their schema has to drop it again), the corpus names the study (assessment §6.2), and "High Low Bands" on a chart legend should not require the reader to reconstruct which column the envelope was pointed at. The step-0 finding is recorded rather than hidden: nothing new is computed here.percent, spelled asenvelopespells itThe half-width option is
percent— the same number, in the same units (percent of the centre), as envelope'spercent, and the same spelling on purpose. ChartIQ draws this indicator with the label "shift"; the builder first followed that label, and the integrator renamed it: a package that spells one knob two ways is a footgun, and a consumer who has writtenenvelope({ percent })should be able to writehighLowBands({ percent })without looking it up. (Thetype/maTypesplit is different in kind — those name different roles.)The default
maTypeis a choice, not a citationThe corpus entry names only "MA of median price × (1 ± shift%)" and does not pin the average. The triangular moving average is the one this study is conventionally drawn with — it double-smooths, which is the point of a band you want to read as a slow envelope rather than a fast one — so
'trima'is the default. The whole shared MaType menu is available;maType(nottype) because the average is an ingredient rather than the output.TA-Lib has no High Low Bands, so the oracle is a pandas replication with the analytic first valid bar asserted and the identity against
envelope-over-medianPricechecked on the TypeScript side, where the two can be compared as the same expression rather than through a fixture.Warm-up and edges
trimaatperiod 10lands at bar 9; the composed types land later (see movingAverageValues). The median price is a derived array, so it goes through the K2 engine's ARRAY door — every window type,smaincluded, waits forperiodfinite values, so a gap blanks every window containing it rather than averaging a short window.middle × (1 + percent/100)is belowmiddlewhen the centre is negative — reachable only by redirectinghigh/lowat columns that can go negative. Nothing reorders them;envelopehas the same property, and clamping would hide an input problem rather than fix one.