@mathieuc/tradingview 3.0.1 → 3.3.1

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.
Files changed (50) hide show
  1. package/.eslintrc.js +6 -0
  2. package/README.md +28 -2
  3. package/docs/DOCS.md +3 -0
  4. package/examples/AllPrivateIndicators.js +4 -4
  5. package/examples/BuiltInIndicator.js +1 -1
  6. package/examples/CustomChartType.js +1 -0
  7. package/examples/Errors.js +147 -153
  8. package/examples/FakeReplayMode.js +41 -0
  9. package/examples/GetDrawings.js +26 -0
  10. package/examples/PinePermManage.js +57 -0
  11. package/examples/ReplayMode.js +97 -0
  12. package/examples/UserLogin.js +16 -0
  13. package/main.js +2 -0
  14. package/package.json +6 -9
  15. package/src/FormData.js +36 -0
  16. package/src/chart/session.js +193 -17
  17. package/src/chart/study.js +68 -68
  18. package/src/classes/BuiltInIndicator.js +1 -0
  19. package/src/classes/PineIndicator.js +7 -7
  20. package/src/classes/PinePermManager.js +143 -0
  21. package/src/client.js +17 -10
  22. package/src/miscRequests.js +148 -103
  23. package/src/protocol.js +7 -1
  24. package/src/quote/session.js +1 -0
  25. package/src/request.js +37 -0
  26. package/src/types.js +6 -2
  27. package/src/utils.js +6 -0
  28. package/test.js +58 -147
  29. package/tests/1. Search.js +18 -0
  30. package/tests/2. QuoteSession.js +54 -0
  31. package/tests/3. SimpleChart.js +61 -0
  32. package/tests/4. Indicators.js +100 -0
  33. package/tests/5. BuiltInIndicator.js +41 -0
  34. package/tests/6. FakeReplayMode.js +59 -0
  35. package/tests/7. ReplayMode.js +51 -0
  36. package/tests/8. CustomChartTypes.js +115 -0
  37. package/tests/9. AllErrors.js +146 -0
  38. package/.github/FUNDING.yml +0 -1
  39. package/examples/CurrentTimeframe.js +0 -34
  40. package/examples/_RenkoIndicator.js +0 -41
  41. package/tests/alerts/discordWH.js +0 -76
  42. package/tests/alerts/drawings.js +0 -41
  43. package/tests/alerts/envLoader.js +0 -11
  44. package/tests/alerts/manualAlert.js +0 -77
  45. package/tests/alerts/sentNotifs.js +0 -16
  46. package/tests/alerts/strategyAlert.js +0 -94
  47. package/tests/analysis.js +0 -13
  48. package/tests/indicator.js +0 -42
  49. package/tests/prices.js +0 -33
  50. package/tests/strategy.js +0 -56
package/package.json CHANGED
@@ -1,20 +1,18 @@
1
1
  {
2
2
  "name": "@mathieuc/tradingview",
3
- "version": "3.0.1",
3
+ "version": "3.3.1",
4
4
  "description": "Tradingview instant stocks API, indicator alerts, trading bot, and more !",
5
5
  "main": "main.js",
6
6
  "scripts": {
7
- "test-prices": "node ./tests/prices.js",
8
- "test-analysis": "node ./tests/analysis.js",
9
- "test-indicator": "node ./tests/indicator.js",
10
- "test-manual-alerts": "node ./tests/alerts/manualAlert.js",
11
- "test-strat-alerts": "node ./tests/alerts/strategyAlert.js",
12
- "test": "npm run test-prices"
7
+ "test": "node test"
13
8
  },
14
9
  "repository": {
15
10
  "type": "git",
16
11
  "url": "git+https://github.com/Mathieu2301/TradingView-API.git"
17
12
  },
13
+ "engines": {
14
+ "node": ">=14.0.0"
15
+ },
18
16
  "keywords": [
19
17
  "tradingwiew",
20
18
  "market",
@@ -36,7 +34,6 @@
36
34
  "@mathieuc/console": "^1.0.1",
37
35
  "eslint": "^7.25.0",
38
36
  "eslint-config-airbnb-base": "^14.2.1",
39
- "eslint-plugin-import": "^2.22.1",
40
- "jsdoc-to-markdown": "^7.1.0"
37
+ "eslint-plugin-import": "^2.22.1"
41
38
  }
42
39
  }
@@ -0,0 +1,36 @@
1
+ /** @class */
2
+ class FormData {
3
+ #string = '';
4
+
5
+ #boundary = '';
6
+
7
+ get boundary() {
8
+ return this.#boundary;
9
+ }
10
+
11
+ constructor() {
12
+ const random = (Math.random() * 10 ** 20).toString(36);
13
+ this.#boundary = `${random}`;
14
+ this.#string = `--${this.boundary}`;
15
+ }
16
+
17
+ /**
18
+ * Adds a property to the FormData object
19
+ * @param {string} key Property key
20
+ * @param {string} value Property value
21
+ */
22
+ append(key, value) {
23
+ this.#string += `\r\nContent-Disposition: form-data; name="${key}"`;
24
+ this.#string += `\r\n\r\n${value}`;
25
+ this.#string += `\r\n--${this.boundary}`;
26
+ }
27
+
28
+ /**
29
+ * @returns {string}
30
+ */
31
+ toString() {
32
+ return `${this.#string}--`;
33
+ }
34
+ }
35
+
36
+ module.exports = FormData;
@@ -64,7 +64,9 @@ const ChartTypes = {
64
64
  * @prop {string} session Session (ex: '24x7')
65
65
  * @prop {string} session-correction Session correction
66
66
  * @prop {string} session-display Session display (ex: '24x7')
67
- *
67
+ */
68
+
69
+ /**
68
70
  * @typedef {Object} MarketInfos
69
71
  * @prop {string} series_id Used series (ex: 'ser_1')
70
72
  * @prop {string} base_currency Base currency (ex: 'BTC')
@@ -113,7 +115,14 @@ const ChartTypes = {
113
115
  * @param {import('../client').ClientBridge} client
114
116
  */
115
117
  module.exports = (client) => class ChartSession {
116
- #sessionID = genSessionID('cs');
118
+ #chartSessionID = genSessionID('cs');
119
+
120
+ #replaySessionID = genSessionID('rs');
121
+
122
+ #replayMode = false;
123
+
124
+ /** @type {Object<string, (): any>} */
125
+ #replayOKCB = {};
117
126
 
118
127
  /** Parent client */
119
128
  #client = client;
@@ -148,6 +157,11 @@ module.exports = (client) => class ChartSession {
148
157
  symbolLoaded: [],
149
158
  update: [],
150
159
 
160
+ replayLoaded: [],
161
+ replayPoint: [],
162
+ replayResolution: [],
163
+ replayEnd: [],
164
+
151
165
  event: [],
152
166
  error: [],
153
167
  };
@@ -167,7 +181,7 @@ module.exports = (client) => class ChartSession {
167
181
  }
168
182
 
169
183
  constructor() {
170
- this.#client.sessions[this.#sessionID] = {
184
+ this.#client.sessions[this.#chartSessionID] = {
171
185
  type: 'chart',
172
186
  onData: (packet) => {
173
187
  if (global.TW_DEBUG) console.log('§90§30§106 CHART SESSION §0 DATA', packet);
@@ -188,7 +202,10 @@ module.exports = (client) => class ChartSession {
188
202
  }
189
203
 
190
204
  if (['timescale_update', 'du'].includes(packet.type)) {
205
+ const changes = [];
206
+
191
207
  Object.keys(packet.data[1]).forEach((k) => {
208
+ changes.push(k);
192
209
  if (k === '$prices') {
193
210
  const periods = packet.data[1].$prices;
194
211
  if (!periods || !periods.s) return;
@@ -211,7 +228,7 @@ module.exports = (client) => class ChartSession {
211
228
  if (this.#studyListeners[k]) this.#studyListeners[k](packet);
212
229
  });
213
230
 
214
- this.#handleEvent('update');
231
+ this.#handleEvent('update', changes);
215
232
  return;
216
233
  }
217
234
 
@@ -232,7 +249,47 @@ module.exports = (client) => class ChartSession {
232
249
  },
233
250
  };
234
251
 
235
- this.#client.send('chart_create_session', [this.#sessionID]);
252
+ this.#client.sessions[this.#replaySessionID] = {
253
+ type: 'replay',
254
+ onData: (packet) => {
255
+ if (global.TW_DEBUG) console.log('§90§30§106 REPLAY SESSION §0 DATA', packet);
256
+
257
+ if (packet.type === 'replay_ok') {
258
+ if (this.#replayOKCB[packet.data[1]]) {
259
+ this.#replayOKCB[packet.data[1]]();
260
+ delete this.#replayOKCB[packet.data[1]];
261
+ }
262
+ return;
263
+ }
264
+
265
+ if (packet.type === 'replay_instance_id') {
266
+ this.#handleEvent('replayLoaded', packet.data[1]);
267
+ return;
268
+ }
269
+
270
+ if (packet.type === 'replay_point') {
271
+ this.#handleEvent('replayPoint', packet.data[1]);
272
+ return;
273
+ }
274
+
275
+ if (packet.type === 'replay_resolutions') {
276
+ this.#handleEvent('replayResolution', packet.data[1], packet.data[2]);
277
+ return;
278
+ }
279
+
280
+ if (packet.type === 'replay_data_end') {
281
+ this.#handleEvent('replayEnd');
282
+ return;
283
+ }
284
+
285
+ if (packet.type === 'critical_error') {
286
+ const [, name, description] = packet.data;
287
+ this.#handleError('Critical error:', name, description);
288
+ }
289
+ },
290
+ };
291
+
292
+ this.#client.send('chart_create_session', [this.#chartSessionID]);
236
293
  }
237
294
 
238
295
  #seriesCreated = false;
@@ -255,7 +312,7 @@ module.exports = (client) => class ChartSession {
255
312
  this.#periods = {};
256
313
 
257
314
  this.#client.send(`${this.#seriesCreated ? 'modify' : 'create'}_series`, [
258
- this.#sessionID,
315
+ this.#chartSessionID,
259
316
  '$prices',
260
317
  's1',
261
318
  `ser_${this.#currentSeries}`,
@@ -278,31 +335,56 @@ module.exports = (client) => class ChartSession {
278
335
  * @param {'EUR' | 'USD' | string} [options.currency] Chart currency
279
336
  * @param {ChartType} [options.type] Chart custom type
280
337
  * @param {ChartInputs} [options.inputs] Chart custom inputs
338
+ * @param {number} [options.replay] Replay mode starting point (Timestamp)
281
339
  */
282
340
  setMarket(symbol, options = {}) {
283
341
  this.#periods = {};
284
342
 
343
+ if (this.#replayMode) {
344
+ this.#replayMode = false;
345
+ this.#client.send('replay_delete_session', [this.#replaySessionID]);
346
+ }
347
+
285
348
  const symbolInit = {
286
349
  symbol: symbol || 'BTCEUR',
287
350
  adjustment: options.adjustment || 'splits',
288
351
  };
289
352
 
290
353
  if (options.session) symbolInit.session = options.session;
291
-
292
354
  if (options.currency) symbolInit['currency-id'] = options.currency;
293
355
 
294
- const chartInit = (options.type && ChartTypes[options.type]) ? {} : symbolInit;
356
+ if (options.replay) {
357
+ this.#replayMode = true;
358
+ this.#client.send('replay_create_session', [this.#replaySessionID]);
359
+
360
+ this.#client.send('replay_add_series', [
361
+ this.#replaySessionID,
362
+ 'req_replay_addseries',
363
+ `=${JSON.stringify(symbolInit)}`,
364
+ options.timeframe,
365
+ ]);
366
+
367
+ this.#client.send('replay_reset', [
368
+ this.#replaySessionID,
369
+ 'req_replay_reset',
370
+ options.replay,
371
+ ]);
372
+ }
373
+
374
+ const complex = options.type || options.replay;
375
+ const chartInit = complex ? {} : symbolInit;
295
376
 
296
- if (options.type && ChartTypes[options.type]) {
377
+ if (complex) {
378
+ if (options.replay) chartInit.replay = this.#replaySessionID;
297
379
  chartInit.symbol = symbolInit;
298
380
  chartInit.type = ChartTypes[options.type];
299
- chartInit.inputs = { ...options.inputs };
381
+ if (options.type) chartInit.inputs = { ...options.inputs };
300
382
  }
301
383
 
302
384
  this.#currentSeries += 1;
303
385
 
304
386
  this.#client.send('resolve_symbol', [
305
- this.#sessionID,
387
+ this.#chartSessionID,
306
388
  `ser_${this.#currentSeries}`,
307
389
  `=${JSON.stringify(chartInit)}`,
308
390
  ]);
@@ -316,7 +398,7 @@ module.exports = (client) => class ChartSession {
316
398
  */
317
399
  setTimezone(timezone) {
318
400
  this.#periods = {};
319
- this.#client.send('switch_timezone', [this.#sessionID, timezone]);
401
+ this.#client.send('switch_timezone', [this.#chartSessionID, timezone]);
320
402
  }
321
403
 
322
404
  /**
@@ -324,7 +406,60 @@ module.exports = (client) => class ChartSession {
324
406
  * @param {number} number Number of additional periods/candles you want to fetch
325
407
  */
326
408
  fetchMore(number = 1) {
327
- this.#client.send('request_more_data', [this.#sessionID, '$prices', number]);
409
+ this.#client.send('request_more_data', [this.#chartSessionID, '$prices', number]);
410
+ }
411
+
412
+ /**
413
+ * Fetch x additional previous periods/candles values
414
+ * @param {number} number Number of additional periods/candles you want to fetch
415
+ * @returns {Promise} Raise when the data has been fetched
416
+ */
417
+ replayStep(number = 1) {
418
+ return new Promise((cb) => {
419
+ if (!this.#replayMode) {
420
+ this.#handleError('No replay session');
421
+ return;
422
+ }
423
+
424
+ const reqID = genSessionID('rsq_step');
425
+ this.#client.send('replay_step', [this.#replaySessionID, reqID, number]);
426
+ this.#replayOKCB[reqID] = () => { cb(); };
427
+ });
428
+ }
429
+
430
+ /**
431
+ * Start fetching a new period/candle every x ms
432
+ * @param {number} interval Number of additional periods/candles you want to fetch
433
+ * @returns {Promise} Raise when the replay mode starts
434
+ */
435
+ replayStart(interval = 1000) {
436
+ return new Promise((cb) => {
437
+ if (!this.#replayMode) {
438
+ this.#handleError('No replay session');
439
+ return;
440
+ }
441
+
442
+ const reqID = genSessionID('rsq_start');
443
+ this.#client.send('replay_start', [this.#replaySessionID, reqID, interval]);
444
+ this.#replayOKCB[reqID] = () => { cb(); };
445
+ });
446
+ }
447
+
448
+ /**
449
+ * Stop fetching a new period/candle every x ms
450
+ * @returns {Promise} Raise when the replay mode stops
451
+ */
452
+ replayStop() {
453
+ return new Promise((cb) => {
454
+ if (!this.#replayMode) {
455
+ this.#handleError('No replay session');
456
+ return;
457
+ }
458
+
459
+ const reqID = genSessionID('rsq_stop');
460
+ this.#client.send('replay_stop', [this.#replaySessionID, reqID]);
461
+ this.#replayOKCB[reqID] = () => { cb(); };
462
+ });
328
463
  }
329
464
 
330
465
  /**
@@ -338,13 +473,52 @@ module.exports = (client) => class ChartSession {
338
473
 
339
474
  /**
340
475
  * When a chart update happens
341
- * @param {() => void} cb
476
+ * @param {(changes: ('$prices' | string)[]) => void} cb
342
477
  * @event
343
478
  */
344
479
  onUpdate(cb) {
345
480
  this.#callbacks.update.push(cb);
346
481
  }
347
482
 
483
+ /**
484
+ * When the replay session is ready
485
+ * @param {() => void} cb
486
+ * @event
487
+ */
488
+ onReplayLoaded(cb) {
489
+ this.#callbacks.replayLoaded.push(cb);
490
+ }
491
+
492
+ /**
493
+ * When the replay session has new resolution
494
+ * @param {(
495
+ * timeframe: import('../types').TimeFrame,
496
+ * index: number,
497
+ * ) => void} cb
498
+ * @event
499
+ */
500
+ onReplayResolution(cb) {
501
+ this.#callbacks.replayResolution.push(cb);
502
+ }
503
+
504
+ /**
505
+ * When the replay session ends
506
+ * @param {() => void} cb
507
+ * @event
508
+ */
509
+ onReplayEnd(cb) {
510
+ this.#callbacks.replayEnd.push(cb);
511
+ }
512
+
513
+ /**
514
+ * When the replay session cursor has moved
515
+ * @param {(index: number) => void} cb
516
+ * @event
517
+ */
518
+ onReplayPoint(cb) {
519
+ this.#callbacks.replayPoint.push(cb);
520
+ }
521
+
348
522
  /**
349
523
  * When chart error happens
350
524
  * @param {(...any) => void} cb Callback
@@ -356,7 +530,7 @@ module.exports = (client) => class ChartSession {
356
530
 
357
531
  /** @type {ChartSessionBridge} */
358
532
  #chartSession = {
359
- sessionID: this.#sessionID,
533
+ sessionID: this.#chartSessionID,
360
534
  studyListeners: this.#studyListeners,
361
535
  indexes: {},
362
536
  send: (t, p) => this.#client.send(t, p),
@@ -366,7 +540,9 @@ module.exports = (client) => class ChartSession {
366
540
 
367
541
  /** Delete the chart session */
368
542
  delete() {
369
- this.#client.send('quote_delete_session', [this.#sessionID]);
370
- delete this.#client.sessions[this.#sessionID];
543
+ if (this.#replayMode) this.#client.send('replay_delete_session', [this.#replaySessionID]);
544
+ this.#client.send('chart_delete_session', [this.#chartSessionID]);
545
+ delete this.#client.sessions[this.#chartSessionID];
546
+ this.#replayMode = false;
371
547
  }
372
548
  };
@@ -16,11 +16,11 @@ function getInputs(options) {
16
16
  if (options.pineId) pineInputs.pineId = options.pineId;
17
17
  if (options.pineVersion) pineInputs.pineVersion = options.pineVersion;
18
18
 
19
- Object.keys(options.inputs).forEach((inputID) => {
19
+ Object.keys(options.inputs).forEach((inputID, n) => {
20
20
  const input = options.inputs[inputID];
21
21
 
22
22
  pineInputs[inputID] = {
23
- v: input.value,
23
+ v: (input.type !== 'color') ? input.value : n,
24
24
  f: input.isFake,
25
25
  t: input.type,
26
26
  };
@@ -35,80 +35,80 @@ function getInputs(options) {
35
35
  /**
36
36
  * @typedef {Object} TradeReport Trade report
37
37
 
38
- * @property {Object} entry Trade entry
39
- * @property {string} entry.name Trade name
40
- * @property {'long' | 'short'} entry.type Entry type (long/short)
41
- * @property {number} entry.value Entry price value
42
- * @property {number} entry.time Entry timestamp
43
-
44
- * @property {Object} exit Trade exit
45
- * @property {'' | string} exit.name Trade name ('' if false exit)
46
- * @property {number} exit.value Exit price value
47
- * @property {number} exit.time Exit timestamp
48
-
49
- * @property {number} quantity Trade quantity
50
- * @property {RelAbsValue} profit Trade profit
51
- * @property {RelAbsValue} cumulative Trade cummulative profit
52
- * @property {RelAbsValue} runup Trade run-up
53
- * @property {RelAbsValue} drawdown Trade drawdown
38
+ * @prop {Object} entry Trade entry
39
+ * @prop {string} entry.name Trade name
40
+ * @prop {'long' | 'short'} entry.type Entry type (long/short)
41
+ * @prop {number} entry.value Entry price value
42
+ * @prop {number} entry.time Entry timestamp
43
+
44
+ * @prop {Object} exit Trade exit
45
+ * @prop {'' | string} exit.name Trade name ('' if false exit)
46
+ * @prop {number} exit.value Exit price value
47
+ * @prop {number} exit.time Exit timestamp
48
+
49
+ * @prop {number} quantity Trade quantity
50
+ * @prop {RelAbsValue} profit Trade profit
51
+ * @prop {RelAbsValue} cumulative Trade cummulative profit
52
+ * @prop {RelAbsValue} runup Trade run-up
53
+ * @prop {RelAbsValue} drawdown Trade drawdown
54
54
  */
55
55
 
56
56
  /**
57
57
  * @typedef {Object} PerfReport
58
- * @property {number} avgBarsInTrade Average bars in trade
59
- * @property {number} avgBarsInWinTrade Average bars in winning trade
60
- * @property {number} avgBarsInLossTrade Average bars in losing trade
61
- * @property {number} avgTrade Average trade gain
62
- * @property {number} avgTradePercent Average trade performace
63
- * @property {number} avgLosTrade Average losing trade gain
64
- * @property {number} avgLosTradePercent Average losing trade performace
65
- * @property {number} avgWinTrade Average winning trade gain
66
- * @property {number} avgWinTradePercent Average winning trade performace
67
- * @property {number} commissionPaid Commission paid
68
- * @property {number} grossLoss Gross loss value
69
- * @property {number} grossLossPercent Gross loss percent
70
- * @property {number} grossProfit Gross profit
71
- * @property {number} grossProfitPercent Gross profit percent
72
- * @property {number} largestLosTrade Largest losing trade gain
73
- * @property {number} largestLosTradePercent Largent losing trade performance (percentage)
74
- * @property {number} largestWinTrade Largest winning trade gain
75
- * @property {number} largestWinTradePercent Largest winning trade performance (percentage)
76
- * @property {number} marginCalls Margin calls
77
- * @property {number} maxContractsHeld Max Contracts Held
78
- * @property {number} netProfit Net profit
79
- * @property {number} netProfitPercent Net performance (percentage)
80
- * @property {number} numberOfLosingTrades Number of losing trades
81
- * @property {number} numberOfWiningTrades Number of winning trades
82
- * @property {number} percentProfitable Strategy winrate
83
- * @property {number} profitFactor Profit factor
84
- * @property {number} ratioAvgWinAvgLoss Ratio Average Win / Average Loss
85
- * @property {number} totalOpenTrades Total open trades
86
- * @property {number} totalTrades Total trades
58
+ * @prop {number} avgBarsInTrade Average bars in trade
59
+ * @prop {number} avgBarsInWinTrade Average bars in winning trade
60
+ * @prop {number} avgBarsInLossTrade Average bars in losing trade
61
+ * @prop {number} avgTrade Average trade gain
62
+ * @prop {number} avgTradePercent Average trade performace
63
+ * @prop {number} avgLosTrade Average losing trade gain
64
+ * @prop {number} avgLosTradePercent Average losing trade performace
65
+ * @prop {number} avgWinTrade Average winning trade gain
66
+ * @prop {number} avgWinTradePercent Average winning trade performace
67
+ * @prop {number} commissionPaid Commission paid
68
+ * @prop {number} grossLoss Gross loss value
69
+ * @prop {number} grossLossPercent Gross loss percent
70
+ * @prop {number} grossProfit Gross profit
71
+ * @prop {number} grossProfitPercent Gross profit percent
72
+ * @prop {number} largestLosTrade Largest losing trade gain
73
+ * @prop {number} largestLosTradePercent Largent losing trade performance (percentage)
74
+ * @prop {number} largestWinTrade Largest winning trade gain
75
+ * @prop {number} largestWinTradePercent Largest winning trade performance (percentage)
76
+ * @prop {number} marginCalls Margin calls
77
+ * @prop {number} maxContractsHeld Max Contracts Held
78
+ * @prop {number} netProfit Net profit
79
+ * @prop {number} netProfitPercent Net performance (percentage)
80
+ * @prop {number} numberOfLosingTrades Number of losing trades
81
+ * @prop {number} numberOfWiningTrades Number of winning trades
82
+ * @prop {number} percentProfitable Strategy winrate
83
+ * @prop {number} profitFactor Profit factor
84
+ * @prop {number} ratioAvgWinAvgLoss Ratio Average Win / Average Loss
85
+ * @prop {number} totalOpenTrades Total open trades
86
+ * @prop {number} totalTrades Total trades
87
87
  */
88
88
 
89
89
  /**
90
90
  * @typedef {Object} StrategyReport
91
- * @property {'EUR' | 'USD' | 'JPY' | '' | 'CHF'} [currency] Selected currency
92
- * @property {TradeReport[]} trades Trade list starting by the last
93
- * @property {Object} history History Chart value
94
- * @property {number[]} [history.buyHold] Buy hold values
95
- * @property {number[]} [history.buyHoldPercent] Buy hold percent values
96
- * @property {number[]} [history.drawDown] Drawdown values
97
- * @property {number[]} [history.drawDownPercent] Drawdown percent values
98
- * @property {number[]} [history.equity] Equity values
99
- * @property {number[]} [history.equityPercent] Equity percent values
100
- * @property {Object} performance Strategy performance
101
- * @property {PerfReport} [performance.all] Strategy long/short performances
102
- * @property {PerfReport} [performance.long] Strategy long performances
103
- * @property {PerfReport} [performance.short] Strategy short performances
104
- * @property {number} [performance.buyHoldReturn] Strategy Buy & Hold Return
105
- * @property {number} [performance.buyHoldReturnPercent] Strategy Buy & Hold Return percent
106
- * @property {number} [performance.maxDrawDown] Strategy max drawdown
107
- * @property {number} [performance.maxDrawDownPercent] Strategy max drawdown percent
108
- * @property {number} [performance.openPL] Strategy Open P&L (Profit And Loss)
109
- * @property {number} [performance.openPLPercent] Strategy Open P&L (Profit And Loss) percent
110
- * @property {number} [performance.sharpeRatio] Strategy Sharpe Ratio
111
- * @property {number} [performance.sortinoRatio] Strategy Sortino Ratio
91
+ * @prop {'EUR' | 'USD' | 'JPY' | '' | 'CHF'} [currency] Selected currency
92
+ * @prop {TradeReport[]} trades Trade list starting by the last
93
+ * @prop {Object} history History Chart value
94
+ * @prop {number[]} [history.buyHold] Buy hold values
95
+ * @prop {number[]} [history.buyHoldPercent] Buy hold percent values
96
+ * @prop {number[]} [history.drawDown] Drawdown values
97
+ * @prop {number[]} [history.drawDownPercent] Drawdown percent values
98
+ * @prop {number[]} [history.equity] Equity values
99
+ * @prop {number[]} [history.equityPercent] Equity percent values
100
+ * @prop {Object} performance Strategy performance
101
+ * @prop {PerfReport} [performance.all] Strategy long/short performances
102
+ * @prop {PerfReport} [performance.long] Strategy long performances
103
+ * @prop {PerfReport} [performance.short] Strategy short performances
104
+ * @prop {number} [performance.buyHoldReturn] Strategy Buy & Hold Return
105
+ * @prop {number} [performance.buyHoldReturnPercent] Strategy Buy & Hold Return percent
106
+ * @prop {number} [performance.maxDrawDown] Strategy max drawdown
107
+ * @prop {number} [performance.maxDrawDownPercent] Strategy max drawdown percent
108
+ * @prop {number} [performance.openPL] Strategy Open P&L (Profit And Loss)
109
+ * @prop {number} [performance.openPLPercent] Strategy Open P&L (Profit And Loss) percent
110
+ * @prop {number} [performance.sharpeRatio] Strategy Sharpe Ratio
111
+ * @prop {number} [performance.sortinoRatio] Strategy Sortino Ratio
112
112
  */
113
113
 
114
114
  /**
@@ -68,6 +68,7 @@ const defaultValues = {
68
68
  },
69
69
  };
70
70
 
71
+ /** @class */
71
72
  module.exports = class BuiltInIndicator {
72
73
  /** @type {BuiltInIndicatorType} */
73
74
  #type;
@@ -4,7 +4,9 @@
4
4
  * @property {string} inline Input inline name
5
5
  * @property {string} [internalID] Input internal ID
6
6
  * @property {string} [tooltip] Input tooltip
7
- * @property {'text' | 'source' | 'integer' | 'float' | 'resolution' | 'bool'} type Input type
7
+ * @property {'text' | 'source' | 'integer'
8
+ * | 'float' | 'resolution' | 'bool' | 'color'
9
+ * } type Input type
8
10
  * @property {string | number | boolean} value Input default value
9
11
  * @property {boolean} isHidden If the input is hidden
10
12
  * @property {boolean} isFake If the input is fake
@@ -26,6 +28,8 @@
26
28
  * @typedef {'Script@tv-scripting-101!'
27
29
  * | 'StrategyScript@tv-scripting-101!'} IndicatorType Indicator type
28
30
  */
31
+
32
+ /** @class */
29
33
  module.exports = class PineIndicator {
30
34
  #options;
31
35
 
@@ -113,12 +117,8 @@ module.exports = class PineIndicator {
113
117
  text: 'String',
114
118
  };
115
119
 
116
- if (
117
- (input.type === 'bool' && typeof value !== 'boolean')
118
- || (input.type === 'integer' && typeof value !== 'number')
119
- || (input.type === 'float' && typeof value !== 'number')
120
- || (input.type === 'text' && typeof value !== 'string')
121
- ) {
120
+ // eslint-disable-next-line valid-typeof
121
+ if (types[input.type] && typeof value !== types[input.type].toLowerCase()) {
122
122
  throw new Error(`Input '${input.name}' (${propI}) must be a ${types[input.type]} !`);
123
123
  }
124
124