xy-scale 1.1.2 → 1.1.4

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/README.md CHANGED
@@ -28,7 +28,6 @@ This function prepares a dataset for supervised learning by parsing, scaling, an
28
28
  - `yCallbackFunc` (Function): Custom function to parse Y for each object. Return null or undefined to exclude it from training.
29
29
  - `xCallbackFunc` (Function): Custom function to parse X for each object. Return null or undefined to exclude it from training.
30
30
  - `forceScaling` (String, optional): Forces a specific scaling approach for each feature.
31
- - `timeSteps` (Number, optional): Transforms a one-dimensional array into an array of overlapping sequences (timesteps), each of a specified length. Default is 0 returning original output.
32
31
 
33
32
  #### Features:
34
33
  - **Y and X Parsing**: Custom parsing for Y and X based on user-defined functions.
@@ -57,7 +56,6 @@ Designed for production environments, this function parses and scales feature da
57
56
  - `weights` (Object, optional): Feature weights for scaling.
58
57
  - `xCallbackFunc` (Function): Custom function to parse X for each object. Return null or undefined to exclude it from production.
59
58
  - `forceScaling` (String, optional): Forces a specific scaling approach for each feature.
60
- - `timeSteps` (Number, optional): Transforms a one-dimensional array into an array of overlapping sequences (timesteps), each of a specified length. Default is 0 returning original output.
61
59
 
62
60
  #### Returns:
63
61
  - `X`: Scaled feature array for production data.
@@ -86,12 +84,28 @@ The `descaleArrayObj` function reverses the scaling applied to a dataset, recons
86
84
  - `scaled`: scaled array returned from `parseTrainingXY` (`trainX`, `trainY`, `testX` or `testY`) or `parseProductionX` (`X`).
87
85
  - `config`: config object returned from `parseTrainingXY` (`configX`, `configY`) or `parseProductionX` (`configX`).
88
86
  - `keyNames`: keyNames array returned from `parseTrainingXY` (`keyNamesX`, `keyNamesY`) or `parseProductionX` (`keyNamesX`).
89
- - `timeSteps`: input numeric timeSteps param submited to `parseTrainingXY` or `parseProductionX`. Defaults to 0.
90
87
 
91
88
  #### Returns:
92
89
 
93
90
  The output of this function in an array of objects similar or equal to the input array of objects submited to `parseTrainingXY` or `parseProductionX`.
94
91
 
92
+ ### 4. `arrayToTimesteps`
93
+
94
+ The `arrayToTimesteps` function transforms a flat array into an array of overlapping sequences of a specified length. This is a common preprocessing step for time-series or sequential data models.
95
+
96
+ #### Parameters:
97
+ - `arr` (Array): The input array to be converted into timesteps.
98
+ - `timeSteps` (Number): The number of elements in each timestep sequence.
99
+ - Must be greater than `0`.
100
+ - If `timeSteps === 0`, the function returns the original array unchanged.
101
+
102
+ #### Returns:
103
+ An array of sub-arrays, where each sub-array contains `timeSteps` consecutive elements from the original array.
104
+
105
+ #### Throws:
106
+ - An error if `timeSteps < 0`, with the message: `"timeSteps must be greater than 0"`.
107
+
108
+
95
109
  ---
96
110
 
97
111
  ## Usage Examples
@@ -99,27 +113,32 @@ The output of this function in an array of objects similar or equal to the input
99
113
  1. **Parsing and Splitting a Training Dataset:**
100
114
 
101
115
  ```javascript
102
- import { parseTrainingXY } from './scale.js';
103
-
104
- const myArray = [
105
- { open: 135.23, high: 137.45, low: 134.56, sma_200: 125.34, sma_100: 130.56 },
106
- { open: 136.45, high: 138.67, low: 135.67, sma_200: 126.78, sma_100: 131.45 },
107
- { open: 137.89, high: 139.34, low: 136.34, sma_200: 127.56, sma_100: 132.78 }
108
- ];
116
+ import { parseTrainingXY, arrayToTimesteps } from 'xy-scale';
117
+ import { loadFile } from "./test/fs.js"
118
+ import * as tf from '@tensorflow/tfjs-node';
109
119
 
120
+ // [{open, high, low, close}, {open, high, low, close}]
121
+ const myArray = await loadFile({fileName: '1d-spy.json', pathName: 'datasets'}) //file in /datasets/1d-spy.json
122
+
123
+ //callback function used to prepare X before scaling
110
124
  const xCallbackFunc = ({ objRow, index }) => {
111
- const curr = objRow[index];
112
- const { open, high, low, sma_200, sma_100 } = curr;
125
+ const curr = objRow[index]
126
+ const prev = objRow[index - 1]
113
127
 
114
- return {
115
- open,
116
- high,
117
- low,
118
- sma_200,
119
- sma_100
120
- };
121
- };
128
+ //returning null or undefined will exclude current row X and Y from training
129
+ if(typeof prev === 'undefined') return null
130
+
131
+ const { open, high, low, close } = curr
122
132
 
133
+ return {
134
+ change: open - prev.close,
135
+ top: high - Math.max(open, close),
136
+ bottom: low - Math.min(open, close),
137
+ body: open-close,
138
+ }
139
+ }
140
+
141
+ //callback function used to prepare Y before scaling
123
142
  const yCallbackFunc = ({ objRow, index }) => {
124
143
  const curr = objRow[index];
125
144
  const next = objRow[index + 1];
@@ -128,15 +147,12 @@ The output of this function in an array of objects similar or equal to the input
128
147
  if (typeof next === 'undefined') return null;
129
148
 
130
149
  return {
131
- label_1: next.open > curr.open, // Label indicating if the next open price is higher than the current
132
- label_2: next.high > curr.high, // Label indicating if the next high price is higher than the current
133
- label_3: next.low > curr.low, // Label indicating if the next low price is higher than the current
134
- label_4: next.sma_200 > curr.sma_200, // Label indicating if the next 200-day SMA is higher than the current
135
- label_5: next.sma_100 > curr.sma_100 // Label indicating if the next 100-day SMA is higher than the current
150
+ label_1: next.open > curr.close,
151
+ label_2: next.close > curr.close,
136
152
  };
137
153
  };
138
-
139
- const const {
154
+
155
+ const {
140
156
  trainX,
141
157
  trainY,
142
158
  testX,
@@ -145,89 +161,32 @@ The output of this function in an array of objects similar or equal to the input
145
161
  keyNamesX,
146
162
  } = parseTrainingXY({
147
163
  arrObj: myArray,
148
- trainingSplit: 0.75,
149
- weights: { open: 1, high: 1, low: 1, sma_200: 1, sma_100: 1 },
164
+ trainingSplit: 0.90,
150
165
  yCallbackFunc,
151
166
  xCallbackFunc,
152
167
  forceScaling: 'normalization',
153
- timeSteps: 0
154
168
  });
155
169
 
156
-
157
- ```
158
170
 
171
+ console.log('testX', testX.slice(-2))
159
172
 
160
- 2. **Parsing a Production Dataset:**
161
173
 
162
- ```javascript
163
- import { parseProductionX } from './scale.js'
164
- import {descaleArrayObj} from './descale.js'
174
+ const timeSteps = 10
175
+ const colsX = trainX[0].length
176
+ const colsY = trainY[0].length
177
+ const timeSteppedTrainX = arrayToTimesteps(trainX, timeSteps)
178
+ const trimedTrainY = trainY.slice(timeSteps-1)
165
179
 
166
- const xCallbackFunc = ({ objRow, index }) => {
167
- const curr = objRow[index];
168
- const { open, high, low, sma_200, sma_100 } = curr;
169
180
 
170
- return {
171
- open,
172
- high,
173
- low,
174
- sma_200,
175
- sma_100
176
- };
177
- };
178
-
179
- const myArray = [
180
- { open: 135.23, high: 137.45, low: 134.56, sma_200: 125.34, sma_100: 130.56 },
181
- { open: 136.45, high: 138.67, low: 135.67, sma_200: 126.78, sma_100: 131.45 },
182
- { open: 137.89, high: 139.34, low: 136.34, sma_200: 127.56, sma_100: 132.78 }
183
- ];
184
-
185
- const {X, configX, keyNamesX} = parseProductionX({
186
- arrObj: myArray,
187
- weights: { open: 2, high: 1, low: 1, sma_200: 1, sma_100: 1 },
188
- xCallbackFunc,
189
- forceScaling: null,
190
- timeSteps: 0
191
- });
192
-
193
- console.log('productionData.X', productionData.X)
194
- console.log('descaled array be equal to myArray', descaleArrayObj({scaled: X, config: configX, keyNames: keyNamesX}))
195
-
196
- ```
197
-
198
- ---
181
+ console.log([trainX.length, timeSteps, timeSteppedTrainX[0][0].length])
199
182
 
200
- ### Upcoming Feature: Optional Precision Handling with Big.js and BigNumber.js
183
+ const inputX = tf.tensor3d(timeSteppedTrainX, [timeSteppedTrainX.length, timeSteps, colsX])
184
+ const targetY = tf.tensor2d(trimedTrainY, [trimedTrainY.length, colsY])
201
185
 
202
- In the next release, we are introducing an optional **precision** feature to enhance decimal precision in financial and scientific datasets. This feature will allow users to integrate **Big.js** or **BigNumber.js** libraries seamlessly into their data processing workflow by adding a new `precision` property to the parameters of `parseTrainingXY` and `parseProductionX`.
203
186
 
204
- #### How Precision Handling Will Work
205
-
206
- With the new `precision` property, users can pass either Big.js or BigNumber.js as callback functions to handle high-precision decimal calculations. This makes the integration fully optional, allowing flexibility based on the precision requirements of the dataset. When `precision` is set, the toolkit will use the specified library for all numeric computations, ensuring high precision and minimizing rounding errors.
207
-
208
- 1. **Future Example Usage:**
209
-
210
- ```javascript
211
- import Big from 'big.js';
212
- import BigNumber from 'bignumber.js';
213
- import { parseTrainingXY, parseProductionX } from './scale.js';
214
-
215
- const myArray = [
216
- { open: 135.23, high: 137.45, low: 134.56, sma_200: 125.34, sma_100: 130.56 },
217
- { open: 136.45, high: 138.67, low: 135.67, sma_200: 126.78, sma_100: 131.45 },
218
- { open: 137.89, high: 139.34, low: 136.34, sma_200: 127.56, sma_100: 132.78 }
219
- ];
220
-
221
- const trainingData = parseTrainingXY({
222
- arrObj: myArray,
223
- trainingSplit: 0.75,
224
- weights: { open: 1, high: 1, low: 1, sma_200: 1, sma_100: 1 },
225
- yCallbackFunc,
226
- xCallbackFunc,
227
- precision: Big, // Big or BigNumber callbacks for high-precision calculations
228
- forceScaling: 'normalization',
229
- timeSteps: 0
230
- });
187
+ console.log('inputX', inputX)
188
+ console.log('inputX', targetY)
189
+
231
190
  ```
232
191
 
233
192
  ---
@@ -1 +1 @@
1
- var XY_Scale;(()=>{"use strict";var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{arrayToTimesteps:()=>s,descaleArrayObj:()=>a,parseProductionX:()=>o,parseTrainingXY:()=>r,timeStepsToArray:()=>i});const n=({arrObj:e,weights:t={},forceScaling:n=null})=>{if(null!==n&&"normalization"!==n&&"standardization"!==n)throw Error('forceScaling should be null, "normalization" or "standardization"');const r=e.length;if(0===r)return{scaledOutput:[],scaledConfig:{},keyNames:[]};const o=Object.keys(e[0]),a=o.map((e=>t.hasOwnProperty(e)?Math.max(t[e],1):1)),s=a.reduce(((e,t)=>e+t),0),i=new Array(s);let l=0;for(let e=0;e<o.length;e++)for(let t=0;t<a[e];t++)i[l++]=o[e];const c={},f={},u={},d={},g={},p={},h={},m={};for(const t of o){const n=e[0][t];c[t]=typeof n,"string"===c[t]&&(h[t]={}),f[t]=1/0,u[t]=-1/0,d[t]=0,g[t]=0,m[t]=0}for(const t of e)for(const e of o){let n=t[e];if("string"===c[e]){const r=h[e];r.hasOwnProperty(n)||(r[n]=Object.keys(r).length),n=r[n],t[e]=n}f[e]=Math.min(f[e],n),u[e]=Math.max(u[e],n),m[e]++;const r=n-d[e];d[e]+=r/m[e],g[e]+=r*(n-d[e])}const y={};for(const e of o)y[e]=m[e]>1?Math.sqrt(g[e]/(m[e]-1)):0,"normalization"===n||"standardization"===n?p[e]=n:0===f[e]&&1===u[e]?p[e]="none":p[e]=y[e]<1?"normalization":"standardization";const b=new Array(r);for(let t=0;t<r;t++){const n=e[t],r=new Array(s);let i=0;for(let e=0;e<o.length;e++){const t=o[e],s=n[t],l=f[t],c=u[t],g=d[t],h=y[t];let m;m="none"===p[t]?s:"normalization"===p[t]?c!==l?(s-l)/(c-l):0:0!==h?(s-g)/h:0;const b=a[e];for(let e=0;e<b;e++)r[i++]=m}b[t]=r}return{scaledOutput:b,scaledConfig:{min:f,max:u,std:y,mean:d,approach:p,inputTypes:c,uniqueStringIndexes:h},scaledKeyNames:i}},r=({arrObj:e,trainingSplit:t=.8,weights:r={},yCallbackFunc:o,xCallbackFunc:a,forceScaling:s,timeSteps:i=0})=>{const l=[],c=[];for(let t=0;t<e.length;t++){const n=a({objRow:e,index:t}),r=o({objRow:e,index:t});null!=n&&null!=r&&(l.push(n),c.push(r))}const{scaledOutput:f,scaledConfig:u,scaledKeyNames:d}=n({arrObj:l,weights:r,forceScaling:s}),{scaledOutput:g,scaledConfig:p,scaledKeyNames:h}=n({arrObj:c,weights:r,forceScaling:s}),m=Math.floor(f.length*t);return{trainX:f.slice(0,m),trainY:g.slice(0,m),testX:f.slice(m),testY:g.slice(m),configX:u,keyNamesX:d,configY:p,keyNamesY:h}},o=({arrObj:e,weights:t={},xCallbackFunc:r,forceScaling:o,timeSteps:a=0})=>{const s=[];for(let t=0;t<e.length;t++){const n=r({objRow:e,index:t});n&&s.push(n)}const{scaledOutput:i,scaledConfig:l,scaledKeyNames:c}=n({arrObj:s,weights:t,forceScaling:o});return{X:i,configX:l,keyNamesX:c}},a=({scaled:e,config:t,keyNames:n})=>{const{min:r,max:o,std:a,mean:s,approach:i,inputTypes:l,uniqueStringIndexes:c}=t;return e.map((e=>{const t={};let f=0;for(const u of Object.keys(r)){const d=i[u],g=r[u],p=o[u],h=s[u],m=a[u],y=n.filter((e=>e===u)).length;let b=0;for(let t=0;t<y;t++)b+=e[f++];const O=b/y;let S;if("normalization"===d?S=O*(p-g)+g:"standardization"===d&&(S=O*m+h),"string"===l[u]){const e=Object.keys(c[u]).find((e=>c[u][e]===S));S=void 0!==e?e:S}t[u]=S}return t}))},s=(e,t)=>{if(0===t)return e;if(t<0)throw new Error("timeSteps must be greater than 0");const n=[];for(let r=0;r<=e.length-t;r++)n.push(e.slice(r,r+t));return n},i=(e,t)=>{if(0===t)return e;if(t<0)throw new Error("timeSteps must be greater than 0");const n=[];n.push(...e[0]);for(let r=1;r<e.length;r++)n.push(e[r][t-1]);return n};XY_Scale=t})();
1
+ var XY_Scale;(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{arrayToTimesteps:()=>s,descaleArrayObj:()=>a,parseProductionX:()=>r,parseTrainingXY:()=>o});const n=({arrObj:e,weights:t={},forceScaling:n=null})=>{if(null!==n&&"normalization"!==n&&"standardization"!==n)throw Error('forceScaling should be null, "normalization" or "standardization"');const o=e.length;if(0===o)return{scaledOutput:[],scaledConfig:{},keyNames:[]};const r=Object.keys(e[0]),a=r.map((e=>t.hasOwnProperty(e)?Math.max(t[e],1):1)),s=a.reduce(((e,t)=>e+t),0),i=new Array(s);let l=0;for(let e=0;e<r.length;e++)for(let t=0;t<a[e];t++)i[l++]=r[e];const c={},f={},d={},u={},g={},p={},m={},h={};for(const t of r){const n=e[0][t];c[t]=typeof n,"string"===c[t]&&(m[t]={}),f[t]=1/0,d[t]=-1/0,u[t]=0,g[t]=0,h[t]=0}for(const t of e)for(const e of r){let n=t[e];if("string"===c[e]){const o=m[e];o.hasOwnProperty(n)||(o[n]=Object.keys(o).length),n=o[n],t[e]=n}f[e]=Math.min(f[e],n),d[e]=Math.max(d[e],n),h[e]++;const o=n-u[e];u[e]+=o/h[e],g[e]+=o*(n-u[e])}const y={};for(const e of r)y[e]=h[e]>1?Math.sqrt(g[e]/(h[e]-1)):0,"normalization"===n||"standardization"===n?p[e]=n:0===f[e]&&1===d[e]?p[e]="none":p[e]=y[e]<1?"normalization":"standardization";const b=new Array(o);for(let t=0;t<o;t++){const n=e[t],o=new Array(s);let i=0;for(let e=0;e<r.length;e++){const t=r[e],s=n[t],l=f[t],c=d[t],g=u[t],m=y[t];let h;h="none"===p[t]?s:"normalization"===p[t]?c!==l?(s-l)/(c-l):0:0!==m?(s-g)/m:0;const b=a[e];for(let e=0;e<b;e++)o[i++]=h}b[t]=o}return{scaledOutput:b,scaledConfig:{min:f,max:d,std:y,mean:u,approach:p,inputTypes:c,uniqueStringIndexes:m},scaledKeyNames:i}},o=({arrObj:e,trainingSplit:t=.8,weights:o={},yCallbackFunc:r,xCallbackFunc:a,forceScaling:s,timeSteps:i=0})=>{const l=[],c=[];for(let t=0;t<e.length;t++){const n=a({objRow:e,index:t}),o=r({objRow:e,index:t});null!=n&&null!=o&&(l.push(n),c.push(o))}const{scaledOutput:f,scaledConfig:d,scaledKeyNames:u}=n({arrObj:l,weights:o,forceScaling:s}),{scaledOutput:g,scaledConfig:p,scaledKeyNames:m}=n({arrObj:c,weights:o,forceScaling:s}),h=Math.floor(f.length*t);return{trainX:f.slice(0,h),trainY:g.slice(0,h),testX:f.slice(h),testY:g.slice(h),configX:d,keyNamesX:u,configY:p,keyNamesY:m}},r=({arrObj:e,weights:t={},xCallbackFunc:o,forceScaling:r,timeSteps:a=0})=>{const s=[];for(let t=0;t<e.length;t++){const n=o({objRow:e,index:t});n&&s.push(n)}const{scaledOutput:i,scaledConfig:l,scaledKeyNames:c}=n({arrObj:s,weights:t,forceScaling:r});return{X:i,configX:l,keyNamesX:c}},a=({scaled:e,config:t,keyNames:n})=>{const{min:o,max:r,std:a,mean:s,approach:i,inputTypes:l,uniqueStringIndexes:c}=t;return e.map((e=>{const t={};let f=0;for(const d of Object.keys(o)){const u=i[d],g=o[d],p=r[d],m=s[d],h=a[d],y=n.filter((e=>e===d)).length;let b=0;for(let t=0;t<y;t++)b+=e[f++];const O=b/y;let S;if("normalization"===u?S=O*(p-g)+g:"standardization"===u&&(S=O*h+m),"string"===l[d]){const e=Object.keys(c[d]).find((e=>c[d][e]===S));S=void 0!==e?e:S}t[d]=S}return t}))},s=(e,t)=>{if(0===t)return e;if(t<0)throw new Error("timeSteps must be greater than 0");const n=[];for(let o=0;o<=e.length-t;o++)n.push(e.slice(o,o+t));return n};XY_Scale=t})();
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { parseTrainingXY, parseProductionX } from "./src/datasets.js"
2
2
  import { descaleArrayObj } from "./src/descale.js"
3
- import { timeStepsToArray, arrayToTimesteps } from "./src/timeSteps.js"
3
+ import {arrayToTimesteps } from "./src/timeSteps.js"
4
4
 
5
- export { parseTrainingXY, parseProductionX, descaleArrayObj, timeStepsToArray, arrayToTimesteps }
5
+ export { parseTrainingXY, parseProductionX, descaleArrayObj, arrayToTimesteps }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xy-scale",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "main": "./index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -11,6 +11,7 @@
11
11
  "license": "ISC",
12
12
  "description": "This repository contains a JavaScript module designed to facilitate the preprocessing of datasets for machine learning applications. The primary functionality of the module is to scale feature data using normalization or standardization methods, and to parse training and production datasets into appropriate formats for training models.",
13
13
  "devDependencies": {
14
+ "@tensorflow/tfjs-node": "^4.22.0",
14
15
  "webpack": "^5.96.1",
15
16
  "webpack-cli": "^5.1.4"
16
17
  },
package/src/timeSteps.js CHANGED
@@ -9,22 +9,4 @@ export const arrayToTimesteps = (arr, timeSteps) => {
9
9
  }
10
10
 
11
11
  return timestepsArray;
12
- }
13
-
14
-
15
- export const timeStepsToArray = (arr, timeSteps) => {
16
- if (timeSteps === 0) return arr;
17
- if (timeSteps < 0) throw new Error("timeSteps must be greater than 0");
18
-
19
- const result = [];
20
-
21
- // Start by adding all elements of the first timestep
22
- result.push(...arr[0]);
23
-
24
- // For each subsequent timestep, add only the last element
25
- for (let i = 1; i < arr.length; i++) {
26
- result.push(arr[i][timeSteps - 1]);
27
- }
28
-
29
- return result;
30
- };
12
+ }
package/test/test.js CHANGED
@@ -1,35 +1,41 @@
1
- import { parseTrainingXY, parseProductionX } from "../src/datasets.js";
2
- import { descaleArrayObj } from "../src/descale.js";
3
- import { loadFile } from "./fs.js";
1
+ import { parseTrainingXY } from "../src/datasets.js"
2
+ import {arrayToTimesteps} from '../src/timeSteps.js'
3
+ import { loadFile } from "./fs.js"
4
+ import * as tf from '@tensorflow/tfjs-node'
4
5
 
5
6
  const test = async () => {
6
7
 
7
- const timeSteps = 10
8
- const myArray = (await loadFile({fileName: '1d-spy.json', pathName: 'datasets'}))
8
+ const myArray = (await loadFile({fileName: '1d-spy.json', pathName: 'datasets'})) //file in /datasets/1d-spy.json
9
9
 
10
+ //callback function used to prepare X before scaling
10
11
  const xCallbackFunc = ({ objRow, index }) => {
11
- const curr = objRow[index];
12
- const { open, high, low} = curr;
13
-
12
+ const curr = objRow[index]
13
+ const prev = objRow[index - 1]
14
+
14
15
  //returning null or undefined will exclude current row X and Y from training
16
+ if(typeof prev === 'undefined') return null
17
+
18
+ const { open, high, low, close } = curr
19
+
15
20
  return {
16
- open,
17
- high,
18
- low,
19
- };
20
- };
21
-
21
+ change: open - prev.close,
22
+ top: high - Math.max(open, close),
23
+ bottom: low - Math.min(open, close),
24
+ body: open-close,
25
+ }
26
+ }
27
+
28
+ //callback function used to prepare Y before scaling
22
29
  const yCallbackFunc = ({ objRow, index }) => {
23
30
  const curr = objRow[index];
24
31
  const next = objRow[index + 1];
25
-
26
- //returning null or undefined will exclude current row X and Y from training
32
+
33
+ //returning null or undefined will exclude current row X and Y from training
27
34
  if (typeof next === 'undefined') return null;
28
-
35
+
29
36
  return {
30
- label_1: next.open > curr.open, // Label indicating if the next open price is higher than the current
31
- label_2: next.high > curr.high, // Label indicating if the next high price is higher than the current
32
- label_3: next.low > curr.low, // Label indicating if the next low price is higher than the current
37
+ label_1: next.open > curr.close,
38
+ label_2: next.close > curr.close,
33
39
  };
34
40
  };
35
41
 
@@ -42,22 +48,31 @@ const test = async () => {
42
48
  keyNamesX,
43
49
  } = parseTrainingXY({
44
50
  arrObj: myArray,
45
- trainingSplit: 0.75,
46
- weights: { open: 1, high: 1, low: 1, sma_200: 1, sma_100: 1 },
51
+ trainingSplit: 0.90,
47
52
  yCallbackFunc,
48
53
  xCallbackFunc,
49
- forceScaling: null,
50
- timeSteps
54
+ forceScaling: 'normalization',
51
55
  });
52
56
 
53
- //console.log(JSON.stringify(trainingData))
54
57
 
55
58
  console.log('testX', testX.slice(-2))
56
- const descaled = descaleArrayObj({scaled: testX, config: configX, keyNames: keyNamesX, timeSteps})
57
59
 
58
- //comparing descaled values with the last values of input myArray
59
- console.log(descaled.slice(-2)) //last 2 values of descaled
60
- console.log(myArray.slice(-3, -1).map(({ open, high, low }) => ({ open, high, low }))) //last 2 values of myArray -1 interval
60
+
61
+ const timeSteps = 10
62
+ const colsX = trainX[0].length
63
+ const colsY = trainY[0].length
64
+ const timeSteppedTrainX = arrayToTimesteps(trainX, timeSteps)
65
+ const trimedTrainY = trainY.slice(timeSteps-1)
66
+
67
+
68
+ console.log([trainX.length, timeSteps, timeSteppedTrainX[0][0].length])
69
+
70
+ const inputX = tf.tensor3d(timeSteppedTrainX, [timeSteppedTrainX.length, timeSteps, colsX])
71
+ const targetY = tf.tensor2d(trimedTrainY, [trimedTrainY.length, colsY])
72
+
73
+
74
+ console.log('inputX', inputX)
75
+ console.log('inputX', targetY)
61
76
  }
62
77
 
63
78
  test()