ohlcv-indicators 1.9.3 → 1.9.5

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.
@@ -8,6 +8,7 @@ import { bollingerBands } from "../moving-averages/bollingerBands.js"
8
8
  import { volumeOscillator } from "../oscillators/volumeOscillator.js"
9
9
  import { candlesStudies } from "../studies/candleStudies.js"
10
10
  import { lag } from "../studies/lag.js"
11
+ import {crossPairs} from "../studies/findCrosses.js"
11
12
 
12
13
  const indicatorFunctions = {
13
14
  rsi,
@@ -19,19 +20,19 @@ const indicatorFunctions = {
19
20
  bollingerBands,
20
21
  volumeOscillator,
21
22
  candlesStudies,
22
- lag
23
+ lag,
23
24
  }
24
25
 
25
26
  const validateFirstDate = (arr) => arr[0].hasOwnProperty('date') && typeof arr[0].date === 'string' && /^\d{4}-\d{2}-\d{2}/.test(arr[0].date)
26
27
 
27
28
  export const defaultStudyOptions = {
28
- midPriceOpenClose: false,
29
- midPriceHighLow: false,
30
- sessionIndex: false,
31
- sessionIntradayIndex: false,
32
- dayOfTheWeek: false,
33
- dayOfTheMonth: false,
34
- weekOfTheMonth: false
29
+ midPriceOpenClose: true,
30
+ midPriceHighLow: true,
31
+ sessionIndex: true,
32
+ sessionIntradayIndex: true,
33
+ dayOfTheWeek: true,
34
+ dayOfTheMonth: true,
35
+ weekOfTheMonth: true
35
36
  }
36
37
 
37
38
  const getDateInfo = (dateString) => {
@@ -49,8 +50,8 @@ const getDateInfo = (dateString) => {
49
50
  };
50
51
  }
51
52
 
52
- export const parseOhlcvToVertical = (input, main) => {
53
- const { len, studyOptions, inputParams } = main
53
+ export const parseOhlcvToVertical = (input, main, startIndex = 0) => {
54
+ const { len, studyOptions = {}, inputParams } = main
54
55
 
55
56
  if (studyOptions) {
56
57
  const studyOptionKeys = Object.keys(studyOptions)
@@ -79,59 +80,83 @@ export const parseOhlcvToVertical = (input, main) => {
79
80
  const numberColsKeysSet = new Set(numberColsKeys)
80
81
  const vert = main.verticalOhlcv
81
82
 
82
- // Initialize arrays for numerical columns
83
- for (let i = 0; i < numberColsKeys.length; i++) {
84
- vert[numberColsKeys[i]] = new Array(len)
85
- }
83
+ let isValidDate = false
84
+ if (startIndex === 0) {
85
+ // Fresh initialization
86
+ // Initialize arrays for numerical columns
87
+ for (let i = 0; i < numberColsKeys.length; i++) {
88
+ vert[numberColsKeys[i]] = new Array(len)
89
+ }
86
90
 
87
- // Extract other keys and initialize their arrays
88
- const inputKeys = Object.keys(input[0])
89
- const otherKeys = []
90
- for (let i = 0; i < inputKeys.length; i++) {
91
- const key = inputKeys[i]
92
- if (!numberColsKeysSet.has(key)) {
93
- vert[key] = new Array(len)
94
- otherKeys.push(key)
91
+ // Extract other keys and initialize their arrays
92
+ const inputKeys = Object.keys(input[0])
93
+ const otherKeys = []
94
+ for (let i = 0; i < inputKeys.length; i++) {
95
+ const key = inputKeys[i]
96
+ if (!numberColsKeysSet.has(key)) {
97
+ vert[key] = new Array(len)
98
+ otherKeys.push(key)
99
+ }
95
100
  }
96
- }
101
+ main.otherKeys = otherKeys
97
102
 
98
- const isValidDate = validateFirstDate(input)
99
- let prevDateStr
100
- let sessionIndexCount = 0
101
- let sessionIntradayIndexCount = 0
103
+ isValidDate = validateFirstDate(input)
102
104
 
103
- // Initialize date-related arrays if necessary
104
- if (isValidDate) {
105
- if (sessionIndex) {
106
- main.verticalOhlcv['session_index'] = new Array(len)
107
- }
108
- if (sessionIntradayIndex) {
109
- main.verticalOhlcv['session_intraday_index'] = new Array(len)
110
- }
111
- if (dayOfTheWeek) {
112
- main.verticalOhlcv['day_of_the_week'] = new Array(len)
105
+ if (isValidDate) {
106
+ if (sessionIndex) {
107
+ vert['session_index'] = new Array(len)
108
+ }
109
+ if (sessionIntradayIndex) {
110
+ vert['session_intraday_index'] = new Array(len)
111
+ }
112
+ if (dayOfTheWeek) {
113
+ vert['day_of_the_week'] = new Array(len)
114
+ }
115
+ if (dayOfTheMonth) {
116
+ vert['day_of_the_month'] = new Array(len)
117
+ }
118
+ if (weekOfTheMonth) {
119
+ vert['week_of_the_month'] = new Array(len)
120
+ }
121
+
122
+ main.prevDateStr = input[0].date.slice(0, 10)
123
+ main.sessionIndexCount = 0
124
+ main.sessionIntradayIndexCount = 0
125
+ main.cachedDayInfo = getDateInfo(main.prevDateStr)
126
+ } else {
127
+ // If no valid date, ensure these are null
128
+ main.prevDateStr = null
129
+ main.sessionIndexCount = null
130
+ main.sessionIntradayIndexCount = null
131
+ main.cachedDayInfo = null
113
132
  }
114
- if (dayOfTheMonth) {
115
- main.verticalOhlcv['day_of_the_month'] = new Array(len)
133
+ } else {
134
+ // startIndex > 0
135
+ // We assume arrays and keys are already set
136
+ if (!main.otherKeys) {
137
+ throw new Error("otherKeys not found in main. Ensure you run with startIndex=0 first to initialize.")
116
138
  }
117
- if (weekOfTheMonth) {
118
- main.verticalOhlcv['week_of_the_month'] = new Array(len)
139
+
140
+ // Validate that state variables needed are present
141
+ if (!main.hasOwnProperty('prevDateStr')) {
142
+ throw new Error("prevDateStr missing in main. Make sure to store state after initial run.")
119
143
  }
120
144
 
121
- prevDateStr = input[0].date.slice(0, 10)
145
+ // If we had a valid date initially, we continue with date computations
146
+ isValidDate = main.prevDateStr !== null
122
147
  }
123
148
 
124
149
  // Pre-process indicator params
125
150
  const indicatorCalls = []
126
151
  if (inputParams && typeof inputParams === 'object') {
127
152
  for (const key in inputParams) {
128
- if (key === 'crossPairs') continue
129
153
  const technical = inputParams[key]
130
154
  if (Array.isArray(technical)) {
131
155
  for (let i = 0; i < technical.length; i++) {
132
156
  const params = technical[i];
133
157
  if (Array.isArray(params)) {
134
158
  indicatorCalls.push({
159
+ key,
135
160
  fn: indicatorFunctions[key],
136
161
  args: params
137
162
  })
@@ -152,14 +177,19 @@ export const parseOhlcvToVertical = (input, main) => {
152
177
 
153
178
  // References for other keys arrays
154
179
  const otherArrays = {}
155
- for (let i = 0; i < otherKeys.length; i++) {
156
- const k = otherKeys[i]
180
+ for (let i = 0; i < main.otherKeys.length; i++) {
181
+ const k = main.otherKeys[i]
157
182
  otherArrays[k] = vert[k]
158
183
  }
159
184
 
160
- // Cached date info for the current date
161
- let cachedDayInfo = getDateInfo(prevDateStr) // initial date info if needed
162
- for (let x = 0; x < len; x++) {
185
+ // For date/session logic, use previously stored state if startIndex > 0
186
+ let prevDateStr = main.prevDateStr
187
+ let sessionIndexCount = main.sessionIndexCount
188
+ let sessionIntradayIndexCount = main.sessionIntradayIndexCount
189
+ let cachedDayInfo = main.cachedDayInfo
190
+
191
+ // Compute indicators and fill data from startIndex to len
192
+ for (let x = startIndex; x < len; x++) {
163
193
  const current = input[x]
164
194
 
165
195
  // Assign OHLCV
@@ -169,11 +199,7 @@ export const parseOhlcvToVertical = (input, main) => {
169
199
  vo_close[x] = current.close
170
200
  vo_volume[x] = current.volume
171
201
 
172
- // Run indicator functions
173
- for (let i = 0; i < indicatorCalls.length; i++) {
174
- const { fn, args } = indicatorCalls[i]
175
- fn(main, x, ...args)
176
- }
202
+
177
203
 
178
204
  // Mid-price calculations
179
205
  if (vo_mid_oc) {
@@ -184,8 +210,8 @@ export const parseOhlcvToVertical = (input, main) => {
184
210
  }
185
211
 
186
212
  // Other keys
187
- for (let i = 0; i < otherKeys.length; i++) {
188
- const k = otherKeys[i]
213
+ for (let i = 0; i < main.otherKeys.length; i++) {
214
+ const k = main.otherKeys[i]
189
215
  otherArrays[k][x] = current[k]
190
216
  }
191
217
 
@@ -200,26 +226,43 @@ export const parseOhlcvToVertical = (input, main) => {
200
226
  }
201
227
 
202
228
  if (dayOfTheWeek) {
203
- main.verticalOhlcv.day_of_the_week[x] = cachedDayInfo.day_of_the_week
229
+ vert.day_of_the_week[x] = cachedDayInfo.day_of_the_week
204
230
  }
205
231
 
206
232
  if (dayOfTheMonth) {
207
- main.verticalOhlcv.day_of_the_month[x] = cachedDayInfo.day_of_the_month
233
+ vert.day_of_the_month[x] = cachedDayInfo.day_of_the_month
208
234
  }
209
235
 
210
236
  if (weekOfTheMonth) {
211
- main.verticalOhlcv.week_of_the_month[x] = cachedDayInfo.week_of_the_month
237
+ vert.week_of_the_month[x] = cachedDayInfo.week_of_the_month
212
238
  }
213
239
 
214
240
  if (sessionIndex) {
215
- main.verticalOhlcv.session_index[x] = sessionIndexCount
241
+ vert.session_index[x] = sessionIndexCount
216
242
  }
217
243
 
218
244
  if (sessionIntradayIndex) {
219
- main.verticalOhlcv.session_intraday_index[x] = sessionIntradayIndexCount
245
+ vert.session_intraday_index[x] = sessionIntradayIndexCount
220
246
  }
221
247
 
222
248
  sessionIntradayIndexCount++
249
+
250
+
251
+ // Run indicator functions
252
+ for (let i = 0; i < indicatorCalls.length; i++) {
253
+ const { fn, args, key } = indicatorCalls[i]
254
+ if(key === 'crossPairs' || key === 'lag') continue
255
+ fn(main, x, ...args)
256
+ }
257
+
258
+ lag(main, x, inputParams.lag)
259
+ crossPairs(main, x, main.crossPairsList)
223
260
  }
224
261
  }
262
+
263
+ // Store current state so that we can continue from here in subsequent calls
264
+ main.prevDateStr = prevDateStr
265
+ main.sessionIndexCount = sessionIndexCount
266
+ main.sessionIntradayIndexCount = sessionIntradayIndexCount
267
+ main.cachedDayInfo = cachedDayInfo
225
268
  }