diff --git a/src/volatility/BollingerBands.ts b/src/volatility/BollingerBands.ts index 7e5e18d9..627789f5 100644 --- a/src/volatility/BollingerBands.ts +++ b/src/volatility/BollingerBands.ts @@ -1,56 +1,63 @@ -"use strict" +"use strict"; import { Indicator, IndicatorInput } from '../indicator/indicator'; -import { SMA } from '../moving_averages/SMA'; +import { SMA } from '../moving_averages/SMA'; +import { EMA } from '../moving_averages/EMA'; import { SD } from '../Utils/SD'; + export class BollingerBandsInput extends IndicatorInput { - period : number; - stdDev : number; - values : number[]; -}; + // Number of values to consider for the moving average and standard deviation. Typically 20. + period: number; + // How many standard deviations between the bands and the moving average. Typically 2. + stdDev: number; + // Whether to use Exponential Moving Average, or Simple Moving Average to calculate the mean. + useEMA: boolean; + // Initial values + values: number[]; +} export class BollingerBandsOutput extends IndicatorInput { - middle : number; - upper : number; - lower :number; - pb:number; -}; + middle: number; + upper: number; + lower: number; + // Percent bandwidth + pb: number; +} export class BollingerBands extends Indicator { - generator:IterableIterator; - constructor(input:BollingerBandsInput) { - super(input); - var period = input.period - var priceArray = input.values; - var stdDev = input.stdDev; - var format = this.format; - - var sma,sd; + generator: IterableIterator; + public result = []; - this.result = []; + constructor(input: BollingerBandsInput) { + super(input); + const period = input.period; + const priceArray = input.values; + const stdDev = input.stdDev; + const format = this.format; - sma = new SMA({period : period, values :[], format : (v) => {return v}}); - sd = new SD({period : period, values : [], format : (v) => {return v}}); + const maType = input.useEMA ? EMA : SMA; + const ma = new maType({ period, values: [], format: v => v }); + const sd = new SD({ period, values: [], format: v => v }); - this.generator = (function* (){ - var result; - var tick; - var calcSMA; - var calcsd; + this.generator = (function* () { + let result; + let tick; + let calcMA; + let calcSD; tick = yield; while (true) { - calcSMA = sma.nextValue(tick); - calcsd = sd.nextValue(tick); - if(calcSMA){ - let middle = format(calcSMA); - let upper = format(calcSMA + (calcsd * stdDev)); - let lower = format(calcSMA - (calcsd * stdDev)); - let pb:number = format((tick - lower) / (upper - lower)); + calcMA = ma.nextValue(tick); + calcSD = sd.nextValue(tick); + if (calcMA) { + const middle = format(calcMA); + const upper = format(calcMA + (calcSD * stdDev)); + const lower = format(calcMA - (calcSD * stdDev)); + const pb: number = format((tick - lower) / (upper - lower)); result = { - middle : middle, - upper : upper, - lower : lower, - pb : pb - } + middle, + upper, + lower, + pb, + }; } tick = yield result; } @@ -58,9 +65,9 @@ export class BollingerBands extends Indicator { this.generator.next(); - priceArray.forEach((tick) => { - var result = this.generator.next(tick); - if(result.value != undefined){ + priceArray.forEach(tick => { + const result = this.generator.next(tick); + if (result.value != undefined) { this.result.push(result.value); } }); @@ -68,17 +75,17 @@ export class BollingerBands extends Indicator { static calculate = bollingerbands; - nextValue(price:number):BollingerBandsOutput | undefined { + nextValue(price: number): BollingerBandsOutput | undefined { return this.generator.next(price).value; - }; + } } -export function bollingerbands(input:BollingerBandsInput):BollingerBandsOutput[] { - Indicator.reverseInputs(input); - var result = new BollingerBands(input).result; - if(input.reversedInput) { - result.reverse(); - } - Indicator.reverseInputs(input); - return result; - }; +export function bollingerbands(input: BollingerBandsInput): BollingerBandsOutput[] { + Indicator.reverseInputs(input); + const result = new BollingerBands(input).result; + if (input.reversedInput) { + result.reverse(); + } + Indicator.reverseInputs(input); + return result; +}