@mathieuc/tradingview 3.5.2 → 4.0.0-beta.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 (120) hide show
  1. package/README.md +112 -51
  2. package/dist/chart/chart-session.d.ts +114 -0
  3. package/dist/chart/chart-session.js +339 -0
  4. package/dist/chart/graphics.d.ts +129 -0
  5. package/dist/chart/graphics.js +153 -0
  6. package/dist/chart/index.d.ts +11 -0
  7. package/dist/chart/index.js +6 -0
  8. package/dist/chart/strategy.d.ts +113 -0
  9. package/dist/chart/strategy.js +78 -0
  10. package/dist/chart/study.d.ts +60 -0
  11. package/dist/chart/study.js +179 -0
  12. package/dist/chart/timeframes.d.ts +7 -0
  13. package/dist/chart/timeframes.js +22 -0
  14. package/dist/chart/types.d.ts +105 -0
  15. package/dist/chart/types.js +9 -0
  16. package/dist/client/client.d.ts +89 -0
  17. package/dist/client/client.js +254 -0
  18. package/dist/client/index.d.ts +4 -0
  19. package/dist/client/index.js +2 -0
  20. package/dist/client/transport.d.ts +27 -0
  21. package/dist/client/transport.js +38 -0
  22. package/dist/data/candles.d.ts +40 -0
  23. package/dist/data/candles.js +101 -0
  24. package/dist/data/history.d.ts +61 -0
  25. package/dist/data/history.js +101 -0
  26. package/dist/data/index.d.ts +30 -0
  27. package/dist/data/index.js +16 -0
  28. package/dist/data/indicators.d.ts +54 -0
  29. package/dist/data/indicators.js +139 -0
  30. package/dist/data/operation.d.ts +71 -0
  31. package/dist/data/operation.js +205 -0
  32. package/dist/data/provider.d.ts +23 -0
  33. package/dist/data/provider.js +11 -0
  34. package/dist/data/quotes.d.ts +33 -0
  35. package/dist/data/quotes.js +117 -0
  36. package/dist/data/symbols.d.ts +9 -0
  37. package/dist/data/symbols.js +19 -0
  38. package/dist/errors.d.ts +53 -0
  39. package/dist/errors.js +24 -0
  40. package/dist/events.d.ts +36 -0
  41. package/dist/events.js +70 -0
  42. package/dist/http/account.d.ts +47 -0
  43. package/dist/http/account.js +127 -0
  44. package/dist/http/index.d.ts +11 -0
  45. package/dist/http/index.js +5 -0
  46. package/dist/http/indicators.d.ts +37 -0
  47. package/dist/http/indicators.js +144 -0
  48. package/dist/http/layouts.d.ts +36 -0
  49. package/dist/http/layouts.js +24 -0
  50. package/dist/http/market.d.ts +45 -0
  51. package/dist/http/market.js +59 -0
  52. package/dist/http/pine-permissions.d.ts +29 -0
  53. package/dist/http/pine-permissions.js +56 -0
  54. package/dist/http/request.d.ts +44 -0
  55. package/dist/http/request.js +83 -0
  56. package/dist/index.d.ts +21 -0
  57. package/dist/index.js +19 -0
  58. package/dist/indicators/builtin-indicator.d.ts +17 -0
  59. package/dist/indicators/builtin-indicator.js +75 -0
  60. package/dist/indicators/index.d.ts +8 -0
  61. package/dist/indicators/index.js +2 -0
  62. package/dist/indicators/pine-indicator.d.ts +63 -0
  63. package/dist/indicators/pine-indicator.js +101 -0
  64. package/dist/protocol/compression.d.ts +12 -0
  65. package/dist/protocol/compression.js +83 -0
  66. package/dist/protocol/framing.d.ts +59 -0
  67. package/dist/protocol/framing.js +68 -0
  68. package/dist/protocol/ids.d.ts +2 -0
  69. package/dist/protocol/ids.js +10 -0
  70. package/dist/protocol/index.d.ts +4 -0
  71. package/dist/protocol/index.js +3 -0
  72. package/dist/quote/fields.d.ts +35 -0
  73. package/dist/quote/fields.js +21 -0
  74. package/dist/quote/index.d.ts +4 -0
  75. package/dist/quote/index.js +2 -0
  76. package/dist/quote/quote-session.d.ts +73 -0
  77. package/dist/quote/quote-session.js +205 -0
  78. package/docs/README.es.md +58 -0
  79. package/docs/README.fr.md +58 -0
  80. package/docs/README.pt.md +58 -0
  81. package/docs/data-api.md +285 -0
  82. package/docs/low-level-api.md +213 -0
  83. package/docs/migration-v4.md +128 -0
  84. package/docs/release-4.0.0-beta.1.md +39 -0
  85. package/docs/v4-coverage.md +213 -0
  86. package/package.json +53 -20
  87. package/.env.sample +0 -2
  88. package/.eslintrc.js +0 -28
  89. package/.gitattributes +0 -2
  90. package/docs/DOCS.md +0 -3
  91. package/examples/AllPrivateIndicators.js +0 -44
  92. package/examples/BuiltInIndicator.js +0 -51
  93. package/examples/CustomChartType.js +0 -123
  94. package/examples/CustomTimeframe.js +0 -31
  95. package/examples/Errors.js +0 -155
  96. package/examples/FakeReplayMode.js +0 -40
  97. package/examples/FromToData.js +0 -35
  98. package/examples/GetDrawings.js +0 -27
  99. package/examples/GraphicIndicator.js +0 -42
  100. package/examples/MultipleSyncFetch.js +0 -44
  101. package/examples/PinePermManage.js +0 -67
  102. package/examples/ReplayMode.js +0 -103
  103. package/examples/Search.js +0 -14
  104. package/examples/SimpleChart.js +0 -63
  105. package/examples/UserLogin.js +0 -16
  106. package/main.js +0 -11
  107. package/src/chart/graphicParser.js +0 -308
  108. package/src/chart/session.js +0 -553
  109. package/src/chart/study.js +0 -435
  110. package/src/classes/BuiltInIndicator.js +0 -137
  111. package/src/classes/PineIndicator.js +0 -132
  112. package/src/classes/PinePermManager.js +0 -159
  113. package/src/client.js +0 -298
  114. package/src/miscRequests.js +0 -609
  115. package/src/protocol.js +0 -60
  116. package/src/quote/market.js +0 -132
  117. package/src/quote/session.js +0 -125
  118. package/src/types.js +0 -36
  119. package/src/utils.js +0 -20
  120. package/vite.config.js +0 -7
@@ -1,435 +0,0 @@
1
- const { genSessionID } = require('../utils');
2
- const { parseCompressed } = require('../protocol');
3
- const graphicParser = require('./graphicParser');
4
-
5
- const PineIndicator = require('../classes/PineIndicator');
6
- const BuiltInIndicator = require('../classes/BuiltInIndicator');
7
-
8
- /**
9
- * Get pine inputs
10
- * @param {PineIndicator | BuiltInIndicator} options
11
- */
12
- function getInputs(options) {
13
- if (options instanceof PineIndicator) {
14
- const pineInputs = { text: options.script };
15
-
16
- if (options.pineId) pineInputs.pineId = options.pineId;
17
- if (options.pineVersion) pineInputs.pineVersion = options.pineVersion;
18
-
19
- Object.keys(options.inputs).forEach((inputID, n) => {
20
- const input = options.inputs[inputID];
21
-
22
- pineInputs[inputID] = {
23
- v: (input.type !== 'color') ? input.value : n,
24
- f: input.isFake,
25
- t: input.type,
26
- };
27
- });
28
-
29
- return pineInputs;
30
- }
31
-
32
- return options.options;
33
- }
34
-
35
- const parseTrades = (trades) => trades.reverse().map((t) => ({
36
- entry: {
37
- name: t.e.c,
38
- type: (t.e.tp[0] === 's' ? 'short' : 'long'),
39
- value: t.e.p,
40
- time: t.e.tm,
41
- },
42
- exit: {
43
- name: t.x.c,
44
- value: t.x.p,
45
- time: t.x.tm,
46
- },
47
- quantity: t.q,
48
- profit: t.tp,
49
- cumulative: t.cp,
50
- runup: t.rn,
51
- drawdown: t.dd,
52
- }));
53
-
54
- // const historyParser = (history) => history.reverse().map((h) => ({
55
-
56
- /**
57
- * @typedef {Object} TradeReport Trade report
58
-
59
- * @prop {Object} entry Trade entry
60
- * @prop {string} entry.name Trade name
61
- * @prop {'long' | 'short'} entry.type Entry type (long/short)
62
- * @prop {number} entry.value Entry price value
63
- * @prop {number} entry.time Entry timestamp
64
-
65
- * @prop {Object} exit Trade exit
66
- * @prop {'' | string} exit.name Trade name ('' if false exit)
67
- * @prop {number} exit.value Exit price value
68
- * @prop {number} exit.time Exit timestamp
69
-
70
- * @prop {number} quantity Trade quantity
71
- * @prop {RelAbsValue} profit Trade profit
72
- * @prop {RelAbsValue} cumulative Trade cummulative profit
73
- * @prop {RelAbsValue} runup Trade run-up
74
- * @prop {RelAbsValue} drawdown Trade drawdown
75
- */
76
-
77
- /**
78
- * @typedef {Object} PerfReport
79
- * @prop {number} avgBarsInTrade Average bars in trade
80
- * @prop {number} avgBarsInWinTrade Average bars in winning trade
81
- * @prop {number} avgBarsInLossTrade Average bars in losing trade
82
- * @prop {number} avgTrade Average trade gain
83
- * @prop {number} avgTradePercent Average trade performace
84
- * @prop {number} avgLosTrade Average losing trade gain
85
- * @prop {number} avgLosTradePercent Average losing trade performace
86
- * @prop {number} avgWinTrade Average winning trade gain
87
- * @prop {number} avgWinTradePercent Average winning trade performace
88
- * @prop {number} commissionPaid Commission paid
89
- * @prop {number} grossLoss Gross loss value
90
- * @prop {number} grossLossPercent Gross loss percent
91
- * @prop {number} grossProfit Gross profit
92
- * @prop {number} grossProfitPercent Gross profit percent
93
- * @prop {number} largestLosTrade Largest losing trade gain
94
- * @prop {number} largestLosTradePercent Largent losing trade performance (percentage)
95
- * @prop {number} largestWinTrade Largest winning trade gain
96
- * @prop {number} largestWinTradePercent Largest winning trade performance (percentage)
97
- * @prop {number} marginCalls Margin calls
98
- * @prop {number} maxContractsHeld Max Contracts Held
99
- * @prop {number} netProfit Net profit
100
- * @prop {number} netProfitPercent Net performance (percentage)
101
- * @prop {number} numberOfLosingTrades Number of losing trades
102
- * @prop {number} numberOfWiningTrades Number of winning trades
103
- * @prop {number} percentProfitable Strategy winrate
104
- * @prop {number} profitFactor Profit factor
105
- * @prop {number} ratioAvgWinAvgLoss Ratio Average Win / Average Loss
106
- * @prop {number} totalOpenTrades Total open trades
107
- * @prop {number} totalTrades Total trades
108
- */
109
-
110
- /**
111
- * @typedef {Object} FromTo
112
- * @prop {number} from From timestamp
113
- * @prop {number} to To timestamp
114
- */
115
-
116
- /**
117
- * @typedef {Object} StrategyReport
118
- * @prop {'EUR' | 'USD' | 'JPY' | '' | 'CHF'} [currency] Selected currency
119
- * @prop {Object} [settings] Backtester settings
120
- * @prop {Object} [settings.dateRange] Backtester date range
121
- * @prop {FromTo} [settings.dateRange.backtest] Date range for backtest
122
- * @prop {FromTo} [settings.dateRange.trade] Date range for trade
123
- * @prop {TradeReport[]} trades Trade list starting by the last
124
- * @prop {Object} history History Chart value
125
- * @prop {number[]} [history.buyHold] Buy hold values
126
- * @prop {number[]} [history.buyHoldPercent] Buy hold percent values
127
- * @prop {number[]} [history.drawDown] Drawdown values
128
- * @prop {number[]} [history.drawDownPercent] Drawdown percent values
129
- * @prop {number[]} [history.equity] Equity values
130
- * @prop {number[]} [history.equityPercent] Equity percent values
131
- * @prop {Object} performance Strategy performance
132
- * @prop {PerfReport} [performance.all] Strategy long/short performances
133
- * @prop {PerfReport} [performance.long] Strategy long performances
134
- * @prop {PerfReport} [performance.short] Strategy short performances
135
- * @prop {number} [performance.buyHoldReturn] Strategy Buy & Hold Return
136
- * @prop {number} [performance.buyHoldReturnPercent] Strategy Buy & Hold Return percent
137
- * @prop {number} [performance.maxDrawDown] Strategy max drawdown
138
- * @prop {number} [performance.maxDrawDownPercent] Strategy max drawdown percent
139
- * @prop {number} [performance.openPL] Strategy Open P&L (Profit And Loss)
140
- * @prop {number} [performance.openPLPercent] Strategy Open P&L (Profit And Loss) percent
141
- * @prop {number} [performance.sharpeRatio] Strategy Sharpe Ratio
142
- * @prop {number} [performance.sortinoRatio] Strategy Sortino Ratio
143
- */
144
-
145
- /**
146
- * @param {import('./session').ChartSessionBridge} chartSession
147
- */
148
- module.exports = (chartSession) => class ChartStudy {
149
- #studID = genSessionID('st');
150
-
151
- #studyListeners = chartSession.studyListeners;
152
-
153
- /**
154
- * Table of periods values indexed by timestamp
155
- * @type {Object<number, {}[]>}
156
- */
157
- #periods = {};
158
-
159
- /** @return {{}[]} List of periods values */
160
- get periods() {
161
- return Object.values(this.#periods).sort((a, b) => b.$time - a.$time);
162
- }
163
-
164
- /**
165
- * List of graphic xPos indexes
166
- * @type {number[]}
167
- */
168
- #indexes = [];
169
-
170
- /**
171
- * Table of graphic drawings indexed by type and ID
172
- * @type {Object<string, Object<number, {}>>}
173
- */
174
- #graphic = {};
175
-
176
- /**
177
- * Table of graphic drawings indexed by type
178
- * @return {import('./graphicParser').GraphicData}
179
- */
180
- get graphic() {
181
- const translator = {};
182
-
183
- Object.keys(chartSession.indexes)
184
- .sort((a, b) => chartSession.indexes[b] - chartSession.indexes[a])
185
- .forEach((r, n) => { translator[r] = n; });
186
-
187
- const indexes = this.#indexes.map((i) => translator[i]);
188
- return graphicParser(this.#graphic, indexes);
189
- }
190
-
191
- /** @type {StrategyReport} */
192
- #strategyReport = {
193
- trades: [],
194
- history: {},
195
- performance: {},
196
- };
197
-
198
- /** @return {StrategyReport} Get the strategy report if available */
199
- get strategyReport() {
200
- return this.#strategyReport;
201
- }
202
-
203
- #callbacks = {
204
- studyCompleted: [],
205
- update: [],
206
-
207
- event: [],
208
- error: [],
209
- };
210
-
211
- /**
212
- * @param {ChartEvent} ev Client event
213
- * @param {...{}} data Packet data
214
- */
215
- #handleEvent(ev, ...data) {
216
- this.#callbacks[ev].forEach((e) => e(...data));
217
- this.#callbacks.event.forEach((e) => e(ev, ...data));
218
- }
219
-
220
- #handleError(...msgs) {
221
- if (this.#callbacks.error.length === 0) console.error(...msgs);
222
- else this.#handleEvent('error', ...msgs);
223
- }
224
-
225
- /**
226
- * @param {PineIndicator | BuiltInIndicator} indicator Indicator object instance
227
- */
228
- constructor(indicator) {
229
- if (!(indicator instanceof PineIndicator) && !(indicator instanceof BuiltInIndicator)) {
230
- throw new Error(`Indicator argument must be an instance of PineIndicator or BuiltInIndicator.
231
- Please use 'TradingView.getIndicator(...)' function.`);
232
- }
233
-
234
- /** @type {PineIndicator | BuiltInIndicator} Indicator instance */
235
- this.instance = indicator;
236
-
237
- this.#studyListeners[this.#studID] = async (packet) => {
238
- if (global.TW_DEBUG) console.log('§90§30§105 STUDY §0 DATA', packet);
239
-
240
- if (packet.type === 'study_completed') {
241
- this.#handleEvent('studyCompleted');
242
- return;
243
- }
244
-
245
- if (['timescale_update', 'du'].includes(packet.type)) {
246
- const changes = [];
247
- const data = packet.data[1][this.#studID];
248
-
249
- if (data && data.st && data.st[0]) {
250
- data.st.forEach((p) => {
251
- const period = {};
252
-
253
- p.v.forEach((plot, i) => {
254
- if (!this.instance.plots) {
255
- period[i === 0 ? '$time' : `plot_${i - 1}`] = plot;
256
- return;
257
- }
258
- const plotName = (i === 0 ? '$time' : this.instance.plots[`plot_${i - 1}`]);
259
- if (plotName && !period[plotName]) period[plotName] = plot;
260
- else period[`plot_${i - 1}`] = plot;
261
- });
262
-
263
- this.#periods[p.v[0]] = period;
264
- });
265
-
266
- changes.push('plots');
267
- }
268
-
269
- if (data.ns && data.ns.d) {
270
- const parsed = JSON.parse(data.ns.d);
271
-
272
- if (parsed.graphicsCmds) {
273
- if (parsed.graphicsCmds.erase) {
274
- parsed.graphicsCmds.erase.forEach((instruction) => {
275
- // console.log('Erase', instruction);
276
- if (instruction.action === 'all') {
277
- if (!instruction.type) {
278
- Object.keys(this.#graphic).forEach((drawType) => {
279
- this.#graphic[drawType] = {};
280
- });
281
- } else delete this.#graphic[instruction.type];
282
- return;
283
- }
284
-
285
- if (instruction.action === 'one') {
286
- delete this.#graphic[instruction.type][instruction.id];
287
- }
288
- // Can an 'instruction' contains other things ?
289
- });
290
- }
291
-
292
- if (parsed.graphicsCmds.create) {
293
- Object.keys(parsed.graphicsCmds.create).forEach((drawType) => {
294
- if (!this.#graphic[drawType]) this.#graphic[drawType] = {};
295
- parsed.graphicsCmds.create[drawType].forEach((group) => {
296
- group.data.forEach((item) => {
297
- this.#graphic[drawType][item.id] = item;
298
- });
299
- });
300
- });
301
- }
302
-
303
- // console.log('graphicsCmds', Object.keys(parsed.graphicsCmds));
304
- // Can 'graphicsCmds' contains other things ?
305
-
306
- changes.push('graphic');
307
- }
308
-
309
- const updateStrategyReport = (report) => {
310
- if (report.currency) {
311
- this.#strategyReport.currency = report.currency;
312
- changes.push('report.currency');
313
- }
314
-
315
- if (report.settings) {
316
- this.#strategyReport.settings = report.settings;
317
- changes.push('report.settings');
318
- }
319
-
320
- if (report.performance) {
321
- this.#strategyReport.performance = report.performance;
322
- changes.push('report.perf');
323
- }
324
-
325
- if (report.trades) {
326
- this.#strategyReport.trades = parseTrades(report.trades);
327
- changes.push('report.trades');
328
- }
329
-
330
- if (report.equity) {
331
- this.#strategyReport.history = {
332
- buyHold: report.buyHold,
333
- buyHoldPercent: report.buyHoldPercent,
334
- drawDown: report.drawDown,
335
- drawDownPercent: report.drawDownPercent,
336
- equity: report.equity,
337
- equityPercent: report.equityPercent,
338
- };
339
- changes.push('report.history');
340
- }
341
- };
342
-
343
- if (parsed.dataCompressed) {
344
- updateStrategyReport((await parseCompressed(parsed.dataCompressed)).report);
345
- }
346
-
347
- if (parsed.data && parsed.data.report) updateStrategyReport(parsed.data.report);
348
- }
349
-
350
- if (data.ns.indexes && typeof data.ns.indexes === 'object') {
351
- this.#indexes = data.ns.indexes;
352
- }
353
-
354
- this.#handleEvent('update', changes);
355
- return;
356
- }
357
-
358
- if (packet.type === 'study_error') {
359
- this.#handleError(packet.data[3], packet.data[4]);
360
- }
361
- };
362
-
363
- chartSession.send('create_study', [
364
- chartSession.sessionID,
365
- `${this.#studID}`,
366
- 'st1',
367
- '$prices',
368
- this.instance.type,
369
- getInputs(this.instance),
370
- ]);
371
- }
372
-
373
- /**
374
- * @param {PineIndicator | BuiltInIndicator} indicator Indicator instance
375
- */
376
- setIndicator(indicator) {
377
- if (!(indicator instanceof PineIndicator) && !(indicator instanceof BuiltInIndicator)) {
378
- throw new Error(`Indicator argument must be an instance of PineIndicator or BuiltInIndicator.
379
- Please use 'TradingView.getIndicator(...)' function.`);
380
- }
381
-
382
- this.instance = indicator;
383
-
384
- chartSession.send('modify_study', [
385
- chartSession.sessionID,
386
- `${this.#studID}`,
387
- 'st1',
388
- getInputs(this.instance),
389
- ]);
390
- }
391
-
392
- /**
393
- * When the indicator is ready
394
- * @param {() => void} cb
395
- * @event
396
- */
397
- onReady(cb) {
398
- this.#callbacks.studyCompleted.push(cb);
399
- }
400
-
401
- /**
402
- * @typedef {'plots' | 'report.currency'
403
- * | 'report.settings' | 'report.perf'
404
- * | 'report.trades' | 'report.history'
405
- * | 'graphic'
406
- * } UpdateChangeType
407
- */
408
-
409
- /**
410
- * When an indicator update happens
411
- * @param {(changes: UpdateChangeType[]) => void} cb
412
- * @event
413
- */
414
- onUpdate(cb) {
415
- this.#callbacks.update.push(cb);
416
- }
417
-
418
- /**
419
- * When indicator error happens
420
- * @param {(...any) => void} cb Callback
421
- * @event
422
- */
423
- onError(cb) {
424
- this.#callbacks.error.push(cb);
425
- }
426
-
427
- /** Remove the study */
428
- remove() {
429
- chartSession.send('remove_study', [
430
- chartSession.sessionID,
431
- this.#studID,
432
- ]);
433
- delete this.#studyListeners[this.#studID];
434
- }
435
- };
@@ -1,137 +0,0 @@
1
- /**
2
- * @typedef {'Volume@tv-basicstudies-241'
3
- * | 'VbPFixed@tv-basicstudies-241'
4
- * | 'VbPFixed@tv-basicstudies-241!'
5
- * | 'VbPFixed@tv-volumebyprice-53!'
6
- * | 'VbPSessions@tv-volumebyprice-53'
7
- * | 'VbPSessionsRough@tv-volumebyprice-53!'
8
- * | 'VbPSessionsDetailed@tv-volumebyprice-53!'
9
- * | 'VbPVisible@tv-volumebyprice-53'} BuiltInIndicatorType Built-in indicator type
10
- */
11
-
12
- /**
13
- * @typedef {'rowsLayout' | 'rows' | 'volume'
14
- * | 'vaVolume' | 'subscribeRealtime'
15
- * | 'first_bar_time' | 'first_visible_bar_time'
16
- * | 'last_bar_time' | 'last_visible_bar_time'
17
- * | 'extendPocRight'} BuiltInIndicatorOption Built-in indicator Option
18
- */
19
-
20
- const defaultValues = {
21
- 'Volume@tv-basicstudies-241': {
22
- length: 20,
23
- col_prev_close: false,
24
- },
25
- 'VbPFixed@tv-basicstudies-241': {
26
- rowsLayout: 'Number Of Rows',
27
- rows: 24,
28
- volume: 'Up/Down',
29
- vaVolume: 70,
30
- subscribeRealtime: false,
31
- first_bar_time: NaN,
32
- last_bar_time: Date.now(),
33
- extendToRight: false,
34
- mapRightBoundaryToBarStartTime: true,
35
- },
36
- 'VbPFixed@tv-basicstudies-241!': {
37
- rowsLayout: 'Number Of Rows',
38
- rows: 24,
39
- volume: 'Up/Down',
40
- vaVolume: 70,
41
- subscribeRealtime: false,
42
- first_bar_time: NaN,
43
- last_bar_time: Date.now(),
44
- },
45
- 'VbPFixed@tv-volumebyprice-53!': {
46
- rowsLayout: 'Number Of Rows',
47
- rows: 24,
48
- volume: 'Up/Down',
49
- vaVolume: 70,
50
- subscribeRealtime: false,
51
- first_bar_time: NaN,
52
- last_bar_time: Date.now(),
53
- },
54
- 'VbPSessions@tv-volumebyprice-53': {
55
- rowsLayout: 'Number Of Rows',
56
- rows: 24,
57
- volume: 'Up/Down',
58
- vaVolume: 70,
59
- extendPocRight: false,
60
- },
61
- 'VbPSessionsRough@tv-volumebyprice-53!': {
62
- volume: 'Up/Down',
63
- vaVolume: 70,
64
- },
65
- 'VbPSessionsDetailed@tv-volumebyprice-53!': {
66
- volume: 'Up/Down',
67
- vaVolume: 70,
68
- subscribeRealtime: false,
69
- first_visible_bar_time: NaN,
70
- last_visible_bar_time: Date.now(),
71
- },
72
- 'VbPVisible@tv-volumebyprice-53': {
73
- rowsLayout: 'Number Of Rows',
74
- rows: 24,
75
- volume: 'Up/Down',
76
- vaVolume: 70,
77
- subscribeRealtime: false,
78
- first_visible_bar_time: NaN,
79
- last_visible_bar_time: Date.now(),
80
- },
81
- };
82
-
83
- /** @class */
84
- module.exports = class BuiltInIndicator {
85
- /** @type {BuiltInIndicatorType} */
86
- #type;
87
-
88
- /** @return {BuiltInIndicatorType} Indicator script */
89
- get type() {
90
- return this.#type;
91
- }
92
-
93
- /** @type {Object<string, any>} */
94
- #options = {};
95
-
96
- /** @return {Object<string, any>} Indicator script */
97
- get options() {
98
- return this.#options;
99
- }
100
-
101
- /**
102
- * @param {BuiltInIndicatorType} type Buit-in indocator raw type
103
- */
104
- constructor(type = '') {
105
- if (!type) throw new Error(`Wrong buit-in indicator type "${type}".`);
106
-
107
- this.#type = type;
108
- if (defaultValues[type]) this.#options = { ...defaultValues[type] };
109
- }
110
-
111
- /**
112
- * Set an option
113
- * @param {BuiltInIndicatorOption} key The option you want to change
114
- * @param {*} value The new value of the property
115
- * @param {boolean} FORCE Ignore type and key verifications
116
- */
117
- setOption(key, value, FORCE = false) {
118
- if (FORCE) {
119
- this.#options[key] = value;
120
- return;
121
- }
122
-
123
- if (defaultValues[this.#type] && defaultValues[this.#type][key] !== undefined) {
124
- const requiredType = typeof defaultValues[this.#type][key];
125
- const valType = typeof value;
126
- if (requiredType !== valType) {
127
- throw new Error(`Wrong '${key}' value type '${valType}' (must be '${requiredType}')`);
128
- }
129
- }
130
-
131
- if (defaultValues[this.#type] && defaultValues[this.#type][key] === undefined) {
132
- throw new Error(`Option '${key}' is denied with '${this.#type}' indicator`);
133
- }
134
-
135
- this.#options[key] = value;
136
- }
137
- };
@@ -1,132 +0,0 @@
1
- /**
2
- * @typedef {Object} IndicatorInput
3
- * @property {string} name Input name
4
- * @property {string} inline Input inline name
5
- * @property {string} [internalID] Input internal ID
6
- * @property {string} [tooltip] Input tooltip
7
- * @property {'text' | 'source' | 'integer'
8
- * | 'float' | 'resolution' | 'bool' | 'color'
9
- * } type Input type
10
- * @property {string | number | boolean} value Input default value
11
- * @property {boolean} isHidden If the input is hidden
12
- * @property {boolean} isFake If the input is fake
13
- * @property {string[]} [options] Input options if the input is a select
14
- */
15
-
16
- /**
17
- * @typedef {Object} Indicator
18
- * @property {string} pineId Indicator ID
19
- * @property {string} pineVersion Indicator version
20
- * @property {string} description Indicator description
21
- * @property {string} shortDescription Indicator short description
22
- * @property {Object<string, IndicatorInput>} inputs Indicator inputs
23
- * @property {Object<string, string>} plots Indicator plots
24
- * @property {string} script Indicator script
25
- */
26
-
27
- /**
28
- * @typedef {'Script@tv-scripting-101!'
29
- * | 'StrategyScript@tv-scripting-101!'} IndicatorType Indicator type
30
- */
31
-
32
- /** @class */
33
- module.exports = class PineIndicator {
34
- #options;
35
-
36
- /** @type {IndicatorType} */
37
- #type = 'Script@tv-scripting-101!';
38
-
39
- /** @param {Indicator} options Indicator */
40
- constructor(options) {
41
- this.#options = options;
42
- }
43
-
44
- /** @return {string} Indicator ID */
45
- get pineId() {
46
- return this.#options.pineId;
47
- }
48
-
49
- /** @return {string} Indicator version */
50
- get pineVersion() {
51
- return this.#options.pineVersion;
52
- }
53
-
54
- /** @return {string} Indicator description */
55
- get description() {
56
- return this.#options.description;
57
- }
58
-
59
- /** @return {string} Indicator short description */
60
- get shortDescription() {
61
- return this.#options.shortDescription;
62
- }
63
-
64
- /** @return {Object<string, IndicatorInput>} Indicator inputs */
65
- get inputs() {
66
- return this.#options.inputs;
67
- }
68
-
69
- /** @return {Object<string, string>} Indicator plots */
70
- get plots() {
71
- return this.#options.plots;
72
- }
73
-
74
- /** @return {IndicatorType} Indicator script */
75
- get type() {
76
- return this.#type;
77
- }
78
-
79
- /**
80
- * Set the indicator type
81
- * @param {IndicatorType} type Indicator type
82
- */
83
- setType(type = 'Script@tv-scripting-101!') {
84
- this.#type = type;
85
- }
86
-
87
- /** @return {string} Indicator script */
88
- get script() {
89
- return this.#options.script;
90
- }
91
-
92
- /**
93
- * Set an option
94
- * @param {number | string} key The key can be ID of the property (`in_{ID}`),
95
- * the inline name or the internalID.
96
- * @param {*} value The new value of the property
97
- */
98
- setOption(key, value) {
99
- let propI = '';
100
-
101
- if (this.#options.inputs[`in_${key}`]) propI = `in_${key}`;
102
- else if (this.#options.inputs[key]) propI = key;
103
- else {
104
- propI = Object.keys(this.#options.inputs).find((I) => (
105
- this.#options.inputs[I].inline === key
106
- || this.#options.inputs[I].internalID === key
107
- ));
108
- }
109
-
110
- if (propI && this.#options.inputs[propI]) {
111
- const input = this.#options.inputs[propI];
112
-
113
- const types = {
114
- bool: 'Boolean',
115
- integer: 'Number',
116
- float: 'Number',
117
- text: 'String',
118
- };
119
-
120
- // eslint-disable-next-line valid-typeof
121
- if (types[input.type] && typeof value !== types[input.type].toLowerCase()) {
122
- throw new Error(`Input '${input.name}' (${propI}) must be a ${types[input.type]} !`);
123
- }
124
-
125
- if (input.options && !input.options.includes(value)) {
126
- throw new Error(`Input '${input.name}' (${propI}) must be one of these values:`, input.options);
127
- }
128
-
129
- input.value = value;
130
- } else throw new Error(`Input '${key}' not found (${propI}).`);
131
- }
132
- };