@mathieuc/tradingview 2.0.5 → 3.0.0-pre
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/.eslintrc.js +18 -16
- package/.github/FUNDING.yml +1 -0
- package/README.md +26 -96
- package/examples/AllPrivateIndicators.js +35 -0
- package/examples/BuiltInIndicator.js +41 -0
- package/examples/CustomChartType.js +121 -0
- package/examples/CustomTimeframe.js +29 -0
- package/examples/Errors.js +153 -0
- package/examples/GraphicIndicator.js +44 -0
- package/examples/MultipleSyncFetch.js +38 -0
- package/examples/Search.js +15 -0
- package/examples/SimpleChart.js +63 -0
- package/examples/_RenkoIndicator.js +41 -0
- package/main.js +9 -337
- package/package.json +10 -2
- package/src/chart/graphicParser.js +110 -0
- package/src/chart/session.js +367 -0
- package/src/chart/study.js +403 -0
- package/src/classes/BuiltInIndicator.js +119 -0
- package/src/classes/PineIndicator.js +132 -0
- package/src/client.js +280 -0
- package/src/miscRequests.js +525 -0
- package/src/protocol.js +54 -0
- package/src/quote/market.js +123 -0
- package/src/quote/session.js +124 -0
- package/src/types.js +32 -0
- package/src/utils.js +8 -0
- package/test.js +155 -0
- package/tests/alerts/discordWH.js +76 -76
- package/tests/alerts/drawings.js +41 -0
- package/tests/alerts/envLoader.js +11 -11
- package/tests/alerts/manualAlert.js +77 -77
- package/tests/alerts/sentNotifs.js +16 -16
- package/tests/alerts/strategyAlert.js +94 -94
- package/tests/analysis.js +3 -3
- package/tests/indicator.js +42 -42
- package/tests/strategy.js +56 -0
- package/miscRequests.js +0 -285
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const TradingView = require('../main');
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
This example creates a BTCEUR daily chart
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const client = new TradingView.Client(); // Creates a websocket client
|
|
8
|
+
|
|
9
|
+
const chart = new client.Session.Chart(); // Init a Chart session
|
|
10
|
+
|
|
11
|
+
chart.setMarket('BINANCE:BTCEUR', { // Set the market
|
|
12
|
+
timeframe: 'D',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
chart.onError((...err) => { // Listen for errors (can avoid crash)
|
|
16
|
+
console.error('Chart error:', ...err);
|
|
17
|
+
// Do something...
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
chart.onSymbolLoaded(() => { // When the symbol is successfully loaded
|
|
21
|
+
console.log(`Market "${chart.infos.description}" loaded !`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
chart.onUpdate(() => { // When price changes
|
|
25
|
+
if (!chart.periods[0]) return;
|
|
26
|
+
console.log(`[${chart.infos.description}]: ${chart.periods[0].close} ${chart.infos.currency_id}`);
|
|
27
|
+
// Do something...
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Wait 5 seconds and set the market to BINANCE:ETHEUR
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
console.log('\nSetting market to BINANCE:ETHEUR...');
|
|
33
|
+
chart.setMarket('BINANCE:ETHEUR', {
|
|
34
|
+
timeframe: 'D',
|
|
35
|
+
});
|
|
36
|
+
}, 5000);
|
|
37
|
+
|
|
38
|
+
// Wait 10 seconds and set the timeframe to 15 minutes
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
console.log('\nSetting timeframe to 15 minutes...');
|
|
41
|
+
chart.setSeries('15');
|
|
42
|
+
}, 10000);
|
|
43
|
+
|
|
44
|
+
// Wait 15 seconds and set the chart type to "Heikin Ashi"
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
console.log('\nSetting the chart type to "Heikin Ashi"s...');
|
|
47
|
+
chart.setMarket('BINANCE:ETHEUR', {
|
|
48
|
+
timeframe: 'D',
|
|
49
|
+
type: 'HeikinAshi',
|
|
50
|
+
});
|
|
51
|
+
}, 15000);
|
|
52
|
+
|
|
53
|
+
// Wait 20 seconds and close the chart
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
console.log('\nClosing the chart...');
|
|
56
|
+
chart.delete();
|
|
57
|
+
}, 20000);
|
|
58
|
+
|
|
59
|
+
// Wait 25 seconds and close the client
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
console.log('\nClosing the client...');
|
|
62
|
+
client.end();
|
|
63
|
+
}, 25000);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const TradingView = require('../main');
|
|
2
|
+
|
|
3
|
+
if (!process.argv[2]) throw Error('Please specify your \'sessionid\' cookie');
|
|
4
|
+
|
|
5
|
+
const client = new TradingView.Client({
|
|
6
|
+
token: process.argv[2],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const chart = new client.Session.Chart();
|
|
10
|
+
chart.setMarket('NASDAQ:AAPL', {
|
|
11
|
+
type: 'Renko',
|
|
12
|
+
timeframe: '1',
|
|
13
|
+
inputs: {
|
|
14
|
+
source: 'close',
|
|
15
|
+
sources: 'Close',
|
|
16
|
+
boxSize: 3,
|
|
17
|
+
style: 'Traditional',
|
|
18
|
+
atrLength: 14,
|
|
19
|
+
wicks: true,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
TradingView.searchIndicator('CM_Ultimate_MA_MTF_V2').then(async (indicator) => {
|
|
24
|
+
console.log(
|
|
25
|
+
'*** Indicator information\n',
|
|
26
|
+
indicator[0].id,
|
|
27
|
+
);
|
|
28
|
+
const pineIndicator = await indicator[0].get();
|
|
29
|
+
const study = new chart.Study(pineIndicator);
|
|
30
|
+
study.onUpdate(() => {
|
|
31
|
+
console.log(
|
|
32
|
+
'\n*** Chart time and close:\n',
|
|
33
|
+
chart.periods[0].time,
|
|
34
|
+
chart.periods[0].close,
|
|
35
|
+
);
|
|
36
|
+
console.log(
|
|
37
|
+
'\n*** Indicator values:\n',
|
|
38
|
+
study.periods[0].MultiTimeframe_Moving_Avg,
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
});
|
package/main.js
CHANGED
|
@@ -1,337 +1,9 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (!p) return false;
|
|
11
|
-
try {
|
|
12
|
-
return JSON.parse(p);
|
|
13
|
-
} catch (error) {
|
|
14
|
-
console.warn('Cant parse', p);
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
}).filter((p) => p);
|
|
18
|
-
|
|
19
|
-
packets.forEach((packet) => {
|
|
20
|
-
if (packet.m === 'protocol_error') {
|
|
21
|
-
return onPacket({
|
|
22
|
-
type: 'error',
|
|
23
|
-
syntax: packet.p[0],
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (packet.m && packet.p) {
|
|
28
|
-
return onPacket({
|
|
29
|
-
type: packet.m,
|
|
30
|
-
session: packet.p[0],
|
|
31
|
-
data: packet.p[1],
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (typeof packet === 'number') return onPacket({ type: 'ping', ping: packet });
|
|
36
|
-
|
|
37
|
-
return onPacket({ type: 'info', ...packet });
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function genSession() {
|
|
42
|
-
let r = '';
|
|
43
|
-
const c = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
44
|
-
for (let i = 0; i < 12; i += 1) r += c.charAt(Math.floor(Math.random() * c.length));
|
|
45
|
-
return `qs_${r}`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = (autoInit = true) => {
|
|
49
|
-
const callbacks = {
|
|
50
|
-
connected: [],
|
|
51
|
-
disconnected: [],
|
|
52
|
-
logged: [],
|
|
53
|
-
subscribed: [],
|
|
54
|
-
ping: [],
|
|
55
|
-
price: [],
|
|
56
|
-
data: [],
|
|
57
|
-
|
|
58
|
-
error: [],
|
|
59
|
-
event: [],
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const chartEventNames = [
|
|
63
|
-
'du', 'timescale_update',
|
|
64
|
-
'series_loading', 'series_completed', 'series_error',
|
|
65
|
-
'symbol_resolved', 'symbol_error',
|
|
66
|
-
'study_loading', 'study_error',
|
|
67
|
-
];
|
|
68
|
-
const chartCBs = {};
|
|
69
|
-
|
|
70
|
-
function handleEvent(ev, ...data) {
|
|
71
|
-
callbacks[ev].forEach((e) => e(...data));
|
|
72
|
-
callbacks.event.forEach((e) => e(ev, ...data));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function handleError(...msgs) {
|
|
76
|
-
if (callbacks.error.length === 0) console.error(...msgs);
|
|
77
|
-
else handleEvent('error', ...msgs);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const ws = new WebSocket('wss://widgetdata.tradingview.com/socket.io/websocket', {
|
|
81
|
-
origin: 'https://s.tradingview.com',
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
let logged = false;
|
|
85
|
-
/** ID of the quote session */
|
|
86
|
-
let sessionId = '';
|
|
87
|
-
|
|
88
|
-
/** List of subscribed symbols */
|
|
89
|
-
let subscribed = [];
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Send a custom packet
|
|
93
|
-
* @param {string} t Packet type
|
|
94
|
-
* @param {string[]} p Packet data
|
|
95
|
-
* @example
|
|
96
|
-
* // Subscribe manualy to BTCEUR
|
|
97
|
-
* send('quote_add_symbols', [sessionId, 'BTCEUR']);
|
|
98
|
-
*/
|
|
99
|
-
function send(t, p = []) {
|
|
100
|
-
if (!sessionId) return;
|
|
101
|
-
|
|
102
|
-
const msg = JSON.stringify({ m: t, p });
|
|
103
|
-
ws.send(`~m~${msg.length}~m~${msg}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
ws.on('open', () => {
|
|
107
|
-
sessionId = genSession();
|
|
108
|
-
handleEvent('connected');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
ws.on('close', () => {
|
|
112
|
-
logged = false;
|
|
113
|
-
sessionId = '';
|
|
114
|
-
handleEvent('disconnected');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
ws.on('message', parse);
|
|
118
|
-
|
|
119
|
-
onPacket = (packet) => {
|
|
120
|
-
if (packet.type === 'ping') {
|
|
121
|
-
const pingStr = `~h~${packet.ping}`;
|
|
122
|
-
ws.send(`~m~${pingStr.length}~m~${pingStr}`);
|
|
123
|
-
handleEvent('ping', packet.ping);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (packet.type === 'quote_completed' && packet.data) {
|
|
128
|
-
handleEvent('subscribed', packet.data);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (packet.type === 'qsd' && packet.data.n && packet.data.v.lp) {
|
|
133
|
-
handleEvent('price', {
|
|
134
|
-
symbol: packet.data.n,
|
|
135
|
-
price: packet.data.v.lp,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (chartEventNames.includes(packet.type) && chartCBs[packet.session]) {
|
|
142
|
-
chartCBs[packet.session](packet);
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (!logged && packet.type === 'info') {
|
|
147
|
-
if (autoInit) {
|
|
148
|
-
send('set_auth_token', ['unauthorized_user_token']);
|
|
149
|
-
send('quote_create_session', [sessionId]);
|
|
150
|
-
send('quote_set_fields', [sessionId, 'lp']);
|
|
151
|
-
|
|
152
|
-
subscribed.forEach((symbol) => send('quote_add_symbols', [sessionId, symbol]));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
handleEvent('logged', packet);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (packet.type === 'error') {
|
|
160
|
-
handleError(`Market API critical error: ${packet.syntax}`);
|
|
161
|
-
ws.close();
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
handleEvent('data', packet);
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
/** Event listener
|
|
170
|
-
* @param { 'connected' | 'disconnected' | 'logged'
|
|
171
|
-
* | 'subscribed' | 'price' | 'data' | 'error' | 'ping' } event Event
|
|
172
|
-
* @param {(...data: object) => null} cb Callback
|
|
173
|
-
*/
|
|
174
|
-
on(event, cb) {
|
|
175
|
-
if (!callbacks[event]) {
|
|
176
|
-
console.log('Wrong event:', event);
|
|
177
|
-
console.log('Available events:', Object.keys(callbacks));
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
callbacks[event].push(cb);
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Close the websocket connection
|
|
186
|
-
* @param {string} symbol Market symbol (Example: BTCEUR or COINBASE:BTCEUR)
|
|
187
|
-
*/
|
|
188
|
-
end() { ws.close(); },
|
|
189
|
-
|
|
190
|
-
search,
|
|
191
|
-
getScreener,
|
|
192
|
-
getTA,
|
|
193
|
-
subscribed,
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Unsubscribe to a market
|
|
197
|
-
* @param {string} symbol Market symbol (Example: BTCEUR or COINBASE:BTCEUR)
|
|
198
|
-
*/
|
|
199
|
-
subscribe(symbol) {
|
|
200
|
-
if (subscribed.includes(symbol)) return;
|
|
201
|
-
send('quote_add_symbols', [sessionId, symbol]);
|
|
202
|
-
subscribed.push(symbol);
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Unsubscribe from a market
|
|
207
|
-
* @param {string} symbol Market symbol (Example: BTCEUR or COINBASE:BTCEUR)
|
|
208
|
-
*/
|
|
209
|
-
unsubscribe(symbol) {
|
|
210
|
-
if (!subscribed.includes(symbol)) return;
|
|
211
|
-
send('quote_remove_symbols', [sessionId, symbol]);
|
|
212
|
-
subscribed = subscribed.filter((s) => s !== symbol);
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* @typedef {Object} IndicatorInfos Indicator infos
|
|
217
|
-
* @property {string} id ID of the indicator (Like: XXX;XXXXXXXXXXXXXXXXXXXXX)
|
|
218
|
-
* @property {string} version Wanted version of the indicator
|
|
219
|
-
* @property {(string | number | boolean | null)[]} [settings] Indicator settings value
|
|
220
|
-
*
|
|
221
|
-
* @typedef {Object} ChartInfos
|
|
222
|
-
* @property {string} [session] User 'sessionid' cookie
|
|
223
|
-
* @property {string} symbol Market symbol (Example: BTCEUR or COINBASE:BTCEUR)
|
|
224
|
-
* @property { '1' | '3' | '5' | '15' | '30' | '45'
|
|
225
|
-
* | '60' | '120' | '180' | '240'
|
|
226
|
-
* | '1D' | '1W' | '1M'
|
|
227
|
-
* } [period] Period
|
|
228
|
-
* @property {number} [range] Number of loaded periods
|
|
229
|
-
* @property {string} [timezone] Timezone in 'Europe/Paris' format
|
|
230
|
-
* @property {IndicatorInfos[]} [indicators] List of indicators
|
|
231
|
-
*/
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* @typedef {Object} Period List of prices / indicator values
|
|
235
|
-
* @property {number} $time
|
|
236
|
-
* @property {{
|
|
237
|
-
* time: number, open: number, close: number,
|
|
238
|
-
* max: number, min: number, change: number,
|
|
239
|
-
* }} $prices
|
|
240
|
-
*/
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Init a chart instance
|
|
244
|
-
* @param {ChartInfos} chart
|
|
245
|
-
* @param {{(prices: Period[]): null}} onUpdate List of periods starting from the lastest
|
|
246
|
-
*/
|
|
247
|
-
async initChart(chart, onUpdate) {
|
|
248
|
-
const chartSession = genSession();
|
|
249
|
-
const periods = [];
|
|
250
|
-
const indicators = await Promise.all(
|
|
251
|
-
(chart.indicators || []).map((i) => getIndicator(i.id, i.version, i.settings)),
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
function updatePeriods(packet) {
|
|
255
|
-
const newData = packet.data;
|
|
256
|
-
|
|
257
|
-
Object.keys(newData).forEach((type) => {
|
|
258
|
-
(newData[type].s || newData[type].st || []).forEach((p) => {
|
|
259
|
-
if (!periods[p.i]) periods[p.i] = {};
|
|
260
|
-
|
|
261
|
-
if (newData[type].s) {
|
|
262
|
-
[periods[p.i].$time] = p.v;
|
|
263
|
-
|
|
264
|
-
periods[p.i][type] = {
|
|
265
|
-
open: p.v[1],
|
|
266
|
-
close: p.v[4],
|
|
267
|
-
max: p.v[2],
|
|
268
|
-
min: p.v[3],
|
|
269
|
-
change: Math.round(p.v[5] * 100) / 100,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (newData[type].st) {
|
|
274
|
-
const period = {};
|
|
275
|
-
const indicator = indicators[parseInt(type, 10)];
|
|
276
|
-
|
|
277
|
-
p.v.forEach((val, i) => {
|
|
278
|
-
if (i === 0) return;
|
|
279
|
-
if (indicator.plots[`plot_${i - 1}`]) period[indicator.plots[`plot_${i - 1}`]] = val;
|
|
280
|
-
else period[`_plot_${i - 1}`] = val;
|
|
281
|
-
});
|
|
282
|
-
periods[p.i][chart.indicators[parseInt(type, 10)].name || `st${type}`] = period;
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
chartCBs[chartSession] = (packet) => {
|
|
289
|
-
if (['timescale_update', 'du'].includes(packet.type)) {
|
|
290
|
-
updatePeriods(packet);
|
|
291
|
-
onUpdate([...periods].reverse());
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (packet.type.endsWith('_error')) {
|
|
296
|
-
handleError(`Error on '${chart.symbol}' (${chartSession}) chart: "${packet.type}"`);
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
if (chart.session) send('set_auth_token', [await getUserToken(chart.session)]);
|
|
301
|
-
send('chart_create_session', [chartSession, '']);
|
|
302
|
-
if (chart.timezone) send('switch_timezone', [chartSession, chart.timezone]);
|
|
303
|
-
send('resolve_symbol', [chartSession, 'sds_sym_1', `={"symbol":"${chart.symbol || 'BTCEUR'}","adjustment":"splits"}`]);
|
|
304
|
-
send('create_series', [chartSession, '$prices', 's1', 'sds_sym_1', (chart.period || '240'), (chart.range || 100), '']);
|
|
305
|
-
|
|
306
|
-
indicators.forEach(async (indicator, i) => {
|
|
307
|
-
const pineInfos = {
|
|
308
|
-
pineId: indicator.pineId,
|
|
309
|
-
pineVersion: indicator.pineVersion,
|
|
310
|
-
text: indicator.script,
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
Object.keys(indicator.inputs).forEach((inputID, inp) => {
|
|
314
|
-
const input = indicator.inputs[inputID];
|
|
315
|
-
if (input.type === 'bool' && typeof input.value !== 'boolean') handleError(`Input '${input.name}' (${inp}) must be a boolean !`);
|
|
316
|
-
if (input.type === 'integer' && typeof input.value !== 'number') handleError(`Input '${input.name}' (${inp}) must be a number !`);
|
|
317
|
-
if (input.type === 'float' && typeof input.value !== 'number') handleError(`Input '${input.name}' (${inp}) must be a number !`);
|
|
318
|
-
if (input.type === 'text' && typeof input.value !== 'string') handleError(`Input '${input.name}' (${inp}) must be a string !`);
|
|
319
|
-
if (input.options && !input.options.includes(input.value)) {
|
|
320
|
-
handleError(`Input '${input.name}' (${inp}) must be one of these values:`, input.options);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
pineInfos[inputID] = {
|
|
324
|
-
v: input.value,
|
|
325
|
-
f: input.isFake,
|
|
326
|
-
t: input.type,
|
|
327
|
-
};
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
send('create_study', [chartSession, `${i}`, 'st1', '$prices', 'Script@tv-scripting-101!', pineInfos]);
|
|
331
|
-
});
|
|
332
|
-
},
|
|
333
|
-
|
|
334
|
-
send,
|
|
335
|
-
sessionId,
|
|
336
|
-
};
|
|
337
|
-
};
|
|
1
|
+
const miscRequests = require('./src/miscRequests');
|
|
2
|
+
const Client = require('./src/client');
|
|
3
|
+
const BuiltInIndicator = require('./src/classes/BuiltInIndicator');
|
|
4
|
+
const PineIndicator = require('./src/classes/PineIndicator');
|
|
5
|
+
|
|
6
|
+
module.exports = { ...miscRequests };
|
|
7
|
+
module.exports.Client = Client;
|
|
8
|
+
module.exports.BuiltInIndicator = BuiltInIndicator;
|
|
9
|
+
module.exports.PineIndicator = PineIndicator;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mathieuc/tradingview",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-pre",
|
|
4
4
|
"description": "Tradingview instant stocks API, indicator alerts, trading bot, and more !",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"test-strat-alerts": "node ./tests/alerts/strategyAlert.js",
|
|
12
12
|
"test": "npm run test-prices"
|
|
13
13
|
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/Mathieu2301/TradingView-API.git"
|
|
17
|
+
},
|
|
14
18
|
"keywords": [
|
|
15
19
|
"tradingwiew",
|
|
16
20
|
"market",
|
|
@@ -24,11 +28,15 @@
|
|
|
24
28
|
"author": "Mathieu Colmon",
|
|
25
29
|
"license": "ISC",
|
|
26
30
|
"dependencies": {
|
|
31
|
+
"jszip": "^3.7.1",
|
|
27
32
|
"ws": "^7.4.3"
|
|
28
33
|
},
|
|
29
34
|
"devDependencies": {
|
|
35
|
+
"@babel/eslint-parser": "^7.15.7",
|
|
36
|
+
"@mathieuc/console": "^1.0.1",
|
|
30
37
|
"eslint": "^7.25.0",
|
|
31
38
|
"eslint-config-airbnb-base": "^14.2.1",
|
|
32
|
-
"eslint-plugin-import": "^2.22.1"
|
|
39
|
+
"eslint-plugin-import": "^2.22.1",
|
|
40
|
+
"jsdoc-to-markdown": "^7.1.0"
|
|
33
41
|
}
|
|
34
42
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} GraphicLabel
|
|
3
|
+
* @prop {number} id Drawing ID
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} GraphicLine
|
|
8
|
+
* @prop {number} id Drawing ID
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} GraphicBox
|
|
13
|
+
* @prop {number} id Drawing ID
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} GraphicTable
|
|
18
|
+
* @prop {number} id Drawing ID
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} GraphicHorizline
|
|
23
|
+
* @prop {number} id Drawing ID
|
|
24
|
+
* @prop {number} level Y position of the line
|
|
25
|
+
* @prop {number} startIndex Start index of the line (`chart.periods[line.startIndex]`)
|
|
26
|
+
* @prop {number} endIndex End index of the line (`chart.periods[line.endIndex]`)
|
|
27
|
+
* @prop {boolean} extendRight Is the line extended to the right
|
|
28
|
+
* @prop {boolean} extendLeft Is the line extended to the left
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {Object} GraphicPoint
|
|
33
|
+
* @prop {number} index X position of the point
|
|
34
|
+
* @prop {number} level Y position of the point
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} GraphicPolygon
|
|
39
|
+
* @prop {number} id Drawing ID
|
|
40
|
+
* @prop {GraphicPoint[]} points List of polygon points
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {Object} GraphicHorizHist
|
|
45
|
+
* @prop {number} id Drawing ID
|
|
46
|
+
* @prop {number} priceLow Low Y position
|
|
47
|
+
* @prop {number} priceHigh High Y position
|
|
48
|
+
* @prop {number} firstBarTime First X position
|
|
49
|
+
* @prop {number} lastBarTime Last X position
|
|
50
|
+
* @prop {number[]} rate List of values
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {Object} GraphicData List of drawings indexed by type
|
|
55
|
+
* @prop {GraphicLabel[]} labels List of labels drawings
|
|
56
|
+
* @prop {GraphicLine[]} lines List of lines drawings
|
|
57
|
+
* @prop {GraphicBox[]} boxes List of boxes drawings
|
|
58
|
+
* @prop {GraphicTable[]} tables List of tables drawings
|
|
59
|
+
* @prop {GraphicPolygon[]} polygons List of polygons drawings
|
|
60
|
+
* @prop {GraphicHorizHist[]} horizHists List of horizontal histograms drawings
|
|
61
|
+
* @prop {GraphicHorizline[]} horizLines List of horizontal lines drawings
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {Object} rawGraphic Raw graphic data
|
|
66
|
+
* @param {Object} indexes Drawings xPos indexes
|
|
67
|
+
* @returns {GraphicData}
|
|
68
|
+
*/
|
|
69
|
+
module.exports = function graphicParse(rawGraphic = {}, indexes = []) {
|
|
70
|
+
// console.log('indexes', indexes);
|
|
71
|
+
return {
|
|
72
|
+
labels: Object.values(rawGraphic.dwglabels ?? {}).map((l) => ({
|
|
73
|
+
...l,
|
|
74
|
+
})),
|
|
75
|
+
|
|
76
|
+
lines: Object.values(rawGraphic.dwglines ?? {}).map((l) => ({
|
|
77
|
+
...l,
|
|
78
|
+
})),
|
|
79
|
+
|
|
80
|
+
boxes: Object.values(rawGraphic.dwgboxes ?? {}).map((b) => ({
|
|
81
|
+
...b,
|
|
82
|
+
})),
|
|
83
|
+
|
|
84
|
+
tables: Object.values(rawGraphic.dwgtables ?? {}).map((t) => ({
|
|
85
|
+
...t,
|
|
86
|
+
})),
|
|
87
|
+
|
|
88
|
+
horizLines: Object.values(rawGraphic.horizlines ?? {}).map((h) => ({
|
|
89
|
+
...h,
|
|
90
|
+
startIndex: indexes[h.startIndex],
|
|
91
|
+
endIndex: indexes[h.endIndex],
|
|
92
|
+
})),
|
|
93
|
+
|
|
94
|
+
polygons: Object.values(rawGraphic.polygons ?? {}).map((p) => ({
|
|
95
|
+
...p,
|
|
96
|
+
points: p.points.map((pt) => ({
|
|
97
|
+
...pt,
|
|
98
|
+
index: indexes[pt.index],
|
|
99
|
+
})),
|
|
100
|
+
})),
|
|
101
|
+
|
|
102
|
+
horizHists: Object.values(rawGraphic.hhists ?? {}).map((h) => ({
|
|
103
|
+
...h,
|
|
104
|
+
firstBarTime: indexes[h.firstBarTime],
|
|
105
|
+
lastBarTime: indexes[h.lastBarTime],
|
|
106
|
+
})),
|
|
107
|
+
|
|
108
|
+
raw: () => rawGraphic,
|
|
109
|
+
};
|
|
110
|
+
};
|