ohlcv-indicators 3.2.7 → 3.2.9

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
@@ -431,7 +431,7 @@ export default class OHLCV_INDICATORS {
431
431
  throw new Error('"size" must be a positive number greater than 0 in candleVectors.');
432
432
  }
433
433
 
434
- const { stdDev = 1, lag = 0, scale = 0.05, patternSize = 1, autoMinMax = false } = options;
434
+ const { stdDev = 1, lag = 0, scale = 0.001, patternSize = 0, autoMinMax = false } = options;
435
435
 
436
436
 
437
437
  if (typeof stdDev !== 'number' || stdDev <= 0) {
@@ -443,9 +443,9 @@ export default class OHLCV_INDICATORS {
443
443
  throw new Error(`"scale" value in candleVectors must be any of the following numbers: ${validMagnitudeValues.join(', ')}`);
444
444
  }
445
445
 
446
- if (typeof patternSize !== 'number' || !Number.isInteger(patternSize) || patternSize < 1 ) {
446
+ if (typeof patternSize !== 'number' || !Number.isInteger(patternSize) || patternSize < 0 ) {
447
447
 
448
- throw new Error(`"patternSize" value in candleVectors must be an integer greater than 0.`);
448
+ throw new Error(`"patternSize" value in candleVectors must be a positive integer.`);
449
449
  }
450
450
  if (typeof autoMinMax !== 'boolean') {
451
451
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohlcv-indicators",
3
- "version": "3.2.7",
3
+ "version": "3.2.9",
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,6 +1,6 @@
1
1
 
2
2
  import {FasterEMA, FasterSMA, FasterBollingerBands} from 'trading-signals';
3
- import { classifyBoll } from '../utilities/classification.js'
3
+ import { classifyBoll, calcZScore } from '../utilities/classification.js'
4
4
 
5
5
  const indicatorClasses = {ema: FasterEMA, sma: FasterSMA}
6
6
 
@@ -26,7 +26,8 @@ export const movingAverages = (main, index, indicatorName, size, { target, diff,
26
26
 
27
27
  // Create the main moving average instance.
28
28
  instances[keyName] = {
29
- maInstance: new indicatorClasses[indicatorName](size)
29
+ maInstance: new indicatorClasses[indicatorName](size),
30
+ arrayChunk: {[diffKeyName]: []}
30
31
  };
31
32
 
32
33
  verticalOhlcv[keyName] = [...nullArray];
@@ -63,7 +64,7 @@ export const movingAverages = (main, index, indicatorName, size, { target, diff,
63
64
 
64
65
  // Retrieve the current price value.
65
66
  const value = verticalOhlcv[target][index];
66
- const { maInstance, diffInstance } = instances[keyName];
67
+ const { maInstance, diffInstance, arrayChunk } = instances[keyName];
67
68
 
68
69
  // Update the moving average instance.
69
70
  maInstance.update(value, lastIndexReplace);
@@ -82,6 +83,7 @@ export const movingAverages = (main, index, indicatorName, size, { target, diff,
82
83
  for (const targetKey of diff.targets) {
83
84
  // Compute diffValue only if we have a valid MA value.
84
85
  let diffValue = null;
86
+ let zScore = null
85
87
  if (currMa !== null && typeof currMa === 'number') {
86
88
  diffValue = verticalOhlcv[targetKey][index] - currMa;
87
89
  }
@@ -89,6 +91,8 @@ export const movingAverages = (main, index, indicatorName, size, { target, diff,
89
91
  // Update the diff indicator only if diffValue is a valid number.
90
92
  if (diffValue !== null && typeof diffValue === 'number') {
91
93
  diffInstance.update(Math.abs(diffValue), lastIndexReplace);
94
+
95
+ zScore = calcZScore(arrayChunk, diffKeyName, diff.size, diffValue, lastIndexReplace)
92
96
  }
93
97
 
94
98
  let diffBoll = null;
@@ -102,7 +106,7 @@ export const movingAverages = (main, index, indicatorName, size, { target, diff,
102
106
  main.pushToMain({
103
107
  index,
104
108
  key: `${diffKeyName}_${targetKey}`,
105
- value: classified
109
+ value: zScore
106
110
  });
107
111
  }
108
112
  }
@@ -1,16 +1,10 @@
1
- import { FasterBollingerBands } from 'trading-signals'
2
- import { classifyBoll } from '../utilities/classification.js'
1
+ const diff = (a, b) => (a - b)
3
2
 
4
- const diff = (a, b) => (a - b) / b
3
+ import { calcZScore } from "../utilities/classification.js"
5
4
 
6
- // crear una nueva instancia con la altura porcentual utilizando Bollinger Bands con una desviación estándar de 1.5
7
- // Las diferencias estarán basadas en (objetivo - lower) / (upper - lower). Esto arrojará un valor entre -1 y 1
8
-
9
-
10
- export const candleVectors = (main, index, size, {stdDev, patternSize, lag, scale, autoMinMax}) => {
5
+ export const candleVectors = (main, index, size, {patternSize, lag, autoMinMax}) => {
11
6
 
12
7
  const { verticalOhlcv, instances, lastIndexReplace } = main
13
- const calcSize = (di, bo) => classifyBoll(di, bo, scale, autoMinMax)
14
8
 
15
9
  if(index === 0)
16
10
  {
@@ -74,7 +68,7 @@ export const candleVectors = (main, index, size, {stdDev, patternSize, lag, scal
74
68
  bodyVectors,
75
69
  lookBackVectors,
76
70
  keyNames,
77
- bodyInstance: new FasterBollingerBands(size, stdDev),
71
+ arrayChunk: {...Object.fromEntries(keyNames.map(v => [v, []]))}
78
72
  }
79
73
  })
80
74
 
@@ -85,33 +79,19 @@ export const candleVectors = (main, index, size, {stdDev, patternSize, lag, scal
85
79
 
86
80
  }
87
81
 
88
- if (index === 0) return true
89
-
90
-
91
- const {bodyVectors, lookBackVectors, bodyInstance} = instances.candleVectors
92
-
93
- let bodyBoll = null
94
- const currOpen = verticalOhlcv.open[index]
95
- const currClose = verticalOhlcv.close[index]
96
- const bodySize = diff(currClose, currOpen)
97
-
98
- // Update instances with current absolute values
99
- bodyInstance.update(Math.abs(bodySize), lastIndexReplace)
100
-
101
- try {
102
- bodyBoll = bodyInstance.getResult()
103
- } catch (err) {
104
- // If there's not enough data, means remain null
105
- }
106
-
82
+ const {bodyVectors, lookBackVectors, arrayChunk} = instances.candleVectors
107
83
 
108
84
  for(let x = 0; x < bodyVectors.length; x++)
109
85
  {
110
86
  const [k2, k1] = bodyVectors[x]
111
87
  const v2 = verticalOhlcv[k2][index]
112
88
  const v1 = verticalOhlcv[k1][index]
89
+ const key = `candle_body_${k2}_${k1}`
90
+ const difference = diff(v2, v1)
113
91
 
114
- main.pushToMain({index, key: `candle_body_${k2}_${k1}`, value: calcSize(diff(v2, v1), bodyBoll)})
92
+ const zScore = calcZScore(arrayChunk, key, size, difference, lastIndexReplace)
93
+
94
+ main.pushToMain({index, key, value: zScore})
115
95
  }
116
96
 
117
97
  for(let x = 0; x < patternSize; x++)
@@ -120,12 +100,18 @@ export const candleVectors = (main, index, size, {stdDev, patternSize, lag, scal
120
100
  {
121
101
  const currV = verticalOhlcv[currK][index]
122
102
  const prevV = verticalOhlcv[prevK][index-(x+1)]
103
+ const key = `candle_change_${x+1}_${currK}_${prevK}`
104
+
105
+ if(typeof prevV === 'undefined')
106
+ {
107
+ main.pushToMain({index, key, value: null})
108
+ continue
109
+ }
123
110
 
124
- main.pushToMain({
125
- index,
126
- key: `candle_change_${x+1}_${currK}_${prevK}`,
127
- value: (typeof prevV === 'undefined') ? null : calcSize(diff(currV, prevV), bodyBoll)
128
- })
111
+ const difference = diff(currV, prevV)
112
+ const zScore = calcZScore(arrayChunk, key, size, difference, lastIndexReplace)
113
+
114
+ main.pushToMain({index, key, value: zScore})
129
115
  }
130
116
  }
131
117
 
@@ -47,3 +47,31 @@ export const classifyBoll = (value, bollingerBands, scale = 0.05, autoMinMax = f
47
47
  }
48
48
 
49
49
  }
50
+
51
+
52
+ export const calcZScore = (arrayChunk, key, size, difference, lastIndexReplace) => {
53
+
54
+ if(lastIndexReplace)
55
+ {
56
+ arrayChunk[key][arrayChunk[key].length - 1] = difference
57
+ }
58
+ else
59
+ {
60
+ arrayChunk[key].push(difference)
61
+ }
62
+
63
+
64
+ if (arrayChunk[key].length > size) {
65
+ arrayChunk[key].shift(); // Removes the first element to maintain array size
66
+ }
67
+
68
+ if(arrayChunk.length < size) return null
69
+
70
+ const mean = arrayChunk[key].reduce((sum, value) => sum + value, 0) / size
71
+
72
+ const stdDev = Math.sqrt(
73
+ arrayChunk[key].reduce((sum, value) => sum + (value - mean) ** 2, 0) / size
74
+ )
75
+
76
+ return (difference - mean) / stdDev
77
+ }
@@ -30,7 +30,7 @@ export const pushToMain = ({main, index, key, value}) => {
30
30
  }
31
31
  else if(key.startsWith('candle_') && keyInAutoMinMax)
32
32
  {
33
- minMaxRanges[key] = { min: -1, max: 1}
33
+ minMaxRanges[key] = { min: -3, max: 3}
34
34
  }
35
35
  else if(key.includes('_range_') && keyInAutoMinMax)
36
36
  {