Skip to content

Commit

Permalink
refactor(util): Change faster prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
bennycode committed Oct 24, 2021
1 parent cfe9833 commit d489437
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 13 deletions.
48 changes: 47 additions & 1 deletion src/SMA/SMA.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Big from 'big.js';
import {NotEnoughDataError, SMA} from '..';
import {NotEnoughDataError, SMA, FasterSMA} from '..';

import prices from '../test/fixtures/prices.json';
import testData from '../test/fixtures/SMA/LTC-USDT-1m.json';
Expand Down Expand Up @@ -126,3 +126,49 @@ describe('SMA', () => {
});
});
});

describe('FasterSMA', () => {
describe('getResult', () => {
it('calculates the moving average based on the last 5 prices', () => {
// Test data taken from:
// https://github.com/TulipCharts/tulipindicators/blob/v0.8.0/tests/untest.txt#L359-L361
const prices = [
81.59, 81.06, 82.87, 83.0, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29,
];
const expectations = [
'82.426',
'82.738',
'83.094',
'83.318',
'83.628',
'83.778',
'84.254',
'84.994',
'85.574',
'86.218',
'86.804',
];
const sma = new FasterSMA(5);
for (const price of prices) {
const actual = sma.update(price);
if (actual) {
const expected = expectations.shift()!;
expect(actual.toFixed(3)).toBe(expected);
}
}
expect(sma.isStable()).toBeTrue();
expect(sma.getResult()).toBe(86.804);
});

it('throws an error when there is not enough input data', () => {
const sma = new FasterSMA(5);

try {
sma.getResult();
fail('Expected error');
} catch (error) {
expect(error).toBeInstanceOf(NotEnoughDataError);
}
});
});
});
32 changes: 32 additions & 0 deletions src/SMA/SMA.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Big, {BigSource} from 'big.js';
import {MovingAverage} from '../MA/MovingAverage';
import {NotEnoughDataError} from '../error';

/**
* Simple Moving Average (SMA)
Expand Down Expand Up @@ -30,3 +31,34 @@ export class SMA extends MovingAverage {
return sum.div(prices.length);
}
}

export class FasterSMA {
protected result?: number;
public readonly prices: number[] = [];

constructor(public readonly interval: number) {}

isStable(): boolean {
return this.prices.length === this.interval;
}

getResult(): number {
if (!this.result) {
throw new NotEnoughDataError();
}
return this.result;
}

update(price: number): number | void {
this.prices.push(price);

if (this.prices.length > this.interval) {
this.prices.shift();
}

if (this.prices.length === this.interval) {
const sum = this.prices.reduce((a, b) => a + b, 0);
return (this.result = sum / this.prices.length);
}
}
}
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export * from './MACD/MACD';
export * from './MOM/MOM';
export * from './ROC/ROC';
export * from './RSI/RSI';
export * from './SMA/FasterSMA';
export * from './SMA/SMA';
export * from './SMMA/SMMA';
export * from './STOCH/StochasticOscillator';
Expand Down
4 changes: 2 additions & 2 deletions src/start/startBenchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {BollingerBands} from '../BBANDS/BollingerBands';
import {SMA} from '../SMA/SMA';
import {FasterSMA} from '../SMA/FasterSMA';
import candles from '../test/fixtures/candles/100-candles.json';
import {fasterGetAverage, getAverage, getFasterStandardDeviation, getStandardDeviation} from '../util';
import {getFasterAverage, getAverage, getFasterStandardDeviation, getStandardDeviation} from '../util';

const interval = 20;
const prices = candles.map(candle => parseInt(candle.close, 10));
Expand Down Expand Up @@ -32,7 +32,7 @@ new Benchmark.Suite('Technical Indicators')
return getAverage(prices);
})
.add('fasterGetAverage', () => {
return fasterGetAverage(prices);
return getFasterAverage(prices);
})
.add('getStandardDeviation', () => {
return getStandardDeviation(prices);
Expand Down
8 changes: 3 additions & 5 deletions src/util/getAverage.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {fasterGetAverage, getAverage} from './getAverage';
import {getFasterAverage, getAverage} from './getAverage';

describe('getAverage', () => {
it('does not fail when entering an empty array', () => {
Expand All @@ -8,17 +8,15 @@ describe('getAverage', () => {

it('returns the average of all given prices', () => {
const prices = [20, 30, 40];

const average = getAverage(prices);
expect(average.valueOf()).toBe('30');
});
});

describe('fasterGetAverage', () => {
describe('getFasterAverage', () => {
it('only works with the primitive data type number', () => {
const prices = [20, 30, 40];

const average = fasterGetAverage(prices);
const average = getFasterAverage(prices);
expect(average).toBe(30);
});
});
2 changes: 1 addition & 1 deletion src/util/getAverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export function getAverage(values: BigSource[]): Big {
return sum.div(values.length);
}

export function fasterGetAverage(values: number[]): number {
export function getFasterAverage(values: number[]): number {
return values.reduce((sum: number, x: number) => sum + x, 0) / values.length;
}
6 changes: 3 additions & 3 deletions src/util/getStandardDeviation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {fasterGetAverage, getAverage} from './getAverage';
import {getFasterAverage, getAverage} from './getAverage';
import Big, {BigSource} from 'big.js';

/**
Expand All @@ -15,8 +15,8 @@ export function getStandardDeviation(values: BigSource[], average?: BigSource):
}

export function getFasterStandardDeviation(values: number[], average?: number): number {
const middle = average || fasterGetAverage(values);
const middle = average || getFasterAverage(values);
const squaredDifferences = values.map(value => value - middle).map(value => value * value);
const averageDifference = fasterGetAverage(squaredDifferences);
const averageDifference = getFasterAverage(squaredDifferences);
return Math.sqrt(averageDifference);
}

0 comments on commit d489437

Please sign in to comment.