Skip to content

Commit

Permalink
Inline Documentation added (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldrick committed Aug 3, 2021
1 parent c296176 commit 24632c6
Show file tree
Hide file tree
Showing 28 changed files with 389 additions and 137 deletions.
2 changes: 1 addition & 1 deletion docs/modules/dema.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ parent: Modules

## Overview

The Double Exponential Moving Average (DEMA) uses two Exponantial Moving Average (EMA) to reduce noise. It can be used to identify support and resistance levels. Also prices above the DEMA can indicate uptrends, prices below can indicate downtrends.
The Double Exponential Moving Average (DEMA) uses two Exponential Moving Average (EMA) to reduce noise. It can be used to identify support and resistance levels. Also prices above the DEMA can indicate uptrends, prices below can indicate downtrends.

## Signature

Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ema.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ parent: Modules

## Overview

The Exponantial Moving Average (EMA) takes newer values weighted into account and reacts closer to the prices compared to the Simple Moving Average (SMA). It can be used to identify support and resistance levels. Also prices above the EMA can indicate uptrends, prices below can indicate downtrends.
The Exponential Moving Average (EMA) takes newer values weighted into account and reacts closer to the prices compared to the Simple Moving Average (SMA). It can be used to identify support and resistance levels. Also prices above the EMA can indicate uptrends, prices below can indicate downtrends.

## Signature

Expand Down
2 changes: 1 addition & 1 deletion docs/modules/tema.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ parent: Modules

## Overview

The Triple Exponential Moving Average (TEMA) uses three Exponantial Moving Average (EMA) to reduce noise and still get close to latest prices. It can be used to identify support and resistance levels. Also prices above the TEMA can indicate uptrends, prices below can indicate downtrends.
The Triple Exponential Moving Average (TEMA) uses three Exponential Moving Average (EMA) to reduce noise and still get close to latest prices. It can be used to identify support and resistance levels. Also prices above the TEMA can indicate uptrends, prices below can indicate downtrends.

## Signature

Expand Down
53 changes: 45 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,24 @@
"devDependencies": {
"@babel/cli": "^7.14.8",
"@babel/core": "^7.14.8",
"@babel/preset-env": "^7.14.8",
"@babel/preset-env": "^7.14.9",
"@babel/preset-typescript": "^7.14.5",
"@types/big.js": "^6.1.1",
"@types/jest": "^26.0.24",
"@typescript-eslint/eslint-plugin": "^4.28.5",
"@typescript-eslint/parser": "^4.28.5",
"@typescript-eslint/eslint-plugin": "^4.29.0",
"@typescript-eslint/parser": "^4.29.0",
"babel-jest": "^27.0.6",
"core-js": "^3.15.2",
"eslint": "^7.31.0",
"core-js": "^3.16.0",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-node": "^0.3.4",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.3.0",
"eslint-plugin-functional": "^3.5.0",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jest": "^24.4.0",
"eslint-plugin-jsdoc": "^36.0.6",
"husky": "^7.0.1",
"jest": "^27.0.6",
"jest-diff": "^27.0.6",
Expand Down Expand Up @@ -118,6 +119,8 @@
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:eslint-comments/recommended",
"plugin:jsdoc/recommended",
"plugin:eslint-comments/recommended",
"prettier"
],
"parserOptions": {
Expand All @@ -126,7 +129,33 @@
},
"rules": {
"import/prefer-default-export": "off",
"import/no-default-export": "error"
"import/no-default-export": "error",
"jsdoc/require-returns": "off",
"jsdoc/require-param": "off",
"jsdoc/require-jsdoc": [
"warn",
{
"publicOnly": {
"esm": true
},
"require": {
"ArrowFunctionExpression": true,
"ClassDeclaration": true,
"ClassExpression": true,
"FunctionDeclaration": true,
"FunctionExpression": true,
"MethodDefinition": false
}
}
],
"jsdoc/require-description": [
"warn",
{
"contexts": [
"any"
]
}
]
}
},
{
Expand Down Expand Up @@ -176,7 +205,15 @@
"setupFilesAfterEnv": [
"<rootDir>/tests/config/jest.setup.ts"
],
"collectCoverage": true
"collectCoverage": true,
"coverageThreshold": {
"global": {
"branches": 100,
"functions": 100,
"lines": 100,
"statements": 100
}
}
},
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
Expand Down
3 changes: 3 additions & 0 deletions src/averages/amean.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Big } from 'big.js';
import { readonlyNonEmptyArray as RNEA } from 'fp-ts';

/**
* Arithmetic Mean.
*/
export const amean = (values: RNEA.ReadonlyNonEmptyArray<Big>): Big =>
values.reduce((reduced, value) => reduced.add(value), new Big(0)).div(values.length);
7 changes: 7 additions & 0 deletions src/averages/dema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import { emaC } from './ema';
const calculate = (one: readonly Big[], two: readonly Big[], period: number): readonly Big[] =>
two.map((value, index) => one[index + period - 1].mul(2).sub(value));

/**
* The Double Exponential Moving Average (DEMA) uses two Exponential Moving Average (EMA)
* to reduce noise. It can be used to identify support and resistance levels.
* Also prices above the DEMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const dema = (values: readonly number[], period = 20): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
Expand Down
12 changes: 12 additions & 0 deletions src/averages/dma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const getDefaultFactor = (period: number): E.Either<Error, Big> =>
const factorToBig = (period: number, factor?: number): E.Either<Error, Big> =>
factor ? numberToBig(factor) : getDefaultFactor(period);

/**
* DMA without checks and conversion.
* Only for internal use.
*/
export const dmaC = (values: readonly Big[], period: number, factor: Big): readonly Big[] =>
values.reduce(
(reduced, value, index, array) =>
Expand All @@ -38,6 +42,14 @@ export const dmaC = (values: readonly Big[], period: number, factor: Big): reado
<readonly Big[]>[],
);

/**
* The Dynamic Moving Average (DMA) is the base implementation for the
* Exponential Moving Average (EMA) and the Smoothed Moving Average (SMMA) by providing a factor.
* It can be used to identify support and resistance levels.
* Also prices above the DMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const dma = (
values: readonly number[],
period = 20,
Expand Down
12 changes: 12 additions & 0 deletions src/averages/ema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,25 @@ const getFactor = (period: number): E.Either<Error, Big> =>
E.map((periodB) => new Big(2).div(periodB.add(1))),
);

/**
* EMA without checks and conversion.
* Only for internal use.
*/
export const emaC = (values: readonly Big[], period: number): E.Either<Error, readonly Big[]> =>
pipe(
period,
getFactor,
E.map((factorB) => dmaC(values, period, factorB)),
);

/**
* The Exponential Moving Average (EMA) takes newer values weighted into account
* and reacts closer to the prices compared to the Simple Moving Average (SMA).
* It can be used to identify support and resistance levels.
* Also prices above the EMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const ema = (values: readonly number[], period = 20): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
Expand Down
8 changes: 8 additions & 0 deletions src/averages/macd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ const calculate = (fast: readonly Big[], slow: readonly Big[]): readonly Big[] =
return slow.map((value, index) => shortened[index].sub(value));
};

/**
* The Moving Average Convergence Divergence (MACD) is the relationship of
* two Exponential Moving Averages (EMA) with different periods.
* It generates crosses with the generated signal EMA which can be used
* to indicate uptrends or downtrends.
*
* @public
*/
export const macd = (
values: readonly number[],
fastPeriod = 12,
Expand Down
7 changes: 7 additions & 0 deletions src/averages/sma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ const calculate = (values: readonly Big[], period: number): readonly Big[] =>
<readonly Big[]>[],
);

/**
* The Simple Moving Average (SMA) calculates the arithmetic mean of prices over an period.
* It can be used to identify support and resistance levels.
* Also prices above the SMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const sma = (values: readonly number[], period = 20): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
Expand Down
11 changes: 11 additions & 0 deletions src/averages/smma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@ const getFactor = (period: number): E.Either<Error, Big> =>
E.map((periodB) => new Big(1).div(periodB)),
);

/**
* SMMA without checks and conversion.
* Only for internal use.
*/
export const smmaC = (values: readonly Big[], period: number): E.Either<Error, readonly Big[]> =>
pipe(
period,
getFactor,
E.map((factorB) => dmaC(values, period, factorB)),
);

/**
* The Smoothed Moving Average (SMMA) is like the Exponential Moving Average (EMA),
* with just a “smoother” factor. It can be used to identify support and resistance levels.
* Also prices above the SMMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const smma = (values: readonly number[], period = 20): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
Expand Down
8 changes: 8 additions & 0 deletions src/averages/tema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ const calculate = (
.add(value),
);

/**
* The Triple Exponential Moving Average (TEMA) uses three Exponential Moving Average (EMA)
* to reduce noise and still get close to latest prices.
* It can be used to identify support and resistance levels.
* Also prices above the TEMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const tema = (values: readonly number[], period = 20): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
Expand Down
3 changes: 3 additions & 0 deletions src/averages/wamean.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Big } from 'big.js';
import { readonlyNonEmptyArray as RNEA } from 'fp-ts';

/**
* Weighted Arithmetic Mean.
*/
export const wamean = (values: RNEA.ReadonlyNonEmptyArray<Big>): Big => {
const dividend = values.reduce(
(reduced, value, index) => reduced.add(value.mul(index + 1)),
Expand Down
8 changes: 8 additions & 0 deletions src/averages/wma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ const calculate = (values: readonly Big[], period: number): readonly Big[] =>
<readonly Big[]>[],
);

/**
* The Weighted Moving Average (WMA) takes newer values weighted into account
* and reacts closer to the prices compared to the Simple Moving Average (SMA).
* It can be used to identify support and resistance levels.
* Also prices above the WMA can indicate uptrends, prices below can indicate downtrends.
*
* @public
*/
export const wma = (values: readonly number[], period = 20): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
Expand Down
3 changes: 3 additions & 0 deletions src/errors/InfinitNumberError.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Error for `Number` is not finit.
*/
export class InfinitNumberError extends Error {
constructor() {
super(`Given value(s) must be finit.`);
Expand Down
3 changes: 3 additions & 0 deletions src/errors/NotEnoughDataError.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Error for `Array.length` to small.
*/
export class NotEnoughDataError extends Error {
constructor(period: number, required: number) {
super(`Need at least ${required} values for period size ${period}`);
Expand Down
3 changes: 3 additions & 0 deletions src/errors/NotPositiveIntegerError.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Error for any `Number` lower 1 or not an Integer
*/
export class NotPositiveIntegerError extends Error {
constructor(parameter: string) {
super(`Parameter ${parameter} must be positive Integer.`);
Expand Down
3 changes: 3 additions & 0 deletions src/errors/PeriodSizeMissmatchError.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Error for comparable periods, where one must exceed the other.
*/
export class PeriodSizeMissmatchError extends Error {
constructor(periodBig: string, periodShort: string) {
super(`Period ${periodBig} must be greater than ${periodShort}`);
Expand Down
3 changes: 3 additions & 0 deletions src/errors/UnequalArraySizesError.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Error if two `Array` do not have the same length.
*/
export class UnequalArraySizesError extends Error {
constructor(message = 'Amounts of given values are not equal.') {
super(message);
Expand Down
10 changes: 9 additions & 1 deletion src/movements/adx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ const calculation = (pdi: readonly Big[], mdi: readonly Big[]): readonly Big[] =
return dividend.div(sum);
}, <readonly Big[]>[]);

/**
* The Average Directional Index (ADX) determines trend strength.
* It also delivers Plus Directional Movement Indicator (PDI)
* and Minus Directional Movement Indicator (MDI).
* Crossings of these three values can be used to determine trend changes.
*
* @public
*/
export const adx = (
values: HighLowClose,
period = 14,
Expand All @@ -69,7 +77,7 @@ export const adx = (
periodV: validatePeriod(period, 'period'),
valuesV: validateData(values, 2 * period + 1, period),
}),
E.bind('valuesB', ({ valuesV }) => objectToBig<HighLowCloseB>(valuesV)),
E.bind('valuesB', ({ valuesV }) => objectToBig(valuesV)),
E.bind('pdi', ({ valuesB, periodV }) => directionalIndex(valuesB, periodV, 'up')),
E.bind('mdi', ({ valuesB, periodV }) => directionalIndex(valuesB, periodV, 'down')),
E.bind('smoothed', ({ pdi, mdi, periodV }) => {
Expand Down
14 changes: 13 additions & 1 deletion src/movements/atr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,29 @@ const trueRange = (values: HighLowCloseB): readonly Big[] =>
];
}, <readonly Big[]>[]);

/**
* ATR without checks and conversion.
* Only for internal use.
*/
export const atrC = (values: HighLowCloseB, period: number): E.Either<Error, readonly Big[]> => {
const tr = trueRange(values);
return smmaC(tr, period);
};

/**
* The Average True Range (ATR) a period of the True Range Indicator,
* being the greatest out of current high minus the current low,
* the absolute value of current high minus previous close
* and the absolute value of the current low minus the prevous close.
*
* @public
*/
export const atr = (values: HighLowClose, period = 14): E.Either<Error, readonly Big[]> =>
pipe(
AP.sequenceS(E.Apply)({
periodV: validatePeriod(period, 'period'),
valuesV: validateData(values, period + 1, period),
}),
E.bind('valuesB', ({ valuesV }) => objectToBig<HighLowCloseB>(valuesV)),
E.bind('valuesB', ({ valuesV }) => objectToBig(valuesV)),
E.chain(({ valuesB, periodV }) => atrC(valuesB, periodV)),
);
Loading

0 comments on commit 24632c6

Please sign in to comment.