ohlcv-indicators 3.5.55 → 3.5.59

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.
@@ -4,12 +4,6 @@ export const oneHotEncode = (idx, size) => {
4
4
  return vec
5
5
  }
6
6
 
7
- export const logMlTraining = ({featureCols, flatFeaturesColLen, type, trainingSize}) => {
8
-
9
- const oneHotTxt = (featureCols.length !== flatFeaturesColLen) ? ' (including flat one-hot encoded array values) ' : ''
10
- console.log(`---\nInitialized "${type}" with ${flatFeaturesColLen} features ${oneHotTxt} and ${trainingSize} rows: \n${JSON.stringify(featureCols)}\n\n`)
11
- }
12
-
13
7
  export const normalizeMinMax = (value, min, max, [validMin, validMax]) => {
14
8
  const clamped = Math.min(Math.max(value, min), max)
15
9
  return ((clamped - min) / (max - min)) * (validMax - validMin) + validMin
@@ -17,114 +11,4 @@ export const normalizeMinMax = (value, min, max, [validMin, validMax]) => {
17
11
 
18
12
  export const normalizeZScore = (value, mean, std) => {
19
13
  return std === 0 ? 0 : (value - mean) / std
20
- }
21
-
22
- export const findGroupsFunc = (findGroups, scaledGroups) => {
23
-
24
- const output = []
25
-
26
- if(findGroups.length > 0)
27
- {
28
- for(let g = 0; g < findGroups.length; g++)
29
- {
30
- const group = findGroups[g]
31
- const {type, size = null, groupName = null} = group
32
-
33
- let groupKey = (size !== null) ? `${type}_${size}` : `${type}_${groupName}`
34
-
35
- if(!scaledGroups.hasOwnProperty(groupKey)) throw new Error(`Scaled group (${groupKey}) not found for regressor.options.findGroups[${g}]: ${JSON.stringify(group)}`)
36
- output.push(...scaledGroups[groupKey])
37
- }
38
- }
39
-
40
- return output
41
- }
42
-
43
- export const computeFlatFeaturesLen = (featureCols, verticalOhlcv, index) => {
44
-
45
- let flatFeaturesColLen = 0
46
-
47
- for (const key of featureCols) {
48
-
49
- if(!verticalOhlcv.hasOwnProperty(key)) throw new Error(`Property "${key}" not found in "verticalOhlcv".`)
50
-
51
- const val = verticalOhlcv[key][index]
52
-
53
- if(typeof val === 'undefined' || val === null || Number.isNaN(val)) throw new Error(`Invalid value of property "${key}".`)
54
-
55
- if (key.startsWith('one_hot_') || key.startsWith('pca_')) {
56
-
57
- const colSize = verticalOhlcv[key][index].length
58
-
59
- flatFeaturesColLen += colSize
60
-
61
- } else {
62
-
63
- flatFeaturesColLen += 1
64
-
65
- }
66
- }
67
-
68
- return flatFeaturesColLen
69
- }
70
-
71
-
72
- export const getFeaturedKeys = ({trainingCols, findGroups, verticalOhlcv, scaledGroups}) => {
73
-
74
- const featureCols = [...trainingCols, ...(findGroupsFunc(findGroups, scaledGroups))]
75
-
76
-
77
- if (featureCols.length === 0) {
78
- return []
79
- }
80
-
81
- let keyNotFound = false
82
-
83
- // sanity‐check that all features exist
84
- for(let x = 0; x < featureCols.length; x++)
85
- {
86
- const featureKey = featureCols[x]
87
-
88
- if(!verticalOhlcv.hasOwnProperty(featureKey)) {
89
- keyNotFound = true
90
- break
91
- }
92
- }
93
-
94
- if(keyNotFound) return []
95
-
96
- return featureCols
97
- }
98
-
99
- export const updateClassifierMetrics = ({ metrics, trueLabel, predictedLabel }) => {
100
- // Increment overall counters
101
- metrics.total = (metrics.total || 0) + 1
102
- metrics.correct = (metrics.correct || 0)
103
-
104
- // Initialize per‐label stats container if needed
105
- metrics.labels = metrics.labels || {}
106
-
107
- const labelKey = predictedLabel.toString()
108
- // Ensure we have a slot for this label
109
- if (!metrics.labels[labelKey]) {
110
- metrics.labels[labelKey] = { total: 0, correct: 0, accuracy: 0 }
111
- }
112
-
113
- // Update this label’s total predictions
114
- metrics.labels[labelKey].total++
115
-
116
- // If correct, bump both overall and per-label correct counters
117
- if (predictedLabel === trueLabel) {
118
- metrics.correct++
119
- metrics.labels[labelKey].correct++
120
- }
121
-
122
- // Recompute overall accuracy
123
- metrics.accuracy = metrics.correct / metrics.total
124
-
125
- // Recompute accuracy for each label
126
- for (const key in metrics.labels) {
127
- const stats = metrics.labels[key]
128
- stats.accuracy = stats.correct / stats.total
129
- }
130
- }
14
+ }
@@ -1,12 +1,15 @@
1
1
  import { normalizeMinMax, normalizeZScore } from "./ml-utilities.js";
2
-
3
- export const scaler = (main, index, size, colKeys, {type, group, range, lag, precomputed, secondaryLoop}) => {
4
2
 
5
-
3
+ const isBadNumber = (v) => v == null || !Number.isFinite(v)
4
+
5
+ //rowWiseScaler
6
+
7
+ export const scaler = (main, index, size, colKeys, {type, range, lookback, weights, euclideanWeights}) => {
8
+
9
+ //this function performs scaling row by row "row wise scaling"
6
10
 
7
- const {groupKey, groupKeyLen} = precomputed
8
- const { verticalOhlcv, instances, invalidValueIndex } = main;
9
- const prefix = `${type}_${size}`;
11
+ const { verticalOhlcv, instances } = main
12
+ const prefix = `${type}_${size}`
10
13
 
11
14
  if(index === 0) {
12
15
  const { len, isAlreadyComputed } = main
@@ -15,8 +18,6 @@ export const scaler = (main, index, size, colKeys, {type, group, range, lag, pre
15
18
  {
16
19
  throw new Error(`In scaler method can not repeat params "size" and "options.type" together between indicators.`)
17
20
  }
18
-
19
- isAlreadyComputed.add(prefix)
20
21
 
21
22
  if(!instances.hasOwnProperty('scaler')) {
22
23
  instances.scaler = {}
@@ -25,7 +26,7 @@ export const scaler = (main, index, size, colKeys, {type, group, range, lag, pre
25
26
  if(!instances.scaler.hasOwnProperty(prefix))
26
27
  {
27
28
  instances.scaler[prefix] = {
28
- windows: {}
29
+ extectedFeatures: (lookback === 0) ? colKeys.length : colKeys.length + (lookback * colKeys.length)
29
30
  }
30
31
  }
31
32
 
@@ -39,103 +40,104 @@ export const scaler = (main, index, size, colKeys, {type, group, range, lag, pre
39
40
  const key = `${prefix}_${target}`;
40
41
  verticalOhlcv[key] = new Float64Array(len).fill(NaN)
41
42
 
42
- const winKey = group ? groupKey : target;
43
- instances.scaler[prefix].windows[winKey] = [];
44
-
45
- if (!main.scaledGroups[groupKey]) main.scaledGroups[groupKey] = [];
46
- main.scaledGroups[groupKey].push(key);
43
+ if (!main.scaledGroups[prefix]) main.scaledGroups[prefix] = [];
44
+
45
+ main.scaledGroups[prefix].push(key);
47
46
 
48
- if (lag > 0) {
49
- const lags = Array.from({ length: lag }).map((_, i) => `${key}_lag_${i + 1}`)
50
- main.scaledGroups[groupKey].push(...lags)
47
+ if (lookback > 0) {
48
+ const laggedKeys = Array.from({ length: lookback }).map((_, i) => `${key}_lag_${i + 1}`)
49
+
50
+ for(const lKey of laggedKeys) {
51
+ verticalOhlcv[lKey] = new Float64Array(len).fill(NaN)
52
+ }
53
+
54
+ main.scaledGroups[prefix].push(...laggedKeys)
51
55
  features.push(key)
52
56
  }
53
57
  }
54
58
 
55
- if(lag > 0)
56
- {
57
- main.lag(features, lag)
59
+ for(const weKey of Object.keys(weights)) {
60
+ if (!verticalOhlcv.hasOwnProperty(weKey)) {
61
+ throw new Error(`Target property "${weKey}" not found in verticalOhlcv`);
62
+ }
58
63
  }
59
- }
60
64
 
61
- if(secondaryLoop === true && index <= invalidValueIndex) true
65
+ }
62
66
 
63
- const { windows } = instances.scaler[prefix]
67
+ const { extectedFeatures } = instances.scaler[prefix]
64
68
 
65
69
  let hasInvalidVal = false
70
+ const row = {}
71
+ const rowValues = []
72
+ let countFeatures = 0
66
73
 
67
- // update windows with current values
68
74
  for (let x = 0; x < colKeys.length; x++) {
69
75
  const target = colKeys[x]
70
76
  const col = verticalOhlcv[target]
77
+ const currWeight = weights?.[target]?.[0] ?? 1
78
+ const currVal = col[index]
71
79
 
72
- if(typeof col === 'undefined')
73
- {
74
- hasInvalidVal = true
75
- break
76
- }
77
-
78
- const val = col[index]
79
-
80
- if(Number.isNaN(val) || val === null)
80
+ if(isBadNumber(currVal))
81
81
  {
82
82
  hasInvalidVal = true
83
83
  break
84
84
  }
85
85
 
86
- const winKey = group ? groupKey : target
87
- const win = windows[winKey]
88
-
89
- win.push(val)
90
-
91
- if (win.length > (group ? size * groupKeyLen : size)) {
92
- win.shift()
86
+ row[target] = {
87
+ val: currVal,
88
+ weight: (euclideanWeights) ? Math.sqrt(currWeight) : currWeight
93
89
  }
94
90
 
95
- }
91
+ rowValues.push(currVal)
92
+ countFeatures++
96
93
 
97
- if(hasInvalidVal) return
98
-
99
- const ready = index + 1 >= size
94
+ if(lookback > 0) {
95
+ for (let step = 1; step <= lookback; step++) {
100
96
 
101
- if(!ready) return
102
-
103
- // scale values once enough data
104
- for (let x = 0; x < colKeys.length; x++) {
105
- const target = colKeys[x]
106
- const col = verticalOhlcv[target]
97
+ const laggedWeight = weights?.[target]?.[step] ?? 1
98
+ const laggedVal = col[index - step]
107
99
 
108
- if(typeof col === 'undefined')
109
- {
110
- break
111
- }
100
+ if(isBadNumber(laggedVal))
101
+ {
102
+ hasInvalidVal = true
103
+ break
104
+ }
112
105
 
113
- const val = col[index]
106
+ row[`${target}_lag_${step}`] = {
107
+ val: laggedVal,
108
+ weight: (euclideanWeights) ? Math.sqrt(laggedWeight) : laggedWeight
109
+ }
114
110
 
115
- if(Number.isNaN(val) || val === null)
116
- {
117
- break
111
+ rowValues.push(laggedVal)
112
+ countFeatures++
113
+ }
114
+
115
+ if(hasInvalidVal) break
118
116
  }
117
+ }
118
+
119
+ if(hasInvalidVal || countFeatures !== extectedFeatures) return
119
120
 
120
- const key = `${prefix}_${target}`
121
- let scaled = null
122
- const winKey = group ? groupKey : target
123
- const win = windows[winKey]
124
-
125
- if (type === 'minmax') {
126
- const mn = Math.min(...win)
127
- const mx = Math.max(...win)
128
- scaled = normalizeMinMax(val, mn, mx, range)
129
- } else if (type === 'zscore') {
130
- const mean = win.reduce((sum, x) => sum + x, 0) / win.length;
131
- const variance = win.reduce((sum, x) => sum + Math.pow(x - mean, 2), 0) / win.length
132
- const std = Math.sqrt(variance);
133
- scaled = normalizeZScore(val, mean, std)
134
- } else {
135
- throw new Error(`Unknown scaler type "${type}"`)
121
+ if (type === "minmax") {
122
+ const mn = Math.min(...rowValues);
123
+ const mx = Math.max(...rowValues);
124
+
125
+ for (const [key, { val, weight }] of Object.entries(row)) {
126
+ const scaled = normalizeMinMax(val, mn, mx, range) * weight;
127
+ main.pushToMain({ index, key: `${prefix}_${key}`, value: scaled });
128
+ }
129
+ }
130
+
131
+ if (type === "zscore") {
132
+ const n = rowValues.length;
133
+ const mean = rowValues.reduce((s, x) => s + x, 0) / n;
134
+ const variance = rowValues.reduce((s, x) => s + (x - mean) ** 2, 0) / n;
135
+ const std = Math.sqrt(variance);
136
+
137
+ for (const [key, { val, weight }] of Object.entries(row)) {
138
+ const scaled = normalizeZScore(val, mean, std) * weight;
139
+ main.pushToMain({ index, key: `${prefix}_${key}`, value: scaled });
136
140
  }
137
-
138
- main.pushToMain({ index, key, value: scaled})
139
141
  }
140
142
  }
141
143
 
@@ -8,8 +8,6 @@ const indicatorClasses = {
8
8
 
9
9
  export const movingAverages = (main, index, methodName, size, { target, lag }) => {
10
10
 
11
-
12
-
13
11
  const { verticalOhlcv, instances, priceBased } = main
14
12
  const suffix = (target !== 'close') ? `_${target}` : ''
15
13
  const keyName = `${methodName}_${size}${suffix}`
@@ -2,8 +2,6 @@ import { FasterSMA } from 'trading-signals';
2
2
 
3
3
  export const relativeVolume = (main, index, size, {lag}) => {
4
4
 
5
-
6
-
7
5
  const key = `relative_volume_${size}`;
8
6
  const { instances, verticalOhlcv } = main;
9
7
 
@@ -9,11 +9,11 @@ export const vidya = (main, index, size, momentum, options = {}) => {
9
9
  // Initialization on the first bar
10
10
  if (index === 0) {
11
11
  if (!(target in verticalOhlcv)) {
12
- throw new Error(`VIDYA could not find target "${target}"`);
12
+ throw new Error(`VIDYA could not find target "${target}"`)
13
13
  }
14
14
 
15
- const prefix = `vidya_${indicatorKey}`;
16
- const keyBase = target === 'close' ? prefix : `${prefix}_${target}`;
15
+ const prefix = `vidya_${indicatorKey}`
16
+ const keyBase = target === 'close' ? prefix : `${prefix}_${target}`
17
17
  const keys = {
18
18
  vidya: keyBase,
19
19
  upper: `${prefix}_upper`,
@@ -21,7 +21,7 @@ export const vidya = (main, index, size, momentum, options = {}) => {
21
21
  delta_vol: `${prefix}_delta_vol`,
22
22
  cross: `${prefix}_cross`,
23
23
  liquidity: `${prefix}_liquidity`,
24
- };
24
+ }
25
25
 
26
26
  const priceBasedVidyaKeys = [keyBase, keys.upper, keys.lower, keys.liquidity]
27
27
 
@@ -63,13 +63,13 @@ export const vidya = (main, index, size, momentum, options = {}) => {
63
63
  };
64
64
 
65
65
  // Series inputs
66
- const price = verticalOhlcv[target][index];
67
- const high = verticalOhlcv.high[index];
68
- const low = verticalOhlcv.low[index];
69
- const close = verticalOhlcv.close[index];
70
- const open = verticalOhlcv.open[index];
71
- const vol = verticalOhlcv.volume[index];
72
- const prevCross = index > 0 ? verticalOhlcv[keys.cross][index - 1] : 0;
66
+ const price = verticalOhlcv[target][index]
67
+ const high = verticalOhlcv.high[index]
68
+ const low = verticalOhlcv.low[index]
69
+ const close = verticalOhlcv.close[index]
70
+ const open = verticalOhlcv.open[index]
71
+ const vol = verticalOhlcv.volume[index]
72
+ const prevCross = index > 0 ? verticalOhlcv[keys.cross][index - 1] : 0
73
73
 
74
74
  const highestHigh = (inst.liquidity.high.length === liquidityLookback) ? Math.max(...inst.liquidity.high) : NaN
75
75
  const lowestLow = (inst.liquidity.low.length === liquidityLookback) ? Math.min(...inst.liquidity.low) : NaN
@@ -81,77 +81,77 @@ export const vidya = (main, index, size, momentum, options = {}) => {
81
81
  high - low,
82
82
  Math.abs(high - prevClose),
83
83
  Math.abs(low - prevClose)
84
- );
85
- inst.atrBuffer.push(tr);
86
- if (inst.atrBuffer.length > atrLength) inst.atrBuffer.shift();
84
+ )
85
+ inst.atrBuffer.push(tr)
86
+ if (inst.atrBuffer.length > atrLength) inst.atrBuffer.shift()
87
87
  }
88
88
  const atr = inst.atrBuffer.length === atrLength
89
89
  ? inst.atrBuffer.reduce((a, b) => a + b, 0) / atrLength
90
- : NaN;
90
+ : NaN
91
91
 
92
92
  // Compute raw VIDYA
93
- let rawVidya = NaN;
94
- let mom = NaN;
95
- if (index > 0) mom = price - verticalOhlcv[target][index - 1];
96
- inst.momentumBuffer.push(mom);
97
- if (inst.momentumBuffer.length > momentum) inst.momentumBuffer.shift();
93
+ let rawVidya = NaN
94
+ let mom = NaN
95
+ if (index > 0) mom = price - verticalOhlcv[target][index - 1]
96
+ inst.momentumBuffer.push(mom)
97
+ if (inst.momentumBuffer.length > momentum) inst.momentumBuffer.shift()
98
98
  if (inst.momentumBuffer.length === momentum) {
99
- let sumPos = 0, sumNeg = 0;
99
+ let sumPos = 0, sumNeg = 0
100
100
  inst.momentumBuffer.forEach(m => m >= 0 ? sumPos += m : sumNeg += -m);
101
- const denom = sumPos + sumNeg;
101
+ const denom = sumPos + sumNeg
102
102
  const cmo = denom === 0 ? 0 : Math.abs((sumPos - sumNeg) / denom) * 100;
103
- const alpha = 2 / (size + 1);
104
- const a = alpha * (cmo / 100);
103
+ const alpha = 2 / (size + 1)
104
+ const a = alpha * (cmo / 100)
105
105
  rawVidya = isNaN(inst.prevVidya) ? price : (a * price + (1 - a) * inst.prevVidya);
106
- inst.prevVidya = rawVidya;
106
+ inst.prevVidya = rawVidya
107
107
  }
108
108
 
109
109
  // Smooth VIDYA using fixed 15-bar SMA
110
- inst.sma.update(rawVidya);
111
- let smoothedVidya = NaN;
112
- try { smoothedVidya = inst.sma.getResult(); } catch {}
110
+ inst.sma.update(rawVidya)
111
+ let smoothedVidya = NaN
112
+ try { smoothedVidya = inst.sma.getResult() } catch {}
113
113
 
114
114
  // Bands
115
115
  const upper = (!isNaN(atr) && !isNaN(smoothedVidya))
116
116
  ? smoothedVidya + atr * bandDistance
117
- : NaN;
117
+ : NaN
118
118
  const lower = (!isNaN(atr) && !isNaN(smoothedVidya))
119
119
  ? smoothedVidya - atr * bandDistance
120
- : NaN;
120
+ : NaN
121
121
 
122
122
  // Detect crosses
123
- const prevPrice = index > 0 ? verticalOhlcv[target][index - 1] : NaN;
124
- const prevUpper = index > 0 ? verticalOhlcv[keys.upper][index - 1] : NaN;
125
- const prevLower = index > 0 ? verticalOhlcv[keys.lower][index - 1] : NaN;
126
- const crossUp = index > 0 && prevPrice <= prevUpper && price > upper;
127
- const crossDown = index > 0 && prevPrice >= prevLower && price < lower;
123
+ const prevPrice = index > 0 ? verticalOhlcv[target][index - 1] : NaN
124
+ const prevUpper = index > 0 ? verticalOhlcv[keys.upper][index - 1] : NaN
125
+ const prevLower = index > 0 ? verticalOhlcv[keys.lower][index - 1] : NaN
126
+ const crossUp = index > 0 && prevPrice <= prevUpper && price > upper
127
+ const crossDown = index > 0 && prevPrice >= prevLower && price < lower
128
128
 
129
129
  // Update trend state
130
- if (crossUp) inst.isTrendUp = true;
131
- if (crossDown) inst.isTrendUp = false;
130
+ if (crossUp) inst.isTrendUp = true
131
+ if (crossDown) inst.isTrendUp = false
132
132
 
133
133
  // Cumulative cross counter: positive when uptrend, negative when downtrend
134
134
  let cross = 0;
135
135
  if (index > 0) {
136
136
  if (inst.isTrendUp) {
137
- cross = prevCross > 0 ? prevCross + 1 : 1;
137
+ cross = prevCross > 0 ? prevCross + 1 : 1
138
138
  } else {
139
- cross = prevCross < 0 ? prevCross - 1 : -1;
139
+ cross = prevCross < 0 ? prevCross - 1 : -1
140
140
  }
141
141
  }
142
142
 
143
143
  // Volume accumulation
144
144
  if (crossUp || crossDown) {
145
- inst.upVol = inst.downVol = 0;
145
+ inst.upVol = inst.downVol = 0
146
146
  } else {
147
- inst.upVol += (close > open ? vol : 0);
148
- inst.downVol += (close < open ? vol : 0);
147
+ inst.upVol += (close > open ? vol : 0)
148
+ inst.downVol += (close < open ? vol : 0)
149
149
  }
150
- const avgVol = (inst.upVol + inst.downVol) / 2 || 1;
151
- const deltaPct = (inst.upVol - inst.downVol) / avgVol;
150
+ const avgVol = (inst.upVol + inst.downVol) / 2 || 1
151
+ const deltaPct = (inst.upVol - inst.downVol) / avgVol
152
152
 
153
153
  // Trend-based boundary (reset on crossover)
154
- const trendValue = (inst.isTrendUp) ? lower : upper;
154
+ const trendValue = (inst.isTrendUp) ? lower : upper
155
155
  let liquidity = NaN
156
156
 
157
157
  if(cross > 0)
@@ -164,12 +164,12 @@ export const vidya = (main, index, size, momentum, options = {}) => {
164
164
  }
165
165
 
166
166
  // Push outputs
167
- main.pushToMain({ index, key: keys.vidya, value: trendValue });
168
- main.pushToMain({ index, key: keys.upper, value: upper });
169
- main.pushToMain({ index, key: keys.lower, value: lower });
170
- main.pushToMain({ index, key: keys.delta_vol, value: deltaPct });
171
- main.pushToMain({ index, key: keys.cross, value: cross });
172
- main.pushToMain({ index, key: keys.liquidity, value: liquidity });
167
+ main.pushToMain({ index, key: keys.vidya, value: trendValue })
168
+ main.pushToMain({ index, key: keys.upper, value: upper })
169
+ main.pushToMain({ index, key: keys.lower, value: lower })
170
+ main.pushToMain({ index, key: keys.delta_vol, value: deltaPct })
171
+ main.pushToMain({ index, key: keys.cross, value: cross })
172
+ main.pushToMain({ index, key: keys.liquidity, value: liquidity })
173
173
 
174
174
  inst.liquidity.high.push(high)
175
175
  inst.liquidity.low.push(low)
@@ -177,5 +177,5 @@ export const vidya = (main, index, size, momentum, options = {}) => {
177
177
  if(inst.liquidity.high.length > liquidityLookback) inst.liquidity.high.shift()
178
178
  if(inst.liquidity.low.length > liquidityLookback) inst.liquidity.low.shift()
179
179
 
180
- return true;
181
- };
180
+ return true
181
+ }
@@ -12,17 +12,12 @@ export const dateTime = (main, index, {lag, oneHot, precompute}) => {
12
12
  const {len, dateType} = main
13
13
  if(!dateType) throw Error('dateTime method found and invalid "date" in input ohlcv')
14
14
 
15
- const startYear = verticalOhlcv.date[0].getUTCFullYear()
16
- const currentYear = new Date().getUTCFullYear()
17
-
18
15
  Object.assign(instances, {
19
16
  dateTime: {
20
17
  colKeys: [...precompute.colKeys, `${prefix}year`],
21
18
  colKeySizes: {
22
- ...precompute.colKeySizes,
23
- [`${prefix}year`]: (currentYear - startYear) + 1
19
+ ...precompute.colKeySizes
24
20
  }
25
- ,startYear
26
21
  }
27
22
  })
28
23
 
@@ -45,11 +40,11 @@ export const dateTime = (main, index, {lag, oneHot, precompute}) => {
45
40
  }
46
41
  }
47
42
 
48
- const {colKeySizes, startYear} = instances.dateTime
43
+ const {colKeySizes} = instances.dateTime
49
44
 
50
45
  const currDate = verticalOhlcv.date[index]
51
46
 
52
- const dateInfo = getDateInfo(currDate, oneHot, colKeySizes, prefix, startYear)
47
+ const dateInfo = getDateInfo(currDate, oneHot, colKeySizes)
53
48
 
54
49
  for(const [key, value] of Object.entries(dateInfo))
55
50
  {
@@ -59,25 +54,34 @@ export const dateTime = (main, index, {lag, oneHot, precompute}) => {
59
54
 
60
55
 
61
56
 
62
- const getDateInfo = (date, oneHot, colKeySizes, prefix, startYear) => {
57
+ const getDateInfo = (date, oneHot, colKeySizes) => {
63
58
 
64
- const encode = (value, size) => (oneHot) ? oneHotEncode(value, size) : value
65
59
 
66
- const output = {
67
- [`${prefix}year`]: date.getUTCFullYear(),
68
- [`${prefix}month`]: date.getUTCMonth(),
69
- [`${prefix}hour`]: date.getUTCHours(),
70
- [`${prefix}minute`]: date.getUTCMinutes(),
71
- [`${prefix}day_of_the_week`]: date.getUTCDay(),
72
- [`${prefix}day_of_the_month`]: date.getUTCDate() - 1,
73
- }
60
+ const year = date.getFullYear();
74
61
 
75
- for(const [key, size] of Object.entries(colKeySizes))
76
- {
77
- const value = (key === `${prefix}year`) ? output[key] - startYear: output[key]
78
- output[key] = encode(value, size)
79
- }
62
+ //start with 0 values
63
+ const month = date.getMonth();
64
+ const hour = date.getHours();
65
+ const minute = date.getMinutes();
66
+ const dayOfWeek = date.getDay();
67
+ const dayOfMonth = date.getDate() - 1; // keep same offset
80
68
 
81
- return output
82
- }
69
+ if (!oneHot) {
70
+ return {
71
+ year: year,
72
+ month: month + 1, //iso month
73
+ hour: hour,
74
+ minute: minute,
75
+ day_of_the_week: ((dayOfWeek + 6) % 7) + 1, //iso date of the week
76
+ day_of_the_month: dayOfMonth + 1, //iso date of the month
77
+ };
78
+ }
83
79
 
80
+ return {
81
+ one_hot_month: oneHotEncode(month, colKeySizes.one_hot_month),
82
+ one_hot_hour: oneHotEncode(hour, colKeySizes.one_hot_hour),
83
+ one_hot_minute: oneHotEncode(minute, colKeySizes.one_hot_minute),
84
+ one_hot_day_of_the_week: oneHotEncode(dayOfWeek, colKeySizes.one_hot_day_of_the_week),
85
+ one_hot_day_of_the_month: oneHotEncode(dayOfMonth, colKeySizes.one_hot_day_of_the_month),
86
+ };
87
+ };