ohlcv-indicators 3.4.4 → 3.4.6
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
|
@@ -30,7 +30,7 @@ import { precomputeMovingAverages } from './src/moving-averages/movingAverages.j
|
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
export default class OHLCV_INDICATORS {
|
|
33
|
-
constructor({input, ticker = null, precision = true, inputParams = null, chunkProcess =
|
|
33
|
+
constructor({input, ticker = null, precision = true, inputParams = null, chunkProcess = 2000}) {
|
|
34
34
|
|
|
35
35
|
validateArray(input, 'input', (ticker !== null) ? `contructor ${ticker}` : 'constuctor')
|
|
36
36
|
if(input.length === 0) throw Error('input OHLCV must not be empty: ' + ticker)
|
|
@@ -302,14 +302,15 @@ export default class OHLCV_INDICATORS {
|
|
|
302
302
|
validateNumber(stdDev, {min: 0.01, max: 50, allowDecimals: true}, 'stdDev', methodName)
|
|
303
303
|
validateObject(options, 'options', methodName)
|
|
304
304
|
|
|
305
|
-
const {target = 'close', height = false, range = [], lag = 0} = options
|
|
305
|
+
const {target = 'close', height = false, range = [], lag = 0, decimals = null} = options
|
|
306
306
|
|
|
307
307
|
|
|
308
308
|
validateArray(range, 'options.range', methodName)
|
|
309
309
|
validateNumber(lag, {min: 0, max: this.len, allowDecimals: false}, 'options.lag', methodName)
|
|
310
310
|
validateBoolean(height, 'options.height', methodName)
|
|
311
|
+
if(decimals !== null) validateNumber(decimals, {min: 1, max: 15, allowDecimals: false}, 'decimals', methodName)
|
|
311
312
|
|
|
312
|
-
this.inputParams.push({key: methodName, params: [size, stdDev, {target, height, range, lag}]});
|
|
313
|
+
this.inputParams.push({key: methodName, params: [size, stdDev, {target, height, range, lag, decimals}]});
|
|
313
314
|
|
|
314
315
|
return this;
|
|
315
316
|
}
|
|
@@ -342,13 +343,14 @@ export default class OHLCV_INDICATORS {
|
|
|
342
343
|
validateNumber(offset, {min: 0, max: this.len, allowDecimals: false}, 'offset', methodName)
|
|
343
344
|
|
|
344
345
|
validateObject(options, 'options', methodName)
|
|
345
|
-
const { height = false, range = [], lag = 0} = options;
|
|
346
|
+
const { height = false, range = [], lag = 0, decimals = null} = options;
|
|
346
347
|
|
|
347
348
|
validateArray(range, 'options.range', methodName)
|
|
348
349
|
validateNumber(lag, {min: 0, max: this.len, allowDecimals: false}, 'options.lag', methodName)
|
|
349
350
|
validateBoolean(height, 'options.height', methodName)
|
|
351
|
+
if(decimals !== null) validateNumber(decimals, {min: 1, max: 15, allowDecimals: false}, 'decimals', methodName)
|
|
350
352
|
|
|
351
|
-
this.inputParams.push({ key: methodName, params: [size, offset, { height, range, lag }] });
|
|
353
|
+
this.inputParams.push({ key: methodName, params: [size, offset, { height, range, lag, decimals}] });
|
|
352
354
|
|
|
353
355
|
return this;
|
|
354
356
|
}
|
|
@@ -401,17 +403,19 @@ export default class OHLCV_INDICATORS {
|
|
|
401
403
|
validateNumber(size, {min: 1, max: this.len, allowDecimals: false}, 'size', methodName)
|
|
402
404
|
validateArray(colKeys, 'colKeys', methodName)
|
|
403
405
|
|
|
404
|
-
const {group = false, range = [0, 1], lag = 0, type = 'minmax'} = options
|
|
406
|
+
const {group = false, range = [0, 1], lag = 0, type = 'minmax', decimals = null} = options
|
|
405
407
|
|
|
406
408
|
validateBoolean(group, 'options.group', methodName)
|
|
407
409
|
validateArrayOfRanges(range, 'options.range', methodName)
|
|
408
410
|
validateArrayOptions(['minmax', 'zscore'], type, 'options.type', methodName)
|
|
409
411
|
|
|
412
|
+
if(decimals !== null) validateNumber(decimals, {min: 1, max: 15, allowDecimals: false}, 'decimals', methodName)
|
|
413
|
+
|
|
410
414
|
const groupKey = (group) ? `${type}_${size}_group_${colKeys.join('_')}` : ''
|
|
411
415
|
const groupKeyLen = colKeys.length
|
|
412
416
|
const precomputed = {groupKey, groupKeyLen}
|
|
413
417
|
|
|
414
|
-
this.inputParams.push({key: methodName, params: [size, colKeys, {type, group, range, lag, precomputed}]})
|
|
418
|
+
this.inputParams.push({key: methodName, params: [size, colKeys, {type, group, range, lag, precomputed, decimals}]})
|
|
415
419
|
return this
|
|
416
420
|
}
|
|
417
421
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ohlcv-indicators",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.6",
|
|
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",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { FasterBollingerBands } from 'trading-signals'
|
|
2
|
+
import { roundDecimalPlaces } from '../utilities/numberUtilities.js';
|
|
2
3
|
|
|
3
4
|
const defaultTarget = 'close'
|
|
4
5
|
|
|
5
|
-
export const bollingerBands = (main, index, size, stdDev, { height, range = [], target, lag }) => {
|
|
6
|
+
export const bollingerBands = (main, index, size, stdDev, { height, range = [], target, lag, decimals }) => {
|
|
6
7
|
const { verticalOhlcv, instances } = main;
|
|
7
8
|
const suffix = target === defaultTarget ? '' : `_${target}`;
|
|
8
9
|
const indicatorKey = `${size}_${stdDev}${suffix}`;
|
|
@@ -111,7 +112,7 @@ export const bollingerBands = (main, index, size, stdDev, { height, range = [],
|
|
|
111
112
|
if (!Number.isNaN(lower) && !Number.isNaN(upper)) {
|
|
112
113
|
heightValue = ((upper - lower) / lower)
|
|
113
114
|
}
|
|
114
|
-
main.pushToMain({ index, key: `${subPrefix}_height`, value: heightValue });
|
|
115
|
+
main.pushToMain({ index, key: `${subPrefix}_height`, value: (decimals === null) ? heightValue : roundDecimalPlaces(heightValue, decimals) });
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
// Process each range property.
|
|
@@ -121,7 +122,7 @@ export const bollingerBands = (main, index, size, stdDev, { height, range = [],
|
|
|
121
122
|
if (!Number.isNaN(priceValue) && !Number.isNaN(lower) && !Number.isNaN(upper)) {
|
|
122
123
|
rangeValue = (priceValue - lower) / (upper - lower)
|
|
123
124
|
}
|
|
124
|
-
main.pushToMain({ index, key: `${subPrefix}_range_${rangeKey}`, value: rangeValue });
|
|
125
|
+
main.pushToMain({ index, key: `${subPrefix}_range_${rangeKey}`, value: (decimals === null) ? rangeValue : roundDecimalPlaces(rangeValue, decimals) });
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
return true;
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
|
|
2
|
+
import { roundDecimalPlaces } from "../utilities/numberUtilities.js";
|
|
3
|
+
|
|
2
4
|
export const donchianChannels = (main, index, size, offset, options) => {
|
|
3
|
-
const {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
len,
|
|
7
|
-
inputParams,
|
|
8
|
-
priceBased,
|
|
9
|
-
arrayTypes,
|
|
10
|
-
lag,
|
|
11
|
-
} = main;
|
|
12
|
-
const { height: includeHeight, range: rangeKeys } = options;
|
|
13
|
-
const indicatorKey = `${size}_${offset}`;
|
|
5
|
+
const {verticalOhlcv, instances, len, inputParams, priceBased, arrayTypes, lag} = main
|
|
6
|
+
const { height: includeHeight, range: rangeKeys, decimals } = options
|
|
7
|
+
const indicatorKey = `${size}_${offset}`
|
|
14
8
|
|
|
15
9
|
// ---- INIT (only at first bar) ----
|
|
16
10
|
if (index === 0) {
|
|
@@ -103,7 +97,7 @@ export const donchianChannels = (main, index, size, offset, options) => {
|
|
|
103
97
|
const heightVal = hasBounds && lower
|
|
104
98
|
? (upper - lower) / lower
|
|
105
99
|
: NaN;
|
|
106
|
-
main.pushToMain({ index, key: `${prefix}_height`, value: heightVal });
|
|
100
|
+
main.pushToMain({ index, key: `${prefix}_height`, value: (decimals === null) ? heightVal : roundDecimalPlaces(heightVal, decimals) });
|
|
107
101
|
}
|
|
108
102
|
|
|
109
103
|
// precompute spread once
|
|
@@ -118,7 +112,7 @@ export const donchianChannels = (main, index, size, offset, options) => {
|
|
|
118
112
|
const val = hasBounds && price === price && spread
|
|
119
113
|
? (price - lower) / spread
|
|
120
114
|
: NaN;
|
|
121
|
-
main.pushToMain({ index, key: rangeOut[i], value: val });
|
|
115
|
+
main.pushToMain({ index, key: rangeOut[i], value: (decimals === null) ? val : roundDecimalPlaces(val, decimals) });
|
|
122
116
|
}
|
|
123
117
|
|
|
124
118
|
return true;
|
package/src/studies/scaler.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { roundDecimalPlaces } from "../utilities/numberUtilities.js";
|
|
2
|
+
|
|
1
3
|
/* General scaler: supports "minmax" and "zscore" types */
|
|
2
4
|
|
|
5
|
+
|
|
6
|
+
|
|
3
7
|
const normalizeMinMax = (value, min, max, [validMin, validMax]) => {
|
|
4
8
|
const clamped = Math.min(Math.max(value, min), max);
|
|
5
9
|
return ((clamped - min) / (max - min)) * (validMax - validMin) + validMin;
|
|
@@ -9,7 +13,7 @@ const normalizeMinMax = (value, min, max, [validMin, validMax]) => {
|
|
|
9
13
|
return std === 0 ? 0 : (value - mean) / std;
|
|
10
14
|
};
|
|
11
15
|
|
|
12
|
-
export const scaler = (main, index, size, colKeys, {type, group, range, lag, precomputed}) => {
|
|
16
|
+
export const scaler = (main, index, size, colKeys, {type, group, range, lag, precomputed, decimals}) => {
|
|
13
17
|
const {groupKey, groupKeyLen} = precomputed
|
|
14
18
|
const { verticalOhlcv, instances, arrayTypes } = main;
|
|
15
19
|
const prefix = `${type}_${size}`;
|
|
@@ -93,7 +97,7 @@ export const scaler = (main, index, size, colKeys, {type, group, range, lag, pre
|
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
main.pushToMain({ index, key, value: scaled })
|
|
100
|
+
main.pushToMain({ index, key, value: (decimals === null) ? scaled : roundDecimalPlaces(scaled, decimals)})
|
|
97
101
|
}
|
|
98
102
|
};
|
|
99
103
|
|
|
@@ -68,3 +68,11 @@ export const classifyNum = (num, throwError = false) => {
|
|
|
68
68
|
|
|
69
69
|
return typeof num
|
|
70
70
|
};
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
export const roundDecimalPlaces = (value, decimals) => {
|
|
74
|
+
|
|
75
|
+
const factor = 10 ** decimals
|
|
76
|
+
// add a tiny epsilon to mitigate floating-point quirks around .5
|
|
77
|
+
return Math.round((value + Number.EPSILON) * factor) / factor
|
|
78
|
+
};
|