Skip to content

Commit

Permalink
Bollinger Bands standard deviation calculation is different from othe…
Browse files Browse the repository at this point in the history
…r implementations (#106)

Fixes #105
  • Loading branch information
cinar authored Jun 24, 2022
1 parent 3ae5ce9 commit f282019
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 16 deletions.
40 changes: 40 additions & 0 deletions src/indicator/volatility/bollingerBands.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) 2022 Onur Cinar. All Rights Reserved.
// https://github.com/cinar/indicatorts

import { deepStrictEqual } from 'assert';
import { roundDigitsAll } from '../../helper/numArray';
import { bollingerBands } from './bollingerBands';

describe('Bollinger Bands', () => {
it('should be able to compute the bollinger bands', () => {
const closings = [
2, 4, 6, 8, 12, 14, 16, 18, 20, 2, 4, 6, 8, 12, 14, 16, 18, 20, 2, 4, 6,
8, 12, 14, 16, 18, 20, 2, 4, 6, 8, 12, 14, 16, 18, 20,
];

const expectedUpperBand = [
2, 3, 4, 5, 6.4, 7.67, 8.86, 10, 11.11, 10.2, 9.64, 9.33, 9.23, 9.43,
9.73, 10.13, 10.59, 11.11, 10.63, 22.78, 22.56, 22.45, 22.56, 22.84,
23.22, 23.72, 24.32, 23.9, 22.78, 22.56, 22.45, 22.56, 22.84, 23.22,
23.72, 24.32,
];

const expectedMiddleBand = [
2, 3, 4, 5, 6.4, 7.67, 8.86, 10, 11.11, 10.2, 9.64, 9.33, 9.23, 9.43,
9.73, 10.13, 10.59, 11.11, 10.63, 10.3, 10.5, 10.7, 11, 11.3, 11.5, 11.7,
11.9, 11.1, 10.3, 10.5, 10.7, 11, 11.3, 11.5, 11.7, 11.9,
];

const expectedLowerBand = [
2, 3, 4, 5, 6.4, 7.67, 8.86, 10, 11.11, 10.2, 9.64, 9.33, 9.23, 9.43,
9.73, 10.13, 10.59, 11.11, 10.63, -2.18, -1.56, -1.05, -0.56, -0.24,
-0.22, -0.32, -0.52, -1.7, -2.18, -1.56, -1.05, -0.56, -0.24, -0.22,
-0.32, -0.52,
];

const actual = bollingerBands(closings);
deepStrictEqual(roundDigitsAll(2, actual.upperBand), expectedUpperBand);
deepStrictEqual(roundDigitsAll(2, actual.middleBand), expectedMiddleBand);
deepStrictEqual(roundDigitsAll(2, actual.lowerBand), expectedLowerBand);
});
});
4 changes: 2 additions & 2 deletions src/indicator/volatility/mstd.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { mstd } from './mstd';
describe('Standard deviation', () => {
it('should be able to compute std', () => {
const values = [2, 4, 6, 8, 12, 14, 16, 18, 20];
const expected = [0, 0, 0, 2.236, 2.958, 3.162, 2.958, 2.236, 2.236];
const period = 4;
const expected = [0, 1, 1, 1, 2, 1, 1, 1, 1];
const period = 2;

const actual = mstd(period, values);
deepStrictEqual(roundDigitsAll(3, actual), expected);
Expand Down
22 changes: 8 additions & 14 deletions src/indicator/volatility/mstd.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2022 Onur Cinar. All Rights Reserved.
// https://github.com/cinar/indicatorts

import { sma } from '../trend/sma';

/**
* Moving strandard deviation function.
*
Expand All @@ -10,27 +12,19 @@
*/
export function mstd(period: number, values: number[]): number[] {
const result = new Array<number>(values.length);

let sum = 0;
const averages = sma(period, values);

for (let i = 0; i < values.length; i++) {
sum += values[i];
result[i] = 0;

if (i >= period - 1) {
if (i >= period) {
sum -= values[i - period];
}

const average = sum / period;
let ss = 0;
let sum = 0;

for (let j = 0; j < period; j++) {
ss += Math.pow(values[i - j] - average, 2);
for (let k = i - (period - 1); k <= i; k++) {
sum += (values[k] - averages[i]) * (values[k] - averages[i]);
}

result[i] = Math.sqrt(ss / period);
} else {
result[i] = 0;
result[i] = Math.sqrt(sum / period);
}
}

Expand Down

0 comments on commit f282019

Please sign in to comment.