Volatility, bands and ranges
True range, bands, channels and choppiness measures. See the indicator reference for how to read a signature, and Indicators for the construction and guarding rules.
BBW
Bollinger BandWidth as TradingView plots it: the distance between the bands in percent of their basis, (upper − lower) / basis × 100 (4.5 for bands 4.5% apart).
new BBW(sourceIndicator: Indicator<number>, period: number, stdDevMultiplier: number = 2)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
sourceIndicator |
Indicator<number> |
required | The number stream. |
period |
number |
required | Bollinger length. |
stdDevMultiplier |
number |
2 |
Standard deviations between the basis and each band (2 by default). |
- Input: A number stream whose values are never
undefined. - Value (
getValue()afterhasValue()):number | undefined - Warm-up: First value on candle
period.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new BBW(candles.close, 20);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value === undefined) return;
manager.debugLog('BBW', value);
});
BBWP
Bollinger BandWidth Percentile, The_Caretaker's: the share, in percent, of the previous lookback BBW values (fewer at first) lower than or equal to the current one.
new BBWP(sourceIndicator: Indicator<number>, period: number, lookback: number)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
sourceIndicator |
Indicator<number> |
required | The number stream. |
period |
number |
required | Bollinger length. |
lookback |
number |
required | How many BBW values to rank against. |
- Input: A number stream whose values are never
undefined. - Value (
getValue()afterhasValue()):number | undefined - Warm-up: First value on candle
period + 2.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new BBWP(candles.close, 13, 252);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value === undefined) return;
manager.debugLog('BBWP', value);
});
Bollinger
Bollinger bands: the maPeriod SMA (mean) plus and minus stdDevMultiplier standard deviations.
new Bollinger(sourceIndicator: Indicator<number>, maPeriod: number = 20, stdDevMultiplier: number = 2)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
sourceIndicator |
Indicator<number> |
required | The number stream (usually closes). |
maPeriod |
number |
20 |
Window length. |
stdDevMultiplier |
number |
2 |
Band width in standard deviations. |
- Input: A number stream whose values are never
undefined(candles.close). - Value (
getValue()afterhasValue()):BollingerValueupper: number | undefinedmean: number | undefinedlower: number | undefined
- Warm-up: Fields are
undefineduntilmaPeriodcandles have been seen.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new Bollinger(candles.close, 20, 2);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value.upper === undefined || value.lower === undefined || value.mean === undefined) return;
manager.debugLog('upper', value.upper, 'mean', value.mean, 'lower', value.lower);
});
Chop
Choppiness index: 100 × log10(Σ TR / (highest high − lowest low)) / log10(period); high values mean a sideways market.
new Chop(highIndicator: Indicator<number | undefined>, lowIndicator: Indicator<number | undefined>, trIndicator: Indicator<number | undefined>, period: number)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
highIndicator |
Indicator<number | undefined> |
required | The high stream (candles.high). |
lowIndicator |
Indicator<number | undefined> |
required | The low stream (candles.low). |
trIndicator |
Indicator<number | undefined> |
required | The true range (new TR(candles)). |
period |
number |
required | Window length. |
- Input: Three number streams: highs, lows and true range.
- Value (
getValue()afterhasValue()):number | undefined - Warm-up: First value on candle
period; not finite when the window's highest high equals its lowest low.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new Chop(candles.high, candles.low, new TR(candles), 14);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value === undefined || !Number.isFinite(value)) return;
manager.debugLog('chop', value);
});
Choppy
Counts monotonic runs among the last six closes: type rates the current run ('none', 'weak', 'medium', 'strong') and line counts trending candles among the last ten.
new Choppy(candleIndicator: Indicator<Candle>)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
candleIndicator |
Indicator<Candle> |
required | The candle series. |
- Input: The candle series.
- Value (
getValue()afterhasValue()):ChoppyValuetype: ChoppyTypeline: number
ChoppyTypeis'none' | 'weak' | 'medium' | 'strong'.- Warm-up:
typeis'none'until six candles have been seen;linefills over ten candles.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new Choppy(candles);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
manager.debugLog('run', value.type, 'trending candles out of 10', value.line);
});
DC
Donchian channel MIDLINE: (highest high + lowest low) / 2 over extremePeriod candles, current included. For the upper and lower channel lines use Extreme.
new DC(candleIndicator: Indicator<Candle>, extremePeriod: number)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
candleIndicator |
Indicator<Candle> |
required | The candle series. |
extremePeriod |
number |
required | Window length, current candle included. |
- Input: The candle series.
- Value (
getValue()afterhasValue()):number - Warm-up: A number from the first candle (partial window until
extremePeriodcandles).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new DC(candles, 20);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
manager.debugLog('Donchian midline', value);
});
FindMarketBottom
Williams VIX Fix bottom finder: wvf = 100 × (highest close over 22 − low) / highest close, with Bollinger and percentile ranges; alert is true when wvf spikes above them.
new FindMarketBottom(candleIndicator: ICandleIndicator, bollingerLength: number = 20, bollingerMult: number = 2.0, percentileLookback: number = 50, highPercentile: number = 0.85, lowPercentile: number = 1.01)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
candleIndicator |
ICandleIndicator |
required | The candle series. |
bollingerLength |
number |
20 |
Bollinger length on wvf. |
bollingerMult |
number |
2.0 |
Bollinger multiplier. |
percentileLookback |
number |
50 |
Look-back for the percentile range. |
highPercentile |
number |
0.85 |
Upper range factor (0.85 = 85% of the highest wvf). |
lowPercentile |
number |
1.01 |
Lower range factor. |
- Input: The candle series.
- Value (
getValue()afterhasValue()):FindMarketBottomValuewvf: number | undefinedupperBand: number | undefinedmidLine: number | undefinedlowerBand: number | undefinedrangeHigh: number | undefinedrangeLow: number | undefinedalert: boolean
- Warm-up:
alertis always a boolean; band fields areundefineduntilbollingerLengthandpercentileLookbackvalues exist (about 50 candles with the defaults).
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new FindMarketBottom(candles);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value.alert) manager.debugLog('possible bottom, wvf', value.wvf);
});
KeltnerChannels
Keltner channels: an EMA of the close (middle) plus and minus multiplier ATRs.
new KeltnerChannels(candleIndicator: ICandleIndicator, period: number = 20, multiplier: number = 2, atrPeriod: number = 10)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
candleIndicator |
ICandleIndicator |
required | The candle series. |
period |
number |
20 |
EMA length. |
multiplier |
number |
2 |
Channel width in ATRs. |
atrPeriod |
number |
10 |
ATR length. |
- Input: The candle series.
- Value (
getValue()afterhasValue()):{ upper: number | undefined; middle: number | undefined; lower: number | undefined; }upper: number | undefinedmiddle: number | undefinedlower: number | undefined
- Warm-up: Fields are
undefineduntil both the EMA (candleperiod) and the ATR (candleatrPeriod + 1) are ready.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new KeltnerChannels(candles, 20, 2, 10);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value.upper === undefined || value.lower === undefined) return;
manager.debugLog('upper', value.upper, 'lower', value.lower);
});
TR
True range: max(high − low, |high − previous close|, |low − previous close|). Smooth it with RMA for an ATR (TradingView's ta.atr).
new TR(candleIndicator: Indicator<Candle>, handleNa: boolean = true)
| Parameter | Type | Default | Meaning |
|---|---|---|---|
candleIndicator |
Indicator<Candle> |
required | The candle series. |
handleNa |
boolean |
true |
Count high − low on the first candle, which has no previous close (true by default, as TradingView's ATR does); false leaves that candle undefined, as its DMI does. |
- Input: The candle series.
- Value (
getValue()afterhasValue()):number | undefined - Warm-up: A value from the first candle; from the second with
handleNaset tofalse.
const symbol = 'BTC';
const candles = manager.getIntervalData(symbol, 60);
const indicator = new TR(candles);
manager.onIntervalCandle(symbol, 60, () => {
if (!indicator.hasValue()) return;
const value = indicator.getValue();
if (value === undefined) return;
manager.debugLog('true range', value);
});