ohlcv-indicators 1.9.2 → 1.9.4
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/dist/ohlcv-indicators.min.js +1 -1
- package/index.js +70 -142
- package/package.json +1 -1
- package/src/moving-averages/bollingerBands.js +49 -75
- package/src/moving-averages/donchianChannel.js +47 -56
- package/src/moving-averages/ema.js +15 -40
- package/src/moving-averages/macd.js +30 -37
- package/src/moving-averages/relativeVolume.js +31 -39
- package/src/moving-averages/sma.js +15 -35
- package/src/oscillators/rsi.js +38 -50
- package/src/oscillators/volumeOscillator.js +34 -34
- package/src/studies/candleStudies.js +140 -167
- package/src/studies/findCrosses.js +95 -117
- package/src/studies/lag.js +27 -0
- package/src/utilities/parsing-utilities.js +197 -144
- package/src/utilities/setIndicatorsFromInputParams.js +1 -3
- package/src/oscillators/orb.js +0 -41
|
@@ -1,99 +1,73 @@
|
|
|
1
|
-
|
|
2
1
|
import {FasterBollingerBands, FasterSMA} from 'trading-signals';
|
|
3
2
|
import { classifySize } from '../utilities/classification.js';
|
|
4
3
|
|
|
5
|
-
export const bollingerBands = (main, size, times, bollingerBandsStudies) => {
|
|
6
|
-
|
|
7
|
-
const {verticalOhlcv} = main
|
|
8
|
-
const {close} = verticalOhlcv
|
|
4
|
+
export const bollingerBands = (main, index, size, times, bollingerBandsStudies = false) => {
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
return col
|
|
12
|
-
}
|
|
6
|
+
const value = main.verticalOhlcv.close[index]
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const dataLength = data.length
|
|
17
|
-
const bollinger_bands_upper = Array(dataLength).fill(null)
|
|
18
|
-
const bollinger_bands_middle = Array(dataLength).fill(null)
|
|
19
|
-
const bollinger_bands_lower = Array(dataLength).fill(null)
|
|
8
|
+
if (!main.instances.hasOwnProperty(`bollinger_bands`)) {
|
|
20
9
|
|
|
10
|
+
Object.assign(main.instances, {bollinger_bands: {
|
|
11
|
+
instance: new FasterBollingerBands(size, times),
|
|
12
|
+
heightInstance: bollingerBandsStudies ? new FasterSMA(size) : null
|
|
13
|
+
}})
|
|
21
14
|
|
|
22
|
-
let bollinger_bands_range
|
|
23
|
-
let bollinger_bands_height
|
|
24
|
-
let heightInstance
|
|
25
|
-
let range = null
|
|
26
|
-
let height = null
|
|
27
15
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
16
|
+
Object.assign(main.verticalOhlcv, {
|
|
17
|
+
bollinger_bands_upper: new Array(main.len).fill(null),
|
|
18
|
+
bollinger_bands_middle: new Array(main.len).fill(null),
|
|
19
|
+
bollinger_bands_lower: new Array(main.len).fill(null)
|
|
20
|
+
})
|
|
34
21
|
|
|
35
|
-
|
|
36
|
-
range: ((value - lower) / (upper - lower)),
|
|
37
|
-
height: upper-lower
|
|
38
|
-
})
|
|
22
|
+
if (bollingerBandsStudies) {
|
|
39
23
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let hasNull = false
|
|
47
|
-
let heightMean
|
|
24
|
+
Object.assign(main.verticalOhlcv, {
|
|
25
|
+
bollinger_bands_range: new Array(main.len).fill(null),
|
|
26
|
+
bollinger_bands_height: new Array(main.len).fill(null),
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
}
|
|
48
30
|
|
|
31
|
+
const { instance, heightInstance } = main.instances[`bollinger_bands`];
|
|
32
|
+
instance.update(value);
|
|
49
33
|
|
|
34
|
+
let result;
|
|
50
35
|
try {
|
|
51
|
-
|
|
36
|
+
result = instance.getResult();
|
|
52
37
|
} catch (err) {
|
|
53
|
-
|
|
54
|
-
obj = { upper: null, middle: null, lower: null }
|
|
38
|
+
//do nothing
|
|
55
39
|
}
|
|
56
40
|
|
|
57
|
-
|
|
58
|
-
bollinger_bands_middle[x] = obj.middle;
|
|
59
|
-
bollinger_bands_lower[x] = obj.lower;
|
|
60
|
-
|
|
61
|
-
if(bollingerBandsStudies === false) continue
|
|
62
|
-
|
|
63
|
-
if(hasNull)
|
|
64
|
-
{
|
|
65
|
-
bollinger_bands_range[x] = null
|
|
66
|
-
bollinger_bands_height[x] = null
|
|
67
|
-
}
|
|
68
|
-
else
|
|
69
|
-
{
|
|
70
|
-
const extraProps = getRange(data[x], obj.upper, obj.lower)
|
|
71
|
-
range = extraProps.range
|
|
72
|
-
height = extraProps.height
|
|
41
|
+
if(!result) return true
|
|
73
42
|
|
|
74
|
-
|
|
43
|
+
const { upper, middle, lower } = result;
|
|
44
|
+
main.verticalOhlcv.bollinger_bands_upper[index] = upper;
|
|
45
|
+
main.verticalOhlcv.bollinger_bands_middle[index] = middle;
|
|
46
|
+
main.verticalOhlcv.bollinger_bands_lower[index] = lower;
|
|
75
47
|
|
|
76
|
-
|
|
77
|
-
heightMean = heightInstance.getResult()
|
|
78
|
-
}
|
|
79
|
-
catch(err)
|
|
80
|
-
{
|
|
81
|
-
heightMean = null
|
|
82
|
-
}
|
|
48
|
+
if (!bollingerBandsStudies) return true;
|
|
83
49
|
|
|
84
|
-
|
|
50
|
+
let range = null;
|
|
51
|
+
let height = null;
|
|
52
|
+
let heightMean;
|
|
85
53
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
54
|
+
range = (value - lower) / (upper - lower);
|
|
55
|
+
height = upper - lower;
|
|
89
56
|
|
|
90
|
-
|
|
57
|
+
heightInstance.update(height);
|
|
91
58
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
59
|
+
try {
|
|
60
|
+
heightMean = heightInstance.getResult();
|
|
61
|
+
} catch (err) {
|
|
62
|
+
//do nothing
|
|
63
|
+
}
|
|
96
64
|
|
|
97
|
-
|
|
98
|
-
}
|
|
65
|
+
main.verticalOhlcv.bollinger_bands_range[index] = range;
|
|
99
66
|
|
|
67
|
+
if(heightMean)
|
|
68
|
+
{
|
|
69
|
+
main.verticalOhlcv.bollinger_bands_height[index] = classifySize(height, heightMean, 1.5);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
@@ -1,59 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
while (maxQueue.length && maxQueue[0] <= i - period) {
|
|
22
|
-
maxQueue.shift()
|
|
23
|
-
}
|
|
24
|
-
// Remove smaller values from the end
|
|
25
|
-
while (maxQueue.length && high[maxQueue[maxQueue.length - 1]] <= high[i]) {
|
|
26
|
-
maxQueue.pop()
|
|
27
|
-
}
|
|
28
|
-
maxQueue.push(i)
|
|
29
|
-
|
|
30
|
-
while (minQueue.length && minQueue[0] <= i - period) {
|
|
31
|
-
minQueue.shift()
|
|
32
|
-
}
|
|
33
|
-
while (minQueue.length && low[minQueue[minQueue.length - 1]] >= low[i]) {
|
|
34
|
-
minQueue.pop()
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
minQueue.push(i)
|
|
38
|
-
|
|
39
|
-
if (i >= period - 1) {
|
|
40
|
-
const upperValue = high[maxQueue[0]]
|
|
41
|
-
const lowerValue = low[minQueue[0]]
|
|
42
|
-
const basisValue = avg(upperValue, lowerValue)
|
|
43
|
-
|
|
44
|
-
const indexWithOffset = i + offset
|
|
45
|
-
|
|
46
|
-
if (indexWithOffset >= 0 && indexWithOffset < len) {
|
|
47
|
-
donchian_channel_upper[indexWithOffset] = upperValue
|
|
48
|
-
donchian_channel_lower[indexWithOffset] = lowerValue
|
|
49
|
-
donchian_channel_basis[indexWithOffset] = basisValue
|
|
50
|
-
}
|
|
51
|
-
}
|
|
1
|
+
const avg = (h, l) => (h + l) / 2;
|
|
2
|
+
|
|
3
|
+
export const donchianChannels = (main, index, size, offset) => {
|
|
4
|
+
|
|
5
|
+
const highs = main.verticalOhlcv.high;
|
|
6
|
+
const lows = main.verticalOhlcv.low;
|
|
7
|
+
|
|
8
|
+
// If we don't have enough data to fill one size ending at (index - offset), return
|
|
9
|
+
if ((index - offset) < (size - 1)) return true;
|
|
10
|
+
|
|
11
|
+
// Ensure that the required arrays exist
|
|
12
|
+
if (!main.instances.hasOwnProperty('donchian_channels')) {
|
|
13
|
+
|
|
14
|
+
main.instances['donchian_channels'] = {};
|
|
15
|
+
|
|
16
|
+
Object.assign(main.verticalOhlcv, {
|
|
17
|
+
donchian_channel_upper: new Array(main.len).fill(null),
|
|
18
|
+
donchian_channel_basis: new Array(main.len).fill(null),
|
|
19
|
+
donchian_channel_lower: new Array(main.len).fill(null),
|
|
20
|
+
})
|
|
52
21
|
}
|
|
53
22
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
23
|
+
|
|
24
|
+
// Compute the slice start and end to get exactly 'size' bars
|
|
25
|
+
const endIdx = (index - offset) + 1; // inclusive end of the slice
|
|
26
|
+
const startIdx = endIdx - size; // start index for slicing
|
|
27
|
+
|
|
28
|
+
// If any of these indices is out of bounds, return
|
|
29
|
+
if (startIdx < 0 || endIdx > main.len) return true;
|
|
30
|
+
|
|
31
|
+
// Extract the relevant chunks of data
|
|
32
|
+
const highChunk = highs.slice(startIdx, endIdx)
|
|
33
|
+
const lowChunk = lows.slice(startIdx, endIdx)
|
|
34
|
+
|
|
35
|
+
// Compute the Donchian channels
|
|
36
|
+
const upper = Math.max(...highChunk);
|
|
37
|
+
const lower = Math.min(...lowChunk);
|
|
38
|
+
const basis = avg(upper, lower);
|
|
39
|
+
|
|
40
|
+
// Place the result at index
|
|
41
|
+
const placementIndex = index;
|
|
42
|
+
|
|
43
|
+
if (placementIndex >= 0 && placementIndex < main.len) {
|
|
44
|
+
main.verticalOhlcv['donchian_channel_upper'][placementIndex] = upper;
|
|
45
|
+
main.verticalOhlcv['donchian_channel_basis'][placementIndex] = basis;
|
|
46
|
+
main.verticalOhlcv['donchian_channel_lower'][placementIndex] = lower;
|
|
58
47
|
}
|
|
59
|
-
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
};
|
|
@@ -1,54 +1,29 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import {FasterEMA} from 'trading-signals'
|
|
3
3
|
|
|
4
|
-
export const ema = (main, size) => {
|
|
4
|
+
export const ema = (main, index, size) => {
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
const {close} = verticalOhlcv
|
|
6
|
+
const value = main.verticalOhlcv.close[index]
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if(!main.instances.hasOwnProperty(`ema_${size}`))
|
|
9
|
+
{
|
|
10
|
+
main.instances[`ema_${size}`] = new FasterEMA(size)
|
|
11
|
+
main.verticalOhlcv[`ema_${size}`] = new Array(main.len).fill(null)
|
|
13
12
|
}
|
|
14
|
-
}
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
let currSma
|
|
15
|
+
main.instances[`ema_${size}`].update(value)
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
try{
|
|
18
|
+
currSma = main.instances[`ema_${size}`].getResult()
|
|
19
|
+
} catch(err)
|
|
20
20
|
{
|
|
21
|
-
|
|
21
|
+
currSma = null
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
const output = new Array(dataLength).fill(null)
|
|
26
|
-
const instance = new FasterEMA(size)
|
|
27
|
-
|
|
28
|
-
for(let x = 0; x < dataLength; x++)
|
|
24
|
+
if(currSma)
|
|
29
25
|
{
|
|
30
|
-
|
|
31
|
-
let value = null
|
|
32
|
-
|
|
33
|
-
if(data[x] !== null)
|
|
34
|
-
{
|
|
35
|
-
instance.update(data[x])
|
|
36
|
-
|
|
37
|
-
try
|
|
38
|
-
{
|
|
39
|
-
value = instance.getResult()
|
|
40
|
-
}
|
|
41
|
-
catch(err)
|
|
42
|
-
{
|
|
43
|
-
value = null
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
output[x] = value
|
|
26
|
+
main.verticalOhlcv[`ema_${size}`][index] = currSma
|
|
48
27
|
}
|
|
49
28
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return output
|
|
53
|
-
|
|
54
29
|
}
|
|
@@ -1,50 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {EMA, MACD, FasterEMA, FasterMACD} from 'trading-signals';
|
|
1
|
+
import {FasterEMA, FasterMACD} from 'trading-signals';
|
|
3
2
|
|
|
3
|
+
export const macd = (main, index, fastLine = 12, slowLine = 26, signalLine = 9) => {
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const value = main.verticalOhlcv.close[index]
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
const {close} = verticalOhlcv
|
|
9
|
-
const col = getMACD(close, fastLine, slowLine, signalLine)
|
|
7
|
+
if (!main.instances.hasOwnProperty('macd')) {
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
}
|
|
9
|
+
main.autoCrossPairsList.push({fast: 'macd_diff', slow: 'macd_dea'});
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
main.instances['macd'] = new FasterMACD(
|
|
12
|
+
new FasterEMA(fastLine),
|
|
13
|
+
new FasterEMA(slowLine),
|
|
14
|
+
new FasterEMA(signalLine)
|
|
15
|
+
);
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
Object.assign(main.verticalOhlcv, {
|
|
18
|
+
macd_diff: new Array(main.len).fill(null),
|
|
19
|
+
macd_dea: new Array(main.len).fill(null),
|
|
20
|
+
macd_histogram: new Array(main.len).fill(null),
|
|
21
|
+
})
|
|
22
|
+
}
|
|
20
23
|
|
|
21
|
-
const
|
|
24
|
+
const macdInstance = main.instances[`macd`];
|
|
25
|
+
macdInstance.update(value);
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
let obj = {}
|
|
26
|
-
instance.update(data[x])
|
|
27
|
-
|
|
28
|
-
try
|
|
29
|
-
{
|
|
30
|
-
obj = instance.getResult()
|
|
31
|
-
}
|
|
32
|
-
catch(err)
|
|
33
|
-
{
|
|
34
|
-
obj = {macd: null, signal: null, histogram: null}
|
|
35
|
-
}
|
|
27
|
+
let macdResult;
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
try {
|
|
30
|
+
macdResult = macdInstance.getResult();
|
|
31
|
+
} catch (err) {
|
|
32
|
+
//do nothing
|
|
40
33
|
}
|
|
41
34
|
|
|
42
|
-
const x = findCrosses({fast: diff, slow: dea})
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
macd_diff_x_macd_dea: x
|
|
36
|
+
if (macdResult) {
|
|
37
|
+
main.verticalOhlcv['macd_diff'][index] = macdResult.macd;
|
|
38
|
+
main.verticalOhlcv['macd_dea'][index] = macdResult.signal;
|
|
39
|
+
main.verticalOhlcv['macd_histogram'][index] = macdResult.histogram;
|
|
49
40
|
}
|
|
50
|
-
|
|
41
|
+
|
|
42
|
+
return true;
|
|
43
|
+
};
|
|
@@ -1,43 +1,35 @@
|
|
|
1
|
-
import {FasterSMA} from 'trading-signals'
|
|
1
|
+
import {FasterSMA} from 'trading-signals';
|
|
2
2
|
|
|
3
|
-
export const relativeVolume = (main, size = 10) => {
|
|
4
|
-
const {verticalOhlcv} = main
|
|
5
|
-
const {volume} = verticalOhlcv
|
|
6
|
-
const col = getRelativeVolume(volume, size)
|
|
3
|
+
export const relativeVolume = (main, index, size = 10) => {
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const value = main.verticalOhlcv.volume[index]
|
|
6
|
+
|
|
7
|
+
if (!main.instances.hasOwnProperty(`relative_volume_${size}`)) {
|
|
8
|
+
main.instances[`relative_volume_${size}`] = new FasterSMA(size);
|
|
9
|
+
|
|
10
|
+
Object.assign(main.verticalOhlcv, {
|
|
11
|
+
[`relative_volume_${size}`]: new Array(main.len).fill(null),
|
|
12
|
+
[`relative_volume_sma_${size}`]: new Array(main.len).fill(null)
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const smaInstance = main.instances[`relative_volume_${size}`]
|
|
17
|
+
smaInstance.update(value)
|
|
18
|
+
|
|
19
|
+
let smaValue;
|
|
20
|
+
try {
|
|
21
|
+
smaValue = smaInstance.getResult()
|
|
22
|
+
} catch (err) {
|
|
23
|
+
//do nothing
|
|
10
24
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
for(let x = 0; x < volume.length; x++)
|
|
20
|
-
{
|
|
21
|
-
let value = null
|
|
22
|
-
|
|
23
|
-
instance.update(volume[x])
|
|
24
|
-
|
|
25
|
-
try
|
|
26
|
-
{
|
|
27
|
-
value = instance.getResult()
|
|
28
|
-
}
|
|
29
|
-
catch(err)
|
|
30
|
-
{
|
|
31
|
-
value = null
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
sma[x] = value
|
|
35
|
-
|
|
36
|
-
if(typeof sma[x-1] === 'number')
|
|
37
|
-
{
|
|
38
|
-
output[x] = volume[x] / sma[x-1]
|
|
39
|
-
}
|
|
25
|
+
|
|
26
|
+
main.verticalOhlcv[`relative_volume_sma_${size}`][index] = smaValue;
|
|
27
|
+
|
|
28
|
+
if (smaValue !== null && typeof main.verticalOhlcv[`relative_volume_sma_${size}`][index - 1] === 'number') {
|
|
29
|
+
main.verticalOhlcv[`relative_volume_${size}`][index] = value / main.verticalOhlcv[`relative_volume_sma_${size}`][index - 1];
|
|
30
|
+
} else {
|
|
31
|
+
main.verticalOhlcv[`relative_volume_${size}`][index] = null;
|
|
40
32
|
}
|
|
41
|
-
|
|
42
|
-
return
|
|
43
|
-
}
|
|
33
|
+
|
|
34
|
+
return true;
|
|
35
|
+
};
|
|
@@ -1,49 +1,29 @@
|
|
|
1
1
|
|
|
2
2
|
import {FasterSMA} from 'trading-signals';
|
|
3
3
|
|
|
4
|
-
export const sma = (main, size) => {
|
|
4
|
+
export const sma = (main, index, size) => {
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
const {close} = verticalOhlcv
|
|
6
|
+
const value = main.verticalOhlcv.close[index]
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if(!main.instances.hasOwnProperty(`sma_${size}`))
|
|
9
|
+
{
|
|
10
|
+
main.instances[`sma_${size}`] = new FasterSMA(size)
|
|
11
|
+
main.verticalOhlcv[`sma_${size}`] = new Array(main.len).fill(null)
|
|
13
12
|
}
|
|
14
|
-
}
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
let currSma
|
|
15
|
+
main.instances[`sma_${size}`].update(value)
|
|
16
|
+
|
|
17
|
+
try{
|
|
18
|
+
currSma = main.instances[`sma_${size}`].getResult()
|
|
19
|
+
} catch(err)
|
|
19
20
|
{
|
|
20
|
-
|
|
21
|
+
//do nothing
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
const output = new Array(dataLength).fill(null)
|
|
25
|
-
const instance = new FasterSMA(size)
|
|
26
|
-
|
|
27
|
-
for(let x = 0; x < dataLength; x++)
|
|
24
|
+
if(currSma)
|
|
28
25
|
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if(data[x] !== null)
|
|
32
|
-
{
|
|
33
|
-
instance.update(data[x])
|
|
34
|
-
|
|
35
|
-
try
|
|
36
|
-
{
|
|
37
|
-
value = instance.getResult()
|
|
38
|
-
}
|
|
39
|
-
catch(err)
|
|
40
|
-
{
|
|
41
|
-
value = null
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
output[x] = value
|
|
26
|
+
main.verticalOhlcv[`sma_${size}`][index] = currSma
|
|
46
27
|
}
|
|
47
28
|
|
|
48
|
-
return output
|
|
49
29
|
}
|
package/src/oscillators/rsi.js
CHANGED
|
@@ -1,68 +1,56 @@
|
|
|
1
|
-
import { getSMA } from "../moving-averages/sma.js";
|
|
2
|
-
import { getEMA } from "../moving-averages/ema.js";
|
|
3
|
-
import { findCrosses } from "../studies/findCrosses.js";
|
|
4
1
|
import {FasterRSI} from 'trading-signals';
|
|
2
|
+
import { FasterSMA } from 'trading-signals';
|
|
5
3
|
|
|
6
|
-
const ma = {getSMA, getEMA}
|
|
7
4
|
|
|
8
|
-
export const rsi = (main,
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const {close} = verticalOhlcv
|
|
5
|
+
export const rsi = (main, index, size) => {
|
|
6
|
+
|
|
7
|
+
const value = main.verticalOhlcv.close[index]
|
|
12
8
|
|
|
13
|
-
if(
|
|
9
|
+
if(!main.instances.hasOwnProperty(`rsi_${size}`))
|
|
14
10
|
{
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const col = getRSI(close, period, movingAverage, movingAveragePeriod)
|
|
11
|
+
main.autoCrossPairsList.push({fast: `rsi_${size}`, slow: `rsi_sma_${size}`})
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
}
|
|
13
|
+
Object.assign(main.instances, {
|
|
14
|
+
[`rsi_${size}`]: new FasterRSI(size),
|
|
15
|
+
[`rsi_sma_${size}`]: new FasterSMA(size)
|
|
16
|
+
})
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (dataLength < period) {
|
|
28
|
-
return [];
|
|
18
|
+
Object.assign(main.verticalOhlcv, {
|
|
19
|
+
[`rsi_${size}`]: new Array(main.len).fill(null),
|
|
20
|
+
[`rsi_sma_${size}`]: new Array(main.len).fill(null)
|
|
21
|
+
})
|
|
29
22
|
}
|
|
23
|
+
|
|
24
|
+
let currentRsi
|
|
25
|
+
let smoothedRsi
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
const instance = new FasterRSI(period)
|
|
27
|
+
main.instances[`rsi_${size}`].update(value)
|
|
33
28
|
|
|
34
|
-
|
|
29
|
+
try
|
|
35
30
|
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
instance.update(data[x])
|
|
41
|
-
|
|
42
|
-
try
|
|
43
|
-
{
|
|
44
|
-
value = instance.getResult()
|
|
45
|
-
}
|
|
46
|
-
catch(err)
|
|
47
|
-
{
|
|
48
|
-
value = null
|
|
49
|
-
}
|
|
50
|
-
}
|
|
31
|
+
currentRsi = main.instances[`rsi_${size}`].getResult()
|
|
32
|
+
} catch(err) {
|
|
33
|
+
currentRsi = null
|
|
34
|
+
}
|
|
51
35
|
|
|
52
|
-
|
|
36
|
+
if(currentRsi)
|
|
37
|
+
{
|
|
38
|
+
main.verticalOhlcv[`rsi_${size}`][index] = currentRsi
|
|
39
|
+
main.instances[`rsi_sma_${size}`].update(currentRsi)
|
|
53
40
|
}
|
|
54
41
|
|
|
55
|
-
|
|
42
|
+
try
|
|
43
|
+
{
|
|
44
|
+
smoothedRsi = main.instances[`rsi_sma_${size}`].getResult()
|
|
45
|
+
} catch(err)
|
|
46
|
+
{
|
|
47
|
+
smoothedRsi = null
|
|
48
|
+
}
|
|
56
49
|
|
|
57
|
-
if(
|
|
50
|
+
if(smoothedRsi)
|
|
58
51
|
{
|
|
59
|
-
|
|
60
|
-
{
|
|
61
|
-
const rsi_smoothed = ma[`get${movingAverage}`](rsi, movingAveragePeriod)
|
|
62
|
-
output[`rsi_${movingAverage}_${movingAveragePeriod}`] = rsi_smoothed
|
|
63
|
-
output[`rsi_${period}_x_rsi_${movingAverage}_${movingAveragePeriod}`] = findCrosses({fast: rsi, slow: rsi_smoothed})
|
|
64
|
-
}
|
|
52
|
+
main.verticalOhlcv[`rsi_sma_${size}`][index] = smoothedRsi
|
|
65
53
|
}
|
|
66
54
|
|
|
67
|
-
return
|
|
68
|
-
}
|
|
55
|
+
return true
|
|
56
|
+
}
|