ohlcv-indicators 1.8.3 → 1.8.5
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/index.js
CHANGED
|
@@ -192,10 +192,10 @@ export default class OHLCV_INDICATORS {
|
|
|
192
192
|
return this
|
|
193
193
|
|
|
194
194
|
}
|
|
195
|
-
bollingerBands(size, times)
|
|
195
|
+
bollingerBands(size, times, bollingerBandsStudies)
|
|
196
196
|
{
|
|
197
197
|
|
|
198
|
-
const result = bollingerBands(this, size, times)
|
|
198
|
+
const result = bollingerBands(this, size, times, bollingerBandsStudies)
|
|
199
199
|
Object.assign(this.indicators, result)
|
|
200
200
|
|
|
201
201
|
this.priceBased.push('bollinger_bands_middle', 'bollinger_bands_upper', 'bollinger_bands_lower')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ohlcv-indicators",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.5",
|
|
4
4
|
"description": "A JavaScript library featuring optimized trading indicators for OHLCV arrays [{open, high, low, close, value}]. This library is optimized for backtesting and trading bot development.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -2,30 +2,36 @@
|
|
|
2
2
|
import {FasterBollingerBands, FasterSMA} from 'trading-signals';
|
|
3
3
|
import { classifySize } from '../utilities/classification.js';
|
|
4
4
|
|
|
5
|
-
export const bollingerBands = (main, size, times) => {
|
|
5
|
+
export const bollingerBands = (main, size, times, bollingerBandsStudies) => {
|
|
6
6
|
|
|
7
7
|
const {verticalOhlcv} = main
|
|
8
8
|
const {close} = verticalOhlcv
|
|
9
9
|
|
|
10
|
-
const col = getBollingerBands(close, size, times)
|
|
10
|
+
const col = getBollingerBands(close, size, times, bollingerBandsStudies)
|
|
11
11
|
return col
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export const getBollingerBands = (data, size = 20, times = 2) => {
|
|
14
|
+
export const getBollingerBands = (data, size = 20, times = 2, bollingerBandsStudies = false) => {
|
|
15
15
|
|
|
16
16
|
const dataLength = data.length
|
|
17
17
|
const bollinger_bands_upper = Array(dataLength).fill(null)
|
|
18
18
|
const bollinger_bands_middle = Array(dataLength).fill(null)
|
|
19
19
|
const bollinger_bands_lower = Array(dataLength).fill(null)
|
|
20
|
-
const bollinger_bands_range = Array(dataLength).fill(null)
|
|
21
|
-
const bollinger_bands_height = Array(dataLength).fill(null)
|
|
22
20
|
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
let bollinger_bands_range
|
|
23
|
+
let bollinger_bands_height
|
|
24
|
+
let heightInstance
|
|
26
25
|
let range = null
|
|
27
26
|
let height = null
|
|
28
27
|
|
|
28
|
+
if(bollingerBandsStudies)
|
|
29
|
+
{
|
|
30
|
+
bollinger_bands_range = Array(dataLength).fill(null)
|
|
31
|
+
bollinger_bands_height = Array(dataLength).fill(null)
|
|
32
|
+
heightInstance = new FasterSMA(size)
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
let getRange = (value, upper, lower) => ({
|
|
30
36
|
range: ((value - lower) / (upper - lower)),
|
|
31
37
|
height: upper-lower
|
|
@@ -52,6 +58,8 @@ export const getBollingerBands = (data, size = 20, times = 2) => {
|
|
|
52
58
|
bollinger_bands_middle[x] = obj.middle;
|
|
53
59
|
bollinger_bands_lower[x] = obj.lower;
|
|
54
60
|
|
|
61
|
+
if(bollingerBandsStudies === false) continue
|
|
62
|
+
|
|
55
63
|
if(hasNull)
|
|
56
64
|
{
|
|
57
65
|
bollinger_bands_range[x] = null
|
|
@@ -79,6 +87,13 @@ export const getBollingerBands = (data, size = 20, times = 2) => {
|
|
|
79
87
|
bollinger_bands_height[x] = classifySize(height, heightMean, 1.5)
|
|
80
88
|
}
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
let output = { bollinger_bands_upper, bollinger_bands_middle, bollinger_bands_lower }
|
|
91
|
+
|
|
92
|
+
if(bollingerBandsStudies)
|
|
93
|
+
{
|
|
94
|
+
output = {...output, bollinger_bands_range, bollinger_bands_height}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return output
|
|
83
98
|
}
|
|
84
99
|
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {FasterSMA} from 'trading-signals'
|
|
2
2
|
import { classifyChange, classifySize } from '../utilities/classification.js'
|
|
3
3
|
|
|
4
|
-
export const candlesStudies = (main, period, classify) => {
|
|
4
|
+
export const candlesStudies = (main, period, classify, classificationLevels) => {
|
|
5
5
|
|
|
6
6
|
const {inputOhlcv, len} = main
|
|
7
7
|
|
|
8
|
-
const cols = getCandlesStudies(inputOhlcv, period, len, classify)
|
|
8
|
+
const cols = getCandlesStudies(inputOhlcv, period, len, classify, classificationLevels)
|
|
9
9
|
return cols
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
const getCandlesStudies = (inputOhlcv, period = 20, len, classify = true) => {
|
|
12
|
+
const getCandlesStudies = (inputOhlcv, period = 20, len, classify = true, classificationLevels = {}) => {
|
|
13
13
|
|
|
14
|
+
const {changeLevel = 7, sizeLevel = 5} = classificationLevels
|
|
15
|
+
|
|
14
16
|
//close > open
|
|
15
17
|
let candle_body_size = new Array(len).fill(null) //scaled candle direction close - open
|
|
16
18
|
let candle_top_size = new Array(len).fill(null) //scaled top size (0, 0.5 and 1)
|
|
@@ -64,8 +66,8 @@ const getCandlesStudies = (inputOhlcv, period = 20, len, classify = true) => {
|
|
|
64
66
|
const shadowSize = curr.high - curr.low
|
|
65
67
|
|
|
66
68
|
//sizes
|
|
67
|
-
const topSize =
|
|
68
|
-
const bottomSize = (
|
|
69
|
+
const topSize = high - Math.max(open, close)
|
|
70
|
+
const bottomSize = Math.min(open, close) - low
|
|
69
71
|
const gapSize = prev.close - curr.open
|
|
70
72
|
const position = curr.close - prev.close
|
|
71
73
|
|
|
@@ -101,14 +103,14 @@ const getCandlesStudies = (inputOhlcv, period = 20, len, classify = true) => {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
//negatives and positives
|
|
104
|
-
candle_body_size[x] = classifyChange(candleBodySize, bodySizeMean, 0.5)
|
|
105
|
-
candle_gap_size[x] = classifyChange(gapSize, gapMean, 0.5)
|
|
106
|
-
candle_position[x] = classifyChange(position, positionMean, 0.5)
|
|
106
|
+
candle_body_size[x] = classifyChange(candleBodySize, bodySizeMean, 0.5, changeLevel)
|
|
107
|
+
candle_gap_size[x] = classifyChange(gapSize, gapMean, 0.5, changeLevel)
|
|
108
|
+
candle_position[x] = classifyChange(position, positionMean, 0.5, changeLevel)
|
|
107
109
|
|
|
108
110
|
//positives only
|
|
109
|
-
candle_top_size[x] = classifySize(topSize, topSizeMean, 0.5)
|
|
110
|
-
candle_bottom_size[x] = classifySize(bottomSize, bottomSizeMean, 0.5)
|
|
111
|
-
candle_shadow_size[x] = classifySize(shadowSize, shadowSizeMean, 0.5)
|
|
111
|
+
candle_top_size[x] = classifySize(topSize, topSizeMean, 0.5, sizeLevel)
|
|
112
|
+
candle_bottom_size[x] = classifySize(bottomSize, bottomSizeMean, 0.5, sizeLevel)
|
|
113
|
+
candle_shadow_size[x] = classifySize(shadowSize, shadowSizeMean, 0.5, sizeLevel)
|
|
112
114
|
}
|
|
113
115
|
else{
|
|
114
116
|
//negatives and positives
|
|
@@ -1,49 +1,44 @@
|
|
|
1
|
+
export const classifySize = (value, mean, standardDeviation = 1.5, numLevels = 5) => {
|
|
2
|
+
if (value === null || mean === null || standardDeviation === null) return null
|
|
3
|
+
if (numLevels < 2) throw new Error("numLevels must be at least 2")
|
|
1
4
|
|
|
2
|
-
|
|
5
|
+
// Calculate the range for each level
|
|
6
|
+
const step = (4 * standardDeviation) / (numLevels - 1)
|
|
7
|
+
const thresholds = []
|
|
8
|
+
|
|
9
|
+
for (let i = 0; i < numLevels - 1; i++) {
|
|
10
|
+
thresholds.push(mean - (2 * standardDeviation) + (i * step))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Classify the value based on calculated thresholds
|
|
14
|
+
for (let i = thresholds.length - 1; i >= 0; i--) {
|
|
15
|
+
if (value > thresholds[i]) {
|
|
16
|
+
return (i + 1) / (numLevels - 1)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return 0
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export const classifyChange = (value, mean, standardDeviation = 0.5, numLevels = 7) => {
|
|
3
25
|
if (value === null || mean === null || standardDeviation === null) return null;
|
|
26
|
+
if (numLevels < 2) throw new Error("numLevels must be at least 2");
|
|
4
27
|
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const verySmallThreshold = mean - (1.5 * standardDeviation); // Very small (1.5σ below mean)
|
|
28
|
+
// Calculate the range for each level
|
|
29
|
+
const step = (4 * standardDeviation) / (numLevels - 1);
|
|
30
|
+
const thresholds = [];
|
|
9
31
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} else if (value > mediumThreshold) {
|
|
13
|
-
return 0.75; // Medium
|
|
14
|
-
} else if (value > smallThreshold) {
|
|
15
|
-
return 0.5; // Small
|
|
16
|
-
} else if (value > verySmallThreshold) {
|
|
17
|
-
return 0.25; // Very small
|
|
18
|
-
} else {
|
|
19
|
-
return 0; // Insignificant
|
|
32
|
+
for (let i = 0; i < numLevels - 1; i++) {
|
|
33
|
+
thresholds.push(mean - (2 * standardDeviation) + (i * step));
|
|
20
34
|
}
|
|
21
|
-
};
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const mediumPositiveThreshold = mean + (1.5 * standardDeviation); // Medium positive (1.5σ)
|
|
29
|
-
const smallPositiveThreshold = mean + (0.5 * standardDeviation); // Small positive (0.5σ)
|
|
30
|
-
const smallNegativeThreshold = mean - (0.5 * standardDeviation); // Small negative (-0.5σ)
|
|
31
|
-
const mediumNegativeThreshold = mean - (1.5 * standardDeviation); // Medium negative (-1.5σ)
|
|
32
|
-
const largeNegativeThreshold = mean - (2 * standardDeviation); // Large negative
|
|
33
|
-
|
|
34
|
-
if (value >= largePositiveThreshold) {
|
|
35
|
-
return 1; // Large positive
|
|
36
|
-
} else if (value >= mediumPositiveThreshold) {
|
|
37
|
-
return 0.5; // Medium positive
|
|
38
|
-
} else if (value >= smallPositiveThreshold) {
|
|
39
|
-
return 0.25; // Small positive
|
|
40
|
-
} else if (value <= largeNegativeThreshold) {
|
|
41
|
-
return -1; // Large negative
|
|
42
|
-
} else if (value <= mediumNegativeThreshold) {
|
|
43
|
-
return -0.5; // Medium negative
|
|
44
|
-
} else if (value <= smallNegativeThreshold) {
|
|
45
|
-
return -0.25; // Small negative
|
|
46
|
-
} else {
|
|
47
|
-
return 0; // No significant change
|
|
36
|
+
// Classify the value based on calculated thresholds
|
|
37
|
+
for (let i = thresholds.length - 1; i >= 0; i--) {
|
|
38
|
+
if (value > thresholds[i]) {
|
|
39
|
+
return (i - Math.floor((numLevels - 1) / 2)) / Math.floor((numLevels - 1) / 2);
|
|
40
|
+
}
|
|
48
41
|
}
|
|
42
|
+
|
|
43
|
+
return -1;
|
|
49
44
|
};
|