ohlcv-indicators 1.3.9 → 1.4.0

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.
@@ -1,22 +1,32 @@
1
1
  import {Big} from 'trading-signals';
2
2
 
3
-
4
3
  // Function to find crosses between two arrays: fast and slow
5
- export const findCrosses = (fast, slow) => {
4
+ export const findCrosses = (fast, slow, precision) => {
6
5
  // Map states based on comparison of fast and slow arrays
7
6
 
8
- fast = fast.filter(o => o instanceof Big)
9
- slow = slow.filter(o => o instanceof Big)
7
+ fast = fast.filter(o => o instanceof Big || typeof o === 'number')
8
+ slow = slow.filter(o => o instanceof Big || typeof o === 'number')
9
+
10
10
  const min = Math.min(fast.length, slow.length)
11
11
 
12
- fast = fast.slice(-min);
13
- slow = slow.slice(-min);
12
+ fast = fast.slice(-min)
13
+ slow = slow.slice(-min)
14
14
 
15
15
  let state = fast.map((f, i) => {
16
- if(f.eq(slow[i])) return 'neutral'
17
- else if(f.gt(slow[i])) return 'up'
18
- else if(f.lt(slow[i])) return 'down'
19
- else throw Error('undefined error in findCrosses')
16
+ if(precision)
17
+ {
18
+ if(f.eq(slow[i])) return 'neutral'
19
+ else if(f.gt(slow[i])) return 'up'
20
+ else if(f.lt(slow[i])) return 'down'
21
+ }
22
+ else
23
+ {
24
+ if(f === slow[i]) return 'neutral'
25
+ else if(f > slow[i]) return 'up'
26
+ else if(f < slow[i]) return 'down'
27
+ }
28
+
29
+ throw Error('undefined error in findCrosses')
20
30
  })
21
31
 
22
32
  const groups = groupConsecutiveValues(state)
@@ -75,8 +85,9 @@ const groupConsecutiveValues = arr => {
75
85
 
76
86
 
77
87
 
78
- export const crossPairs = (ohlcv, arr) => {
88
+ export const crossPairs = (main, arr) => {
79
89
 
90
+ const {verticalOhlcv, precision} = main
80
91
  const slowNumArrCache = {};
81
92
  const output = {}
82
93
 
@@ -87,21 +98,21 @@ export const crossPairs = (ohlcv, arr) => {
87
98
  // Prepare slowNumArr if 'slow' is a number
88
99
  if (typeof slow === 'number' && !slowNumArrCache[slow]) {
89
100
 
90
- slowNumArrCache[slow] = Array(ohlcv.close.length).fill(new Big(slow))
101
+ slowNumArrCache[slow] = Array(verticalOhlcv.close.length).fill(new Big(slow))
91
102
  }
92
103
 
93
104
  const keyName = `${fast}_x_${slow}`
94
105
 
95
106
  // Find and add crosses
96
- if (ohlcv[fast] && ohlcv[slow]) {
107
+ if (verticalOhlcv[fast] && verticalOhlcv[slow]) {
97
108
 
98
- const cross = findCrosses(ohlcv[fast], ohlcv[slow]);
109
+ const cross = findCrosses(verticalOhlcv[fast], verticalOhlcv[slow], precision);
99
110
 
100
111
  output[keyName] = cross
101
112
 
102
113
 
103
- } else if (ohlcv[fast] && slowNumArrCache[slow]) {
104
- const cross = findCrosses(ohlcv[fast], slowNumArrCache[slow])
114
+ } else if (verticalOhlcv[fast] && slowNumArrCache[slow]) {
115
+ const cross = findCrosses(verticalOhlcv[fast], slowNumArrCache[slow], precision)
105
116
 
106
117
  output[keyName] = cross
107
118
 
@@ -1,6 +1,6 @@
1
- export const volumeProfile = (ohlcv, numBins, daysBack = 1, targetDateKey) => {
1
+ export const volumeProfile = (verticalOhlcv, numBins, daysBack = 1, targetDateKey) => {
2
2
 
3
- const filteredOhlcv = filterLastDays(ohlcv, daysBack, targetDateKey)
3
+ const filteredOhlcv = filterLastDays(verticalOhlcv, daysBack, targetDateKey)
4
4
  const vP = calculateBins(filteredOhlcv, numBins)
5
5
  const vp_high = vP.nodes.high.price
6
6
  const vp_low = vP.nodes.low.price
@@ -12,8 +12,8 @@ export const volumeProfile = (ohlcv, numBins, daysBack = 1, targetDateKey) => {
12
12
  }
13
13
 
14
14
 
15
- export const calculateBins = (ohlcv, numBins = 5) => {
16
- const { open, high, low, close, volume } = ohlcv;
15
+ export const calculateBins = (verticalOhlcv, numBins = 5) => {
16
+ const { open, high, low, close, volume } = verticalOhlcv;
17
17
 
18
18
  // Determine the range of prices
19
19
  const lowPrice = Math.min(...low);
@@ -1,466 +0,0 @@
1
- export default class ChartPatterns {
2
-
3
- constructor(ohlcv, period = 100) {
4
- const validProps = ['open', 'high', 'low', 'close'];
5
- this.ohlcv = {};
6
-
7
- for (let key of Object.keys(ohlcv)) {
8
- if (validProps.includes(key)) {
9
- this.ohlcv[key] = ohlcv[key].slice(-period);
10
- }
11
- }
12
- }
13
-
14
- init() {
15
- const length = this.ohlcv.close.length;
16
- if (length < 50) {
17
- console.log('PatternRecognizer requires at least 50 datapoints')
18
- return { chart_pattern: 'Neutral', chart_score: 0 };
19
- }
20
-
21
- const patterns = [
22
- { name: 'Bullish Flag', condition: this.isBullishFlag.bind(this), score: 2 },
23
- { name: 'Bearish Flag', condition: this.isBearishFlag.bind(this), score: -2 },
24
- { name: 'Bullish Pennant', condition: this.isBullishPennant.bind(this), score: 2 },
25
- { name: 'Bearish Pennant', condition: this.isBearishPennant.bind(this), score: -2 },
26
- { name: 'Bearish Double Top', condition: this.isDoubleTop.bind(this), score: -1 },
27
- { name: 'Bullish Double Bottom', condition: this.isDoubleBottom.bind(this), score: 1 },
28
- { name: 'Bearish Triple Top', condition: this.isTripleTop.bind(this), score: -1 },
29
- { name: 'Bullish Triple Bottom', condition: this.isTripleBottom.bind(this), score: 1 },
30
- { name: 'Bearish Head And Shoulders', condition: this.isHeadAndShoulders.bind(this), score: -1 },
31
- { name: 'Bullish Inverse Head And Shoulders', condition: this.isInverseHeadAndShoulders.bind(this), score: 1 },
32
- { name: 'Bearish Rising Wedge', condition: this.isRisingWedge.bind(this), score: -1 },
33
- { name: 'Bullish Falling Wedge', condition: this.isFallingWedge.bind(this), score: 1 },
34
- { name: 'Bullish Triangle', condition: this.isBullishTriangle.bind(this), score: 1 },
35
- { name: 'Bearish Triangle', condition: this.isBearishTriangle.bind(this), score: -1 },
36
- { name: 'Bullish Rectangle', condition: this.isBullishRectangle.bind(this), score: 1 },
37
- { name: 'Bearish Rectangle', condition: this.isBearishRectangle.bind(this), score: -1 },
38
- ];
39
-
40
- for (const { name, condition, score } of patterns) {
41
- if (condition()) {
42
- return { chart_pattern: name, chart_score: score };
43
- }
44
- }
45
-
46
- return { chart_pattern: 'Neutral', chart_score: 0 };
47
- }
48
-
49
-
50
- // Implementation of Bullish Flag
51
- // https://www.tradingview.com/support/solutions/43000653209/
52
-
53
- isBullishFlag() {
54
-
55
- // A Bullish Flag is characterized by a sharp price rise followed by a period of consolidation that has a downward slant.
56
- const length = this.ohlcv.close.length;
57
- const flagpoleLength = Math.floor(length / 3); // Roughly the first third of the data
58
- const consolidationLength = Math.floor(flagpoleLength / 2); // Roughly half the length of the flagpole
59
-
60
- // Sharp price rise (flagpole)
61
- const flagpoleStart = this.ohlcv.close[length - flagpoleLength * 2];
62
- const flagpoleEnd = this.ohlcv.close[length - flagpoleLength];
63
- const flagpoleGain = (flagpoleEnd - flagpoleStart) / flagpoleStart;
64
-
65
- if (flagpoleGain < 0.15) { // A significant gain, at least 15%
66
- return false;
67
- }
68
-
69
- // Consolidation period
70
- const consolidationStart = this.ohlcv.close[length - flagpoleLength];
71
- const consolidationEnd = this.ohlcv.close[length - 1];
72
- const consolidationDrop = (consolidationStart - consolidationEnd) / consolidationStart;
73
-
74
- if (consolidationDrop > 0.05) { // A downward slant, less than 5%
75
- return false;
76
- }
77
-
78
- // Ensure that the consolidation period has lower highs and lower lows
79
- for (let i = length - flagpoleLength; i < length - 1; i++) {
80
- if (this.ohlcv.high[i] > this.ohlcv.high[i + 1] || this.ohlcv.low[i] > this.ohlcv.low[i + 1]) {
81
- return false;
82
- }
83
- }
84
-
85
- return true;
86
- }
87
-
88
- // Implementation of Bearish Flag
89
- // https://www.tradingview.com/support/solutions/43000653209-chart-pattern-bullish-flag/
90
- isBearishFlag() {
91
- // A Bearish Flag is characterized by a sharp price decline followed by a period of consolidation that has an upward slant.
92
- const length = this.ohlcv.close.length;
93
- const flagpoleLength = Math.floor(length / 3); // Roughly the first third of the data
94
- const consolidationLength = Math.floor(flagpoleLength / 2); // Roughly half the length of the flagpole
95
-
96
- // Sharp price decline (flagpole)
97
- const flagpoleStart = this.ohlcv.close[length - flagpoleLength * 2];
98
- const flagpoleEnd = this.ohlcv.close[length - flagpoleLength];
99
- const flagpoleDrop = (flagpoleStart - flagpoleEnd) / flagpoleStart;
100
-
101
- if (flagpoleDrop < 0.15) { // A significant drop, at least 15%
102
- return false;
103
- }
104
-
105
- // Consolidation period
106
- const consolidationStart = this.ohlcv.close[length - flagpoleLength];
107
- const consolidationEnd = this.ohlcv.close[length - 1];
108
- const consolidationGain = (consolidationEnd - consolidationStart) / consolidationStart;
109
-
110
- if (consolidationGain > 0.05) { // An upward slant, less than 5%
111
- return false;
112
- }
113
-
114
- // Ensure that the consolidation period has higher lows and higher highs
115
- for (let i = length - flagpoleLength; i < length - 1; i++) {
116
- if (this.ohlcv.high[i] < this.ohlcv.high[i + 1] || this.ohlcv.low[i] < this.ohlcv.low[i + 1]) {
117
- return false;
118
- }
119
- }
120
-
121
- return true;
122
- }
123
-
124
- // Implementation of Bullish Pennant
125
- // https://www.tradingview.com/support/solutions/43000653215-chart-pattern-bullish-pennant/
126
- isBullishPennant() {
127
- // A Bullish Pennant is characterized by a sharp price rise followed by a small symmetrical triangle consolidation.
128
- const length = this.ohlcv.close.length;
129
- const flagpoleLength = Math.floor(length / 3); // Roughly the first third of the data
130
- const pennantLength = Math.floor(flagpoleLength / 2); // Roughly half the length of the flagpole
131
-
132
- // Sharp price rise (flagpole)
133
- const flagpoleStart = this.ohlcv.close[length - flagpoleLength * 2];
134
- const flagpoleEnd = this.ohlcv.close[length - flagpoleLength];
135
- const flagpoleGain = (flagpoleEnd - flagpoleStart) / flagpoleStart;
136
-
137
- if (flagpoleGain < 0.15) { // A significant gain, at least 15%
138
- return false;
139
- }
140
-
141
- // Small symmetrical triangle consolidation
142
- const pennantStart = this.ohlcv.close[length - flagpoleLength];
143
- const pennantEnd = this.ohlcv.close[length - 1];
144
- const pennantDrop = (pennantStart - pennantEnd) / pennantStart;
145
-
146
- if (pennantDrop > 0.05) { // A downward slant, less than 5%
147
- return false;
148
- }
149
-
150
- // Ensure the consolidation period forms a small symmetrical triangle
151
- for (let i = length - pennantLength; i < length - 1; i++) {
152
- if ((this.ohlcv.high[i] < this.ohlcv.high[i + 1] && this.ohlcv.low[i] < this.ohlcv.low[i + 1]) ||
153
- (this.ohlcv.high[i] > this.ohlcv.high[i + 1] && this.ohlcv.low[i] > this.ohlcv.low[i + 1])) {
154
- return false;
155
- }
156
- }
157
-
158
- return true;
159
- }
160
-
161
- // Implementation of Bearish Pennant
162
- // https://www.tradingview.com/support/solutions/43000697937-chart-pattern-bearish-pennant/
163
- isBearishPennant() {
164
- const length = this.ohlcv.close.length;
165
- const flagpoleLength = Math.floor(length / 3); // Roughly the first third of the data
166
- const pennantLength = Math.floor(flagpoleLength / 2); // Roughly half the length of the flagpole
167
-
168
- // Sharp price decline (flagpole)
169
- const flagpoleStart = this.ohlcv.close[length - flagpoleLength * 2];
170
- const flagpoleEnd = this.ohlcv.close[length - flagpoleLength];
171
- const flagpoleDrop = (flagpoleStart - flagpoleEnd) / flagpoleStart;
172
-
173
- if (flagpoleDrop < 0.15) { // A significant drop, at least 15%
174
- return false;
175
- }
176
-
177
- // Small symmetrical triangle consolidation
178
- const pennantStart = this.ohlcv.close[length - flagpoleLength];
179
- const pennantEnd = this.ohlcv.close[length - 1];
180
- const pennantGain = (pennantEnd - pennantStart) / pennantStart;
181
-
182
- if (pennantGain > 0.05) { // An upward slant, less than 5%
183
- return false;
184
- }
185
-
186
- // Ensure the consolidation period forms a small symmetrical triangle
187
- for (let i = length - pennantLength; i < length - 1; i++) {
188
- if ((this.ohlcv.high[i] > this.ohlcv.high[i + 1] && this.ohlcv.low[i] > this.ohlcv.low[i + 1]) ||
189
- (this.ohlcv.high[i] < this.ohlcv.high[i + 1] && this.ohlcv.low[i] < this.ohlcv.low[i + 1])) {
190
- return false;
191
- }
192
- }
193
-
194
- return true;
195
- }
196
-
197
- // Implementation of Double Top
198
- // https://www.tradingview.com/support/solutions/43000653211-chart-pattern-double-top/
199
- isDoubleTop() {
200
- const length = this.ohlcv.close.length;
201
- const midpoint = Math.floor(length / 2);
202
-
203
- const firstPeak = Math.max(...this.ohlcv.close.slice(0, midpoint));
204
- const secondPeak = Math.max(...this.ohlcv.close.slice(midpoint));
205
-
206
- if (firstPeak <= 0 || secondPeak <= 0) {
207
- return false;
208
- }
209
-
210
- const firstValley = Math.min(...this.ohlcv.close.slice(0, midpoint));
211
- const secondValley = Math.min(...this.ohlcv.close.slice(midpoint));
212
-
213
- const dropFromFirstPeak = (firstPeak - firstValley) / firstPeak;
214
- const dropFromSecondPeak = (secondPeak - secondValley) / secondPeak;
215
-
216
- if (dropFromFirstPeak < 0.1 || dropFromSecondPeak < 0.1) {
217
- return false;
218
- }
219
-
220
- return Math.abs(firstPeak - secondPeak) / firstPeak < 0.03;
221
- }
222
-
223
- // Implementation of Double Bottom
224
- // https://www.tradingview.com/support/solutions/43000690659-chart-pattern-double-bottom/
225
- isDoubleBottom() {
226
- const length = this.ohlcv.close.length;
227
- const midpoint = Math.floor(length / 2);
228
-
229
- const firstValley = Math.min(...this.ohlcv.close.slice(0, midpoint));
230
- const secondValley = Math.min(...this.ohlcv.close.slice(midpoint));
231
-
232
- if (firstValley <= 0 || secondValley <= 0) {
233
- return false;
234
- }
235
-
236
- const firstPeak = Math.max(...this.ohlcv.close.slice(0, midpoint));
237
- const secondPeak = Math.max(...this.ohlcv.close.slice(midpoint));
238
-
239
- const riseFromFirstValley = (firstPeak - firstValley) / firstValley;
240
- const riseFromSecondValley = (secondPeak - secondValley) / secondValley;
241
-
242
- if (riseFromFirstValley < 0.1 || riseFromSecondValley < 0.1) {
243
- return false;
244
- }
245
-
246
- return Math.abs(firstValley - secondValley) / firstValley < 0.03;
247
- }
248
-
249
- // Implementation of Triple Top
250
- // https://www.tradingview.com/support/solutions/43000653218-chart-pattern-triple-top/
251
- isTripleTop() {
252
- const length = this.ohlcv.close.length;
253
- const third = Math.floor(length / 3);
254
-
255
- const firstPeak = Math.max(...this.ohlcv.close.slice(0, third));
256
- const secondPeak = Math.max(...this.ohlcv.close.slice(third, third * 2));
257
- const thirdPeak = Math.max(...this.ohlcv.close.slice(third * 2));
258
-
259
- if (firstPeak <= 0 || secondPeak <= 0 || thirdPeak <= 0) {
260
- return false;
261
- }
262
-
263
- const dropFromFirstPeak = (firstPeak - Math.min(...this.ohlcv.close.slice(0, third))) / firstPeak;
264
- const dropFromSecondPeak = (secondPeak - Math.min(...this.ohlcv.close.slice(third, third * 2))) / secondPeak;
265
- const dropFromThirdPeak = (thirdPeak - Math.min(...this.ohlcv.close.slice(third * 2))) / thirdPeak;
266
-
267
- if (dropFromFirstPeak < 0.1 || dropFromSecondPeak < 0.1 || dropFromThirdPeak < 0.1) {
268
- return false;
269
- }
270
-
271
- return Math.abs(firstPeak - secondPeak) / firstPeak < 0.03 && Math.abs(firstPeak - thirdPeak) / firstPeak < 0.03;
272
- }
273
-
274
- // Implementation of Triple Bottom
275
- // https://www.tradingview.com/support/solutions/43000690660-chart-pattern-triple-bottom/
276
- isTripleBottom() {
277
- const length = this.ohlcv.close.length;
278
- const third = Math.floor(length / 3);
279
-
280
- const firstValley = Math.min(...this.ohlcv.close.slice(0, third));
281
- const secondValley = Math.min(...this.ohlcv.close.slice(third, third * 2));
282
- const thirdValley = Math.min(...this.ohlcv.close.slice(third * 2));
283
-
284
- if (firstValley <= 0 || secondValley <= 0 || thirdValley <= 0) {
285
- return false;
286
- }
287
-
288
- const riseFromFirstValley = (Math.max(...this.ohlcv.close.slice(0, third)) - firstValley) / firstValley;
289
- const riseFromSecondValley = (Math.max(...this.ohlcv.close.slice(third, third * 2)) - secondValley) / secondValley;
290
- const riseFromThirdValley = (Math.max(...this.ohlcv.close.slice(third * 2)) - thirdValley) / thirdValley;
291
-
292
- if (riseFromFirstValley < 0.1 || riseFromSecondValley < 0.1 || riseFromThirdValley < 0.1) {
293
- return false;
294
- }
295
-
296
- return Math.abs(firstValley - secondValley) / firstValley < 0.03 && Math.abs(firstValley - thirdValley) / firstValley < 0.03;
297
- }
298
-
299
- // Implementation of Head and Shoulders
300
- // https://www.tradingview.com/support/solutions/43000653213-chart-pattern-head-and-shoulders/
301
- isHeadAndShoulders() {
302
- const length = this.ohlcv.close.length;
303
- const third = Math.floor(length / 3);
304
-
305
- const leftShoulder = Math.max(...this.ohlcv.close.slice(0, third));
306
- const head = Math.max(...this.ohlcv.close.slice(third, third * 2));
307
- const rightShoulder = Math.max(...this.ohlcv.close.slice(third * 2));
308
-
309
- if (leftShoulder <= 0 || head <= 0 || rightShoulder <= 0) {
310
- return false;
311
- }
312
-
313
- const leftValley = Math.min(...this.ohlcv.close.slice(0, third));
314
- const middleValley = Math.min(...this.ohlcv.close.slice(third, third * 2));
315
- const rightValley = Math.min(...this.ohlcv.close.slice(third * 2));
316
-
317
- const dropFromHead = (head - middleValley) / head;
318
- const riseFromValleys = (Math.max(leftValley, rightValley) - Math.min(leftValley, rightValley)) / Math.min(leftValley, rightValley);
319
-
320
- return dropFromHead > 0.15 && riseFromValleys < 0.03;
321
- }
322
-
323
- // Implementation of Inverse Head and Shoulders
324
- // https://www.tradingview.com/support/solutions/43000690666-chart-pattern-inverse-head-and-shoulders/
325
- isInverseHeadAndShoulders() {
326
- const length = this.ohlcv.close.length;
327
- const third = Math.floor(length / 3);
328
-
329
- const leftShoulder = Math.min(...this.ohlcv.close.slice(0, third));
330
- const head = Math.min(...this.ohlcv.close.slice(third, third * 2));
331
- const rightShoulder = Math.min(...this.ohlcv.close.slice(third * 2));
332
-
333
- if (leftShoulder <= 0 || head <= 0 || rightShoulder <= 0) {
334
- return false;
335
- }
336
-
337
- const leftPeak = Math.max(...this.ohlcv.close.slice(0, third));
338
- const middlePeak = Math.max(...this.ohlcv.close.slice(third, third * 2));
339
- const rightPeak = Math.max(...this.ohlcv.close.slice(third * 2));
340
-
341
- const riseFromHead = (middlePeak - head) / head;
342
- const dropFromPeaks = (Math.min(leftPeak, rightPeak) - Math.max(leftPeak, rightPeak)) / Math.max(leftPeak, rightPeak);
343
-
344
- return riseFromHead > 0.15 && dropFromPeaks < 0.03;
345
- }
346
-
347
- // Implementation of Rising Wedge
348
- // https://www.tradingview.com/support/solutions/43000653219-chart-pattern-rising-wedge/
349
- isRisingWedge() {
350
- const length = this.ohlcv.close.length;
351
- const third = Math.floor(length / 3);
352
-
353
- const firstPeak = Math.max(...this.ohlcv.close.slice(0, third));
354
- const secondPeak = Math.max(...this.ohlcv.close.slice(third, third * 2));
355
- const thirdPeak = Math.max(...this.ohlcv.close.slice(third * 2));
356
-
357
- const firstValley = Math.min(...this.ohlcv.close.slice(0, third));
358
- const secondValley = Math.min(...this.ohlcv.close.slice(third, third * 2));
359
- const thirdValley = Math.min(...this.ohlcv.close.slice(third * 2));
360
-
361
- const risingPeaks = firstPeak < secondPeak && secondPeak < thirdPeak;
362
- const risingValleys = firstValley < secondValley && secondValley < thirdValley;
363
-
364
- return risingPeaks && risingValleys;
365
- }
366
-
367
- // Implementation of Falling Wedge
368
- // https://www.tradingview.com/support/solutions/43000697938-chart-pattern-falling-wedge/
369
- isFallingWedge() {
370
- const length = this.ohlcv.close.length;
371
- const third = Math.floor(length / 3);
372
-
373
- const firstPeak = Math.max(...this.ohlcv.close.slice(0, third));
374
- const secondPeak = Math.max(...this.ohlcv.close.slice(third, third * 2));
375
- const thirdPeak = Math.max(...this.ohlcv.close.slice(third * 2));
376
-
377
- const firstValley = Math.min(...this.ohlcv.close.slice(0, third));
378
- const secondValley = Math.min(...this.ohlcv.close.slice(third, third * 2));
379
- const thirdValley = Math.min(...this.ohlcv.close.slice(third * 2));
380
-
381
- const fallingPeaks = firstPeak > secondPeak && secondPeak > thirdPeak;
382
- const fallingValleys = firstValley > secondValley && secondValley > thirdValley;
383
-
384
- return fallingPeaks && fallingValleys;
385
- }
386
-
387
- // Implementation of Bullish Triangle
388
- // https://www.tradingview.com/support/solutions/43000653217/
389
- isBullishTriangle() {
390
- const length = this.ohlcv.close.length;
391
- const half = Math.floor(length / 2);
392
-
393
- const firstHalfHigh = Math.max(...this.ohlcv.high.slice(0, half));
394
- const secondHalfHigh = Math.max(...this.ohlcv.high.slice(half));
395
-
396
- const firstHalfLow = Math.min(...this.ohlcv.low.slice(0, half));
397
- const secondHalfLow = Math.min(...this.ohlcv.low.slice(half));
398
-
399
- const contractingHighs = firstHalfHigh > secondHalfHigh;
400
- const risingLows = firstHalfLow < secondHalfLow;
401
-
402
- return contractingHighs && risingLows;
403
- }
404
-
405
- // Implementation of Bearish Triangle
406
- // https://www.tradingview.com/support/solutions/43000653217/
407
- isBearishTriangle() {
408
- const length = this.ohlcv.close.length;
409
- const half = Math.floor(length / 2);
410
-
411
- const firstHalfHigh = Math.max(...this.ohlcv.high.slice(0, half));
412
- const secondHalfHigh = Math.max(...this.ohlcv.high.slice(half));
413
-
414
- const firstHalfLow = Math.min(...this.ohlcv.low.slice(0, half));
415
- const secondHalfLow = Math.min(...this.ohlcv.low.slice(half));
416
-
417
- const contractingLows = firstHalfLow < secondHalfLow;
418
- const fallingHighs = firstHalfHigh > secondHalfHigh;
419
-
420
- return contractingLows && fallingHighs;
421
- }
422
-
423
- // Implementation of Bullish Rectangle
424
- // https://www.tradingview.com/support/solutions/43000653216/
425
- isBullishRectangle() {
426
- const length = this.ohlcv.close.length;
427
- const third = Math.floor(length / 3);
428
-
429
- const firstSectionHigh = Math.max(...this.ohlcv.high.slice(0, third));
430
- const secondSectionHigh = Math.max(...this.ohlcv.high.slice(third, third * 2));
431
- const thirdSectionHigh = Math.max(...this.ohlcv.high.slice(third * 2));
432
-
433
- const firstSectionLow = Math.min(...this.ohlcv.low.slice(0, third));
434
- const secondSectionLow = Math.min(...this.ohlcv.low.slice(third, third * 2));
435
- const thirdSectionLow = Math.min(...this.ohlcv.low.slice(third * 2));
436
-
437
- const stableHighs = Math.abs(firstSectionHigh - secondSectionHigh) / firstSectionHigh < 0.03 &&
438
- Math.abs(secondSectionHigh - thirdSectionHigh) / secondSectionHigh < 0.03;
439
- const stableLows = Math.abs(firstSectionLow - secondSectionLow) / firstSectionLow < 0.03 &&
440
- Math.abs(secondSectionLow - thirdSectionLow) / secondSectionLow < 0.03;
441
-
442
- return stableHighs && stableLows;
443
- }
444
-
445
- // Implementation of Bearish Rectangle
446
- // https://www.tradingview.com/support/solutions/43000653216/
447
- isBearishRectangle() {
448
- const length = this.ohlcv.close.length;
449
- const third = Math.floor(length / 3);
450
-
451
- const firstSectionHigh = Math.max(...this.ohlcv.high.slice(0, third));
452
- const secondSectionHigh = Math.max(...this.ohlcv.high.slice(third, third * 2));
453
- const thirdSectionHigh = Math.max(...this.ohlcv.high.slice(third * 2));
454
-
455
- const firstSectionLow = Math.min(...this.ohlcv.low.slice(0, third));
456
- const secondSectionLow = Math.min(...this.ohlcv.low.slice(third, third * 2));
457
- const thirdSectionLow = Math.min(...this.ohlcv.low.slice(third * 2));
458
-
459
- const stableHighs = Math.abs(firstSectionHigh - secondSectionHigh) / firstSectionHigh < 0.03 &&
460
- Math.abs(secondSectionHigh - thirdSectionHigh) / secondSectionHigh < 0.03;
461
- const stableLows = Math.abs(firstSectionLow - secondSectionLow) / firstSectionLow < 0.03 &&
462
- Math.abs(secondSectionLow - thirdSectionLow) / secondSectionLow < 0.03;
463
-
464
- return stableHighs && stableLows;
465
- }
466
- }