Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BollingerBands: add option to use EMA vs. SMA #215

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 61 additions & 54 deletions src/volatility/BollingerBands.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,91 @@
"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<BollingerBandsOutput | undefined>;
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<BollingerBandsOutput | undefined>;
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;
}
})();

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);
}
});
}

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;
}