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 = 100000}) {
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.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
- verticalOhlcv,
5
- instances,
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;
@@ -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
+ };