@tradingaction/indicators 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/README.md +5 -0
- package/lib/calculator/atr.d.ts +18 -0
- package/lib/calculator/atr.js +51 -0
- package/lib/calculator/atr.js.map +1 -0
- package/lib/calculator/bollingerband.d.ts +14 -0
- package/lib/calculator/bollingerband.js +72 -0
- package/lib/calculator/bollingerband.js.map +1 -0
- package/lib/calculator/change.d.ts +14 -0
- package/lib/calculator/change.js +30 -0
- package/lib/calculator/change.js.map +1 -0
- package/lib/calculator/compare.d.ts +10 -0
- package/lib/calculator/compare.js +50 -0
- package/lib/calculator/compare.js.map +1 -0
- package/lib/calculator/defaultOptionsForComputation.d.ts +91 -0
- package/lib/calculator/defaultOptionsForComputation.js +100 -0
- package/lib/calculator/defaultOptionsForComputation.js.map +1 -0
- package/lib/calculator/elderRay.d.ts +23 -0
- package/lib/calculator/elderRay.js +69 -0
- package/lib/calculator/elderRay.js.map +1 -0
- package/lib/calculator/ema.d.ts +12 -0
- package/lib/calculator/ema.js +73 -0
- package/lib/calculator/ema.js.map +1 -0
- package/lib/calculator/forceIndex.d.ts +12 -0
- package/lib/calculator/forceIndex.js +27 -0
- package/lib/calculator/forceIndex.js.map +1 -0
- package/lib/calculator/heikinAshi.d.ts +4 -0
- package/lib/calculator/heikinAshi.js +30 -0
- package/lib/calculator/heikinAshi.js.map +1 -0
- package/lib/calculator/index.d.ts +19 -0
- package/lib/calculator/index.js +20 -0
- package/lib/calculator/index.js.map +1 -0
- package/lib/calculator/kagi.d.ts +11 -0
- package/lib/calculator/kagi.js +200 -0
- package/lib/calculator/kagi.js.map +1 -0
- package/lib/calculator/macd.d.ts +18 -0
- package/lib/calculator/macd.js +57 -0
- package/lib/calculator/macd.js.map +1 -0
- package/lib/calculator/pointAndFigure.d.ts +10 -0
- package/lib/calculator/pointAndFigure.js +215 -0
- package/lib/calculator/pointAndFigure.js.map +1 -0
- package/lib/calculator/renko.d.ts +12 -0
- package/lib/calculator/renko.js +170 -0
- package/lib/calculator/renko.js.map +1 -0
- package/lib/calculator/rsi.d.ts +12 -0
- package/lib/calculator/rsi.js +87 -0
- package/lib/calculator/rsi.js.map +1 -0
- package/lib/calculator/sar.d.ts +12 -0
- package/lib/calculator/sar.js +87 -0
- package/lib/calculator/sar.js.map +1 -0
- package/lib/calculator/sma.d.ts +12 -0
- package/lib/calculator/sma.js +27 -0
- package/lib/calculator/sma.js.map +1 -0
- package/lib/calculator/smoothedForceIndex.d.ts +13 -0
- package/lib/calculator/smoothedForceIndex.js +40 -0
- package/lib/calculator/smoothedForceIndex.js.map +1 -0
- package/lib/calculator/sto.d.ts +19 -0
- package/lib/calculator/sto.js +91 -0
- package/lib/calculator/sto.js.map +1 -0
- package/lib/calculator/tma.d.ts +12 -0
- package/lib/calculator/tma.js +66 -0
- package/lib/calculator/tma.js.map +1 -0
- package/lib/calculator/wma.d.ts +12 -0
- package/lib/calculator/wma.js +33 -0
- package/lib/calculator/wma.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/indicator/algorithm.d.ts +10 -0
- package/lib/indicator/algorithm.js +35 -0
- package/lib/indicator/algorithm.js.map +1 -0
- package/lib/indicator/atr.d.ts +26 -0
- package/lib/indicator/atr.js +27 -0
- package/lib/indicator/atr.js.map +1 -0
- package/lib/indicator/baseIndicator.d.ts +16 -0
- package/lib/indicator/baseIndicator.js +59 -0
- package/lib/indicator/baseIndicator.js.map +1 -0
- package/lib/indicator/bollingerBand.d.ts +24 -0
- package/lib/indicator/bollingerBand.js +27 -0
- package/lib/indicator/bollingerBand.js.map +1 -0
- package/lib/indicator/change.d.ts +24 -0
- package/lib/indicator/change.js +25 -0
- package/lib/indicator/change.js.map +1 -0
- package/lib/indicator/compare.d.ts +24 -0
- package/lib/indicator/compare.js +29 -0
- package/lib/indicator/compare.js.map +1 -0
- package/lib/indicator/defaultOptionsForAppearance.d.ts +105 -0
- package/lib/indicator/defaultOptionsForAppearance.js +77 -0
- package/lib/indicator/defaultOptionsForAppearance.js.map +1 -0
- package/lib/indicator/elderImpulse.d.ts +7 -0
- package/lib/indicator/elderImpulse.js +61 -0
- package/lib/indicator/elderImpulse.js.map +1 -0
- package/lib/indicator/elderRay.d.ts +24 -0
- package/lib/indicator/elderRay.js +29 -0
- package/lib/indicator/elderRay.js.map +1 -0
- package/lib/indicator/ema.d.ts +24 -0
- package/lib/indicator/ema.js +29 -0
- package/lib/indicator/ema.js.map +1 -0
- package/lib/indicator/forceIndex.d.ts +24 -0
- package/lib/indicator/forceIndex.js +29 -0
- package/lib/indicator/forceIndex.js.map +1 -0
- package/lib/indicator/heikinAshi.d.ts +3 -0
- package/lib/indicator/heikinAshi.js +28 -0
- package/lib/indicator/heikinAshi.js.map +1 -0
- package/lib/indicator/index.d.ts +23 -0
- package/lib/indicator/index.js +24 -0
- package/lib/indicator/index.js.map +1 -0
- package/lib/indicator/kagi.d.ts +11 -0
- package/lib/indicator/kagi.js +13 -0
- package/lib/indicator/kagi.js.map +1 -0
- package/lib/indicator/macd.d.ts +24 -0
- package/lib/indicator/macd.js +32 -0
- package/lib/indicator/macd.js.map +1 -0
- package/lib/indicator/pointAndFigure.d.ts +10 -0
- package/lib/indicator/pointAndFigure.js +13 -0
- package/lib/indicator/pointAndFigure.js.map +1 -0
- package/lib/indicator/renko.d.ts +12 -0
- package/lib/indicator/renko.js +13 -0
- package/lib/indicator/renko.js.map +1 -0
- package/lib/indicator/rsi.d.ts +24 -0
- package/lib/indicator/rsi.js +29 -0
- package/lib/indicator/rsi.js.map +1 -0
- package/lib/indicator/sar.d.ts +24 -0
- package/lib/indicator/sar.js +29 -0
- package/lib/indicator/sar.js.map +1 -0
- package/lib/indicator/sma.d.ts +24 -0
- package/lib/indicator/sma.js +29 -0
- package/lib/indicator/sma.js.map +1 -0
- package/lib/indicator/stochasticOscillator.d.ts +24 -0
- package/lib/indicator/stochasticOscillator.js +27 -0
- package/lib/indicator/stochasticOscillator.js.map +1 -0
- package/lib/indicator/tma.d.ts +24 -0
- package/lib/indicator/tma.js +29 -0
- package/lib/indicator/tma.js.map +1 -0
- package/lib/indicator/wma.d.ts +24 -0
- package/lib/indicator/wma.js +29 -0
- package/lib/indicator/wma.js.map +1 -0
- package/lib/utils/functor.d.ts +1 -0
- package/lib/utils/functor.js +4 -0
- package/lib/utils/functor.js.map +1 -0
- package/lib/utils/identity.d.ts +1 -0
- package/lib/utils/identity.js +2 -0
- package/lib/utils/identity.js.map +1 -0
- package/lib/utils/index.d.ts +8 -0
- package/lib/utils/index.js +9 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/mappedSlidingWindow.d.ts +15 -0
- package/lib/utils/mappedSlidingWindow.js +77 -0
- package/lib/utils/mappedSlidingWindow.js.map +1 -0
- package/lib/utils/merge.d.ts +11 -0
- package/lib/utils/merge.js +70 -0
- package/lib/utils/merge.js.map +1 -0
- package/lib/utils/path.d.ts +1 -0
- package/lib/utils/path.js +15 -0
- package/lib/utils/path.js.map +1 -0
- package/lib/utils/rebind.d.ts +1 -0
- package/lib/utils/rebind.js +18 -0
- package/lib/utils/rebind.js.map +1 -0
- package/lib/utils/slidingWindow.d.ts +19 -0
- package/lib/utils/slidingWindow.js +111 -0
- package/lib/utils/slidingWindow.js.map +1 -0
- package/lib/utils/zipper.d.ts +7 -0
- package/lib/utils/zipper.js +36 -0
- package/lib/utils/zipper.js.map +1 -0
- package/package.json +49 -0
- package/src/calculator/atr.ts +88 -0
- package/src/calculator/bollingerband.ts +102 -0
- package/src/calculator/change.ts +53 -0
- package/src/calculator/compare.ts +68 -0
- package/src/calculator/defaultOptionsForComputation.ts +117 -0
- package/src/calculator/elderRay.ts +90 -0
- package/src/calculator/ema.ts +92 -0
- package/src/calculator/forceIndex.ts +43 -0
- package/src/calculator/heikinAshi.ts +38 -0
- package/src/calculator/index.ts +19 -0
- package/src/calculator/kagi.ts +249 -0
- package/src/calculator/macd.ts +90 -0
- package/src/calculator/pointAndFigure.ts +255 -0
- package/src/calculator/renko.ts +227 -0
- package/src/calculator/rsi.ts +114 -0
- package/src/calculator/sar.ts +117 -0
- package/src/calculator/sma.ts +41 -0
- package/src/calculator/smoothedForceIndex.ts +53 -0
- package/src/calculator/sto.ts +118 -0
- package/src/calculator/tma.ts +82 -0
- package/src/calculator/wma.ts +49 -0
- package/src/index.ts +1 -0
- package/src/indicator/algorithm.ts +53 -0
- package/src/indicator/atr.ts +58 -0
- package/src/indicator/baseIndicator.ts +97 -0
- package/src/indicator/bollingerBand.ts +55 -0
- package/src/indicator/change.ts +51 -0
- package/src/indicator/compare.ts +57 -0
- package/src/indicator/defaultOptionsForAppearance.ts +77 -0
- package/src/indicator/elderImpulse.ts +73 -0
- package/src/indicator/elderRay.ts +56 -0
- package/src/indicator/ema.ts +58 -0
- package/src/indicator/forceIndex.ts +57 -0
- package/src/indicator/heikinAshi.ts +35 -0
- package/src/indicator/index.ts +25 -0
- package/src/indicator/kagi.ts +18 -0
- package/src/indicator/macd.ts +60 -0
- package/src/indicator/pointAndFigure.ts +18 -0
- package/src/indicator/renko.ts +18 -0
- package/src/indicator/rsi.ts +58 -0
- package/src/indicator/sar.ts +56 -0
- package/src/indicator/sma.ts +57 -0
- package/src/indicator/stochasticOscillator.ts +56 -0
- package/src/indicator/tma.ts +57 -0
- package/src/indicator/wma.ts +58 -0
- package/src/utils/functor.ts +3 -0
- package/src/utils/identity.ts +1 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/mappedSlidingWindow.ts +95 -0
- package/src/utils/merge.ts +93 -0
- package/src/utils/path.ts +16 -0
- package/src/utils/rebind.ts +19 -0
- package/src/utils/slidingWindow.ts +142 -0
- package/src/utils/zipper.ts +45 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/*
|
|
2
|
+
TRIMA (Triangular Moving Average).
|
|
3
|
+
|
|
4
|
+
The Triangular Moving Average can be used like any other Moving Average, to
|
|
5
|
+
obtain a smoother representation of the underlying data.
|
|
6
|
+
It is important to note that the Triangular Moving Average is typically much
|
|
7
|
+
smoother than other moving averages.
|
|
8
|
+
|
|
9
|
+
Triangular moving averages give greater weight to prices at the centre of the
|
|
10
|
+
chosen period andi it is calculated as double smoothed SMA (simple moving average).
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
For TimeSerie={a,b,c,d,e,f...} ('a' is the older price)
|
|
14
|
+
|
|
15
|
+
1st value for TMA 4-Period is: ((1*a)+(2*b)+(2*c)+(1*d)) / 6
|
|
16
|
+
2nd value for TMA 4-Period is: ((1*b)+(2*c)+(2*d)+(1*e)) / 6
|
|
17
|
+
|
|
18
|
+
1st value for TMA 5-Period is: ((1*a)+(2*b)+(3*c)+(2*d)+(1*e)) / 9
|
|
19
|
+
2nd value for TMA 5-Period is: ((1*b)+(2*c)+(3*d)+(2*e)+(1*f)) / 9
|
|
20
|
+
|
|
21
|
+
Using algebra, it can be demonstrated that the TMA is equivalent to
|
|
22
|
+
doing a SMA of a SMA. The following explain the rules:
|
|
23
|
+
|
|
24
|
+
(1) When the period is even, TMA(x,period)=SMA(SMA(x,period/2),(period/2)+1)
|
|
25
|
+
(2) When the period is odd, TMA(x,period)=SMA(SMA(x,(period+1)/2),(period+1)/2)
|
|
26
|
+
|
|
27
|
+
In other word:
|
|
28
|
+
(1) A period of 4 becomes TMA(x,4) = SMA( SMA( x, 2), 3 )
|
|
29
|
+
(2) A period of 5 becomes TMA(x,5) = SMA( SMA( x, 3), 3 )
|
|
30
|
+
|
|
31
|
+
The SMA of a SMA is the algorithm generally found in books.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { sum } from "d3-array";
|
|
35
|
+
import { slidingWindow } from "../utils";
|
|
36
|
+
import { TMA as defaultOptions } from "./defaultOptionsForComputation";
|
|
37
|
+
|
|
38
|
+
export interface TMAOptions {
|
|
39
|
+
readonly sourcePath?: string;
|
|
40
|
+
readonly windowSize: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default function () {
|
|
44
|
+
let options = defaultOptions;
|
|
45
|
+
|
|
46
|
+
const calculator = (data: any[]) => {
|
|
47
|
+
const { windowSize, sourcePath } = options;
|
|
48
|
+
|
|
49
|
+
const n = Math.floor(windowSize / 2);
|
|
50
|
+
const weight = windowSize % 2 === 0 ? n * (n + 1) : (n + 1) * (n + 1);
|
|
51
|
+
|
|
52
|
+
const triaverage = slidingWindow()
|
|
53
|
+
.windowSize(windowSize)
|
|
54
|
+
.sourcePath(sourcePath)
|
|
55
|
+
.accumulator((values: number[]) => {
|
|
56
|
+
const total = sum(values, (v, i) => {
|
|
57
|
+
return i < n ? (i + 1) * v : (windowSize - i) * v;
|
|
58
|
+
});
|
|
59
|
+
return total / weight;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return triaverage(data);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
calculator.undefinedLength = () => {
|
|
66
|
+
const { windowSize } = options;
|
|
67
|
+
|
|
68
|
+
return windowSize - 1;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
calculator.options = (newOptions?: TMAOptions) => {
|
|
72
|
+
if (newOptions === undefined) {
|
|
73
|
+
return options;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
options = { ...defaultOptions, ...newOptions };
|
|
77
|
+
|
|
78
|
+
return calculator;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return calculator;
|
|
82
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { sum } from "d3-array";
|
|
2
|
+
import { slidingWindow } from "../utils";
|
|
3
|
+
import { WMA as defaultOptions } from "./defaultOptionsForComputation";
|
|
4
|
+
|
|
5
|
+
export interface WMAOptions {
|
|
6
|
+
sourcePath?: string;
|
|
7
|
+
windowSize: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function () {
|
|
11
|
+
let options = defaultOptions;
|
|
12
|
+
|
|
13
|
+
const calculator = (data: any[]) => {
|
|
14
|
+
const { windowSize, sourcePath } = options;
|
|
15
|
+
|
|
16
|
+
const weight = (windowSize * (windowSize + 1)) / 2;
|
|
17
|
+
|
|
18
|
+
const waverage = slidingWindow()
|
|
19
|
+
.windowSize(windowSize)
|
|
20
|
+
.sourcePath(sourcePath)
|
|
21
|
+
.accumulator((values: number[]) => {
|
|
22
|
+
const total = sum(values, (v, i) => {
|
|
23
|
+
return (i + 1) * v;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return total / weight;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return waverage(data);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
calculator.undefinedLength = () => {
|
|
33
|
+
const { windowSize } = options;
|
|
34
|
+
|
|
35
|
+
return windowSize - 1;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
calculator.options = (newOptions?: WMAOptions) => {
|
|
39
|
+
if (newOptions === undefined) {
|
|
40
|
+
return options;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
options = { ...defaultOptions, ...newOptions };
|
|
44
|
+
|
|
45
|
+
return calculator;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return calculator;
|
|
49
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./indicator";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { identity, merge, slidingWindow } from "../utils";
|
|
2
|
+
|
|
3
|
+
export interface Algorithm {
|
|
4
|
+
(data: any[]): any;
|
|
5
|
+
accumulator(): any;
|
|
6
|
+
accumulator(newAccumulator: any): Algorithm;
|
|
7
|
+
windowSize(): number;
|
|
8
|
+
windowSize(windowSize: number): Algorithm;
|
|
9
|
+
merge(): any;
|
|
10
|
+
merge(newMerge: any): Algorithm;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default function () {
|
|
14
|
+
let windowSize = 1;
|
|
15
|
+
let accumulator = identity;
|
|
16
|
+
let mergeAs = identity;
|
|
17
|
+
|
|
18
|
+
function algorithm(data: any[]) {
|
|
19
|
+
const defaultAlgorithm = slidingWindow().windowSize(windowSize).accumulator(accumulator);
|
|
20
|
+
|
|
21
|
+
const calculator = merge().algorithm(defaultAlgorithm).merge(mergeAs);
|
|
22
|
+
|
|
23
|
+
const newData = calculator(data);
|
|
24
|
+
|
|
25
|
+
return newData;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
algorithm.accumulator = (newAccumulator?: any) => {
|
|
29
|
+
if (newAccumulator === undefined) {
|
|
30
|
+
return accumulator;
|
|
31
|
+
}
|
|
32
|
+
accumulator = newAccumulator;
|
|
33
|
+
return algorithm;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
algorithm.windowSize = (newWindowSize?: number) => {
|
|
37
|
+
if (newWindowSize === undefined) {
|
|
38
|
+
return windowSize;
|
|
39
|
+
}
|
|
40
|
+
windowSize = newWindowSize;
|
|
41
|
+
return algorithm;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
algorithm.merge = (newMerge?: any) => {
|
|
45
|
+
if (newMerge === undefined) {
|
|
46
|
+
return mergeAs;
|
|
47
|
+
}
|
|
48
|
+
mergeAs = newMerge;
|
|
49
|
+
return algorithm;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return algorithm as Algorithm;
|
|
53
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { atr } from "../calculator";
|
|
2
|
+
import { merge, rebind } from "../utils";
|
|
3
|
+
import { ATROptions } from "../calculator/atr";
|
|
4
|
+
import baseIndicator from "./baseIndicator";
|
|
5
|
+
|
|
6
|
+
const ALGORITHM_TYPE = "ATR";
|
|
7
|
+
|
|
8
|
+
interface ATRIndicator {
|
|
9
|
+
(data: any[], options?: { merge: boolean }): any;
|
|
10
|
+
id(): number;
|
|
11
|
+
id(x: number): ATRIndicator;
|
|
12
|
+
accessor(): any;
|
|
13
|
+
accessor(x: any): ATRIndicator;
|
|
14
|
+
stroke(): string | any;
|
|
15
|
+
stroke(x: string | any): ATRIndicator;
|
|
16
|
+
fill(): string | any;
|
|
17
|
+
fill(x: string | any): ATRIndicator;
|
|
18
|
+
echo(): any;
|
|
19
|
+
echo(x: any): ATRIndicator;
|
|
20
|
+
type(): string;
|
|
21
|
+
type(x: string): ATRIndicator;
|
|
22
|
+
merge(): any;
|
|
23
|
+
merge(newMerge: any): ATRIndicator;
|
|
24
|
+
options(): ATROptions;
|
|
25
|
+
options(newOptions: ATROptions): ATRIndicator;
|
|
26
|
+
skipUndefined(): boolean;
|
|
27
|
+
skipUndefined(newSkipUndefined: boolean): ATRIndicator;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default function () {
|
|
31
|
+
const base = baseIndicator().type(ALGORITHM_TYPE);
|
|
32
|
+
|
|
33
|
+
const underlyingAlgorithm = atr();
|
|
34
|
+
|
|
35
|
+
const mergedAlgorithm = merge()
|
|
36
|
+
.algorithm(underlyingAlgorithm)
|
|
37
|
+
.merge((datum: any, i: number) => {
|
|
38
|
+
datum.atr = i;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const indicator = (data: any[], options = { merge: true }) => {
|
|
42
|
+
if (options.merge) {
|
|
43
|
+
if (!base.accessor()) {
|
|
44
|
+
throw new Error(`Set an accessor to ${ALGORITHM_TYPE} before calculating`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return mergedAlgorithm(data);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return underlyingAlgorithm(data);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
rebind(indicator, base, "id", "accessor", "stroke", "fill", "echo", "type");
|
|
54
|
+
rebind(indicator, underlyingAlgorithm, "options");
|
|
55
|
+
rebind(indicator, mergedAlgorithm, "merge", "skipUndefined");
|
|
56
|
+
|
|
57
|
+
return indicator as ATRIndicator;
|
|
58
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { scaleOrdinal } from "d3-scale";
|
|
2
|
+
|
|
3
|
+
const defaultColors = ["#F44336", "#2196F3", "#8BC34A", "#FF5722", "#3F51B5", "#03A9F4", "#9C27B0", "#4CAF50"];
|
|
4
|
+
|
|
5
|
+
let i = 0;
|
|
6
|
+
const overlayColors = scaleOrdinal<number, string>(defaultColors);
|
|
7
|
+
|
|
8
|
+
export interface BaseIndicator {
|
|
9
|
+
(): () => void;
|
|
10
|
+
id(): number;
|
|
11
|
+
id(x: number): BaseIndicator;
|
|
12
|
+
accessor(): any;
|
|
13
|
+
accessor(x: any): BaseIndicator;
|
|
14
|
+
stroke(): string | any;
|
|
15
|
+
stroke(x: string | any): BaseIndicator;
|
|
16
|
+
fill(): string | any;
|
|
17
|
+
fill(x: string | any): BaseIndicator;
|
|
18
|
+
echo(): any;
|
|
19
|
+
echo(x: any): BaseIndicator;
|
|
20
|
+
type(): string;
|
|
21
|
+
type(x: string): BaseIndicator;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function () {
|
|
25
|
+
let id = i++;
|
|
26
|
+
let accessor: any;
|
|
27
|
+
let stroke: string | any;
|
|
28
|
+
let fill: string | any;
|
|
29
|
+
let echo: any;
|
|
30
|
+
let type: string;
|
|
31
|
+
|
|
32
|
+
const baseIndicator = () => () => {
|
|
33
|
+
/** Do Nothing */
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
baseIndicator.id = (newId?: number) => {
|
|
37
|
+
if (newId === undefined) {
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
id = newId;
|
|
42
|
+
|
|
43
|
+
return baseIndicator;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
baseIndicator.accessor = (newAccessor?: any) => {
|
|
47
|
+
if (newAccessor === undefined) {
|
|
48
|
+
return accessor;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
accessor = newAccessor;
|
|
52
|
+
|
|
53
|
+
return baseIndicator;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
baseIndicator.stroke = (newStroke?: string | any) => {
|
|
57
|
+
if (newStroke === undefined) {
|
|
58
|
+
return !stroke ? (stroke = overlayColors(id)) : stroke;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
stroke = newStroke;
|
|
62
|
+
|
|
63
|
+
return baseIndicator;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
baseIndicator.fill = (newFill?: string | any) => {
|
|
67
|
+
if (newFill === undefined) {
|
|
68
|
+
return !fill ? (fill = overlayColors(id)) : fill;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
fill = newFill;
|
|
72
|
+
|
|
73
|
+
return baseIndicator;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
baseIndicator.echo = (newEcho?: any) => {
|
|
77
|
+
if (newEcho === undefined) {
|
|
78
|
+
return echo;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
echo = newEcho;
|
|
82
|
+
|
|
83
|
+
return baseIndicator;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
baseIndicator.type = (newType?: string) => {
|
|
87
|
+
if (newType === undefined) {
|
|
88
|
+
return type;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type = newType;
|
|
92
|
+
|
|
93
|
+
return baseIndicator;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return baseIndicator as BaseIndicator;
|
|
97
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { merge, rebind } from "../utils";
|
|
2
|
+
import { bollingerband } from "../calculator";
|
|
3
|
+
import { BollingerBandOptions } from "../calculator/bollingerband";
|
|
4
|
+
import baseIndicator from "./baseIndicator";
|
|
5
|
+
|
|
6
|
+
const ALGORITHM_TYPE = "BollingerBand";
|
|
7
|
+
|
|
8
|
+
interface BollingerBandIndicator {
|
|
9
|
+
(data: any[], options?: { merge: boolean }): any;
|
|
10
|
+
id(): number;
|
|
11
|
+
id(x: number): BollingerBandIndicator;
|
|
12
|
+
accessor(): any;
|
|
13
|
+
accessor(x: any): BollingerBandIndicator;
|
|
14
|
+
stroke(): string | any;
|
|
15
|
+
stroke(x: string | any): BollingerBandIndicator;
|
|
16
|
+
fill(): string | any;
|
|
17
|
+
fill(x: string | any): BollingerBandIndicator;
|
|
18
|
+
echo(): any;
|
|
19
|
+
echo(x: any): BollingerBandIndicator;
|
|
20
|
+
type(): string;
|
|
21
|
+
type(x: string): BollingerBandIndicator;
|
|
22
|
+
merge(): any;
|
|
23
|
+
merge(newMerge: any): BollingerBandIndicator;
|
|
24
|
+
options(): BollingerBandOptions;
|
|
25
|
+
options(newOptions: BollingerBandOptions): BollingerBandIndicator;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default function () {
|
|
29
|
+
const base = baseIndicator().type(ALGORITHM_TYPE);
|
|
30
|
+
|
|
31
|
+
const underlyingAlgorithm = bollingerband();
|
|
32
|
+
|
|
33
|
+
const mergedAlgorithm = merge()
|
|
34
|
+
.algorithm(underlyingAlgorithm)
|
|
35
|
+
.merge((datum: any, i: number) => {
|
|
36
|
+
datum.bollingerBand = i;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const indicator = (data: any[], options = { merge: true }) => {
|
|
40
|
+
if (options.merge) {
|
|
41
|
+
if (!base.accessor()) {
|
|
42
|
+
throw new Error(`Set an accessor to ${ALGORITHM_TYPE} before calculating`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return mergedAlgorithm(data);
|
|
46
|
+
}
|
|
47
|
+
return underlyingAlgorithm(data);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
rebind(indicator, base, "id", "accessor", "stroke", "fill", "echo", "type");
|
|
51
|
+
rebind(indicator, underlyingAlgorithm, "options");
|
|
52
|
+
rebind(indicator, mergedAlgorithm, "merge", "skipUndefined");
|
|
53
|
+
|
|
54
|
+
return indicator as BollingerBandIndicator;
|
|
55
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { change } from "../calculator";
|
|
2
|
+
import { merge, rebind } from "../utils";
|
|
3
|
+
import { ChangeOptions } from "../calculator/change";
|
|
4
|
+
import baseIndicator from "./baseIndicator";
|
|
5
|
+
|
|
6
|
+
const ALGORITHM_TYPE = "Change";
|
|
7
|
+
|
|
8
|
+
interface ChangeIndicator {
|
|
9
|
+
(data: any[], options?: { merge: boolean }): any;
|
|
10
|
+
id(): number;
|
|
11
|
+
id(x: number): ChangeIndicator;
|
|
12
|
+
accessor(): any;
|
|
13
|
+
accessor(x: any): ChangeIndicator;
|
|
14
|
+
stroke(): string | any;
|
|
15
|
+
stroke(x: string | any): ChangeIndicator;
|
|
16
|
+
fill(): string | any;
|
|
17
|
+
fill(x: string | any): ChangeIndicator;
|
|
18
|
+
echo(): any;
|
|
19
|
+
echo(x: any): ChangeIndicator;
|
|
20
|
+
type(): string;
|
|
21
|
+
type(x: string): ChangeIndicator;
|
|
22
|
+
merge(): any;
|
|
23
|
+
merge(newMerge: any): ChangeIndicator;
|
|
24
|
+
options(): ChangeOptions;
|
|
25
|
+
options(newOptions: ChangeOptions): ChangeIndicator;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default function () {
|
|
29
|
+
const base = baseIndicator().type(ALGORITHM_TYPE);
|
|
30
|
+
|
|
31
|
+
const underlyingAlgorithm = change();
|
|
32
|
+
|
|
33
|
+
const mergedAlgorithm = merge()
|
|
34
|
+
.algorithm(underlyingAlgorithm)
|
|
35
|
+
.merge((datum: any, i: any) => {
|
|
36
|
+
datum.absoluteChange = i.absoluteChange;
|
|
37
|
+
datum.percentChange = i.percentChange;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const indicator = (data: any[], options = { merge: true }) => {
|
|
41
|
+
if (options.merge) {
|
|
42
|
+
return mergedAlgorithm(data);
|
|
43
|
+
}
|
|
44
|
+
return underlyingAlgorithm(data);
|
|
45
|
+
};
|
|
46
|
+
rebind(indicator, base, "id", "accessor", "stroke", "fill", "echo", "type");
|
|
47
|
+
rebind(indicator, underlyingAlgorithm, "options");
|
|
48
|
+
rebind(indicator, mergedAlgorithm, "merge", "skipUndefined");
|
|
49
|
+
|
|
50
|
+
return indicator as ChangeIndicator;
|
|
51
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { merge, rebind } from "../utils";
|
|
2
|
+
import { compare } from "../calculator";
|
|
3
|
+
import { CompareOptions } from "../calculator/compare";
|
|
4
|
+
import baseIndicator from "./baseIndicator";
|
|
5
|
+
|
|
6
|
+
const ALGORITHM_TYPE = "Compare";
|
|
7
|
+
|
|
8
|
+
interface CompareIndicator {
|
|
9
|
+
(data: any[], options?: { merge: boolean }): any;
|
|
10
|
+
id(): number;
|
|
11
|
+
id(x: number): CompareIndicator;
|
|
12
|
+
accessor(): any;
|
|
13
|
+
accessor(x: any): CompareIndicator;
|
|
14
|
+
stroke(): string | any;
|
|
15
|
+
stroke(x: string | any): CompareIndicator;
|
|
16
|
+
fill(): string | any;
|
|
17
|
+
fill(x: string | any): CompareIndicator;
|
|
18
|
+
echo(): any;
|
|
19
|
+
echo(x: any): CompareIndicator;
|
|
20
|
+
type(): string;
|
|
21
|
+
type(x: string): CompareIndicator;
|
|
22
|
+
merge(): any;
|
|
23
|
+
merge(newMerge: any): CompareIndicator;
|
|
24
|
+
options(): CompareOptions;
|
|
25
|
+
options(newOptions: CompareOptions): CompareIndicator;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default function () {
|
|
29
|
+
const base = baseIndicator()
|
|
30
|
+
.type(ALGORITHM_TYPE)
|
|
31
|
+
.accessor((d: any) => d.compare);
|
|
32
|
+
|
|
33
|
+
const underlyingAlgorithm = compare();
|
|
34
|
+
|
|
35
|
+
const mergedAlgorithm = merge()
|
|
36
|
+
.algorithm(underlyingAlgorithm)
|
|
37
|
+
.merge((datum: any, i: number) => {
|
|
38
|
+
datum.compare = i;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const indicator = (data: any[], options = { merge: true }) => {
|
|
42
|
+
if (options.merge) {
|
|
43
|
+
if (!base.accessor()) {
|
|
44
|
+
throw new Error(`Set an accessor to ${ALGORITHM_TYPE} before calculating`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return mergedAlgorithm(data);
|
|
48
|
+
}
|
|
49
|
+
return underlyingAlgorithm(data);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
rebind(indicator, base, "id", "accessor", "stroke", "fill", "echo", "type");
|
|
53
|
+
rebind(indicator, underlyingAlgorithm, "options");
|
|
54
|
+
rebind(indicator, mergedAlgorithm, "merge");
|
|
55
|
+
|
|
56
|
+
return indicator as CompareIndicator;
|
|
57
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const themes = {
|
|
2
|
+
light: {
|
|
3
|
+
BollingerBand: {
|
|
4
|
+
stroke: {
|
|
5
|
+
top: "#964B00",
|
|
6
|
+
middle: "#000000",
|
|
7
|
+
bottom: "#964B00",
|
|
8
|
+
},
|
|
9
|
+
fill: "#4682B4",
|
|
10
|
+
},
|
|
11
|
+
ElderImpulse: {
|
|
12
|
+
stroke: {
|
|
13
|
+
up: "#6BA583",
|
|
14
|
+
down: "#FF0000",
|
|
15
|
+
neutral: "#0000FF",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
MACD: {
|
|
19
|
+
fill: {
|
|
20
|
+
divergence: "#4682B4",
|
|
21
|
+
},
|
|
22
|
+
stroke: {
|
|
23
|
+
macd: "#FF0000",
|
|
24
|
+
signal: "#00F300",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
FullStochasticOscillator: {
|
|
28
|
+
stroke: {
|
|
29
|
+
top: "#37a600",
|
|
30
|
+
middle: "#b8ab00",
|
|
31
|
+
bottom: "#37a600",
|
|
32
|
+
dLine: "#17becf",
|
|
33
|
+
kLine: "#ff7f0e",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
dark: {
|
|
38
|
+
BollingerBand: {
|
|
39
|
+
stroke: {
|
|
40
|
+
top: "#964B00",
|
|
41
|
+
middle: "#FF6600",
|
|
42
|
+
bottom: "#964B00",
|
|
43
|
+
},
|
|
44
|
+
fill: "#4682B4",
|
|
45
|
+
},
|
|
46
|
+
ElderImpulse: {
|
|
47
|
+
stroke: {
|
|
48
|
+
up: "#6BA583",
|
|
49
|
+
down: "#FF0000",
|
|
50
|
+
neutral: "#0000FF",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
MACD: {
|
|
54
|
+
fill: {
|
|
55
|
+
divergence: "#FF6600",
|
|
56
|
+
},
|
|
57
|
+
stroke: {
|
|
58
|
+
macd: "#ea2bff",
|
|
59
|
+
signal: "#74d400",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
FullStochasticOscillator: {
|
|
63
|
+
stroke: {
|
|
64
|
+
top: "#37a600",
|
|
65
|
+
middle: "#b8ab00",
|
|
66
|
+
bottom: "#37a600",
|
|
67
|
+
dLine: "#ea2bff",
|
|
68
|
+
kLine: "#74d400",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const BollingerBand = themes.light.BollingerBand;
|
|
75
|
+
export const ElderImpulse = themes.light.ElderImpulse;
|
|
76
|
+
export const MACD = themes.light.MACD;
|
|
77
|
+
export const FullStochasticOscillator = themes.light.FullStochasticOscillator;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { merge, rebind, slidingWindow } from "../utils";
|
|
2
|
+
import baseIndicator from "./baseIndicator";
|
|
3
|
+
import { ElderImpulse as appearanceOptions } from "./defaultOptionsForAppearance";
|
|
4
|
+
|
|
5
|
+
const ALGORITHM_TYPE = "ElderImpulse";
|
|
6
|
+
|
|
7
|
+
export default function () {
|
|
8
|
+
let macdSource: any | undefined;
|
|
9
|
+
let emaSource: any | undefined;
|
|
10
|
+
|
|
11
|
+
const base = baseIndicator().type(ALGORITHM_TYPE).stroke(appearanceOptions.stroke).fill(undefined);
|
|
12
|
+
|
|
13
|
+
const underlyingAlgorithm = slidingWindow()
|
|
14
|
+
.windowSize(2)
|
|
15
|
+
.undefinedValue("neutral")
|
|
16
|
+
.accumulator(([prev, curr]: any) => {
|
|
17
|
+
if (macdSource === undefined) {
|
|
18
|
+
throw new Error(`macdSource not defined for ${ALGORITHM_TYPE} calculator`);
|
|
19
|
+
}
|
|
20
|
+
if (emaSource === undefined) {
|
|
21
|
+
throw new Error(`emaSource not defined for ${ALGORITHM_TYPE} calculator`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const prevMacd = macdSource(prev);
|
|
25
|
+
const prevEMA = emaSource(prev);
|
|
26
|
+
|
|
27
|
+
if (prevMacd !== undefined && prevEMA !== undefined) {
|
|
28
|
+
const prevMACDDivergence = prevMacd.divergence;
|
|
29
|
+
const currMACDDivergence = macdSource(curr).divergence;
|
|
30
|
+
|
|
31
|
+
const currEMA = emaSource(curr);
|
|
32
|
+
|
|
33
|
+
if (currMACDDivergence >= prevMACDDivergence && currEMA >= prevEMA) {
|
|
34
|
+
return "up";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (currMACDDivergence <= prevMACDDivergence && currEMA <= prevEMA) {
|
|
38
|
+
return "down";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return "neutral";
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const mergedAlgorithm = merge()
|
|
45
|
+
.algorithm(underlyingAlgorithm)
|
|
46
|
+
.merge((datum: any, i: number) => {
|
|
47
|
+
datum.elderImpulse = i;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const indicator = function (data: any, options = { merge: true }) {
|
|
51
|
+
const newData = options.merge ? mergedAlgorithm(data) : underlyingAlgorithm(data);
|
|
52
|
+
|
|
53
|
+
return newData;
|
|
54
|
+
};
|
|
55
|
+
indicator.macdSource = function (x: any) {
|
|
56
|
+
if (!arguments.length) {
|
|
57
|
+
return macdSource;
|
|
58
|
+
}
|
|
59
|
+
macdSource = x;
|
|
60
|
+
return indicator;
|
|
61
|
+
};
|
|
62
|
+
indicator.emaSource = function (x: any) {
|
|
63
|
+
if (!arguments.length) {
|
|
64
|
+
return emaSource;
|
|
65
|
+
}
|
|
66
|
+
emaSource = x;
|
|
67
|
+
return indicator;
|
|
68
|
+
};
|
|
69
|
+
rebind(indicator, base, "id", "echo", "type", "stroke");
|
|
70
|
+
rebind(indicator, mergedAlgorithm, "merge", "skipUndefined");
|
|
71
|
+
|
|
72
|
+
return indicator;
|
|
73
|
+
}
|