market-data-tradingview-ws 0.0.12 → 0.0.13
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/lib/client.js +83 -65
- package/lib/tradingView.js +14 -8
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -13,10 +13,13 @@ const periods = {
|
|
|
13
13
|
3600: '60',
|
|
14
14
|
14400: '240',
|
|
15
15
|
86400: '1D',
|
|
16
|
+
604800: '1W',
|
|
17
|
+
2592000: '1M',
|
|
16
18
|
};
|
|
17
19
|
|
|
20
|
+
let ws = null;
|
|
21
|
+
|
|
18
22
|
module.exports = class Client {
|
|
19
|
-
#ws;
|
|
20
23
|
#charts = {
|
|
21
24
|
values: {},
|
|
22
25
|
set({ key, data }) {
|
|
@@ -29,6 +32,7 @@ module.exports = class Client {
|
|
|
29
32
|
frame: data.frame,
|
|
30
33
|
i: data.i,
|
|
31
34
|
deleted: data.deleted || false,
|
|
35
|
+
limit: data.limit || 1500,
|
|
32
36
|
};
|
|
33
37
|
}
|
|
34
38
|
},
|
|
@@ -84,17 +88,29 @@ module.exports = class Client {
|
|
|
84
88
|
if (index !== -1) arr.splice(index, 1);
|
|
85
89
|
},
|
|
86
90
|
};
|
|
91
|
+
#symbols = {
|
|
92
|
+
values: {},
|
|
93
|
+
max: 1,
|
|
94
|
+
getSymbol({ key, symbol }) {
|
|
95
|
+
// let data = this.values[symbol];
|
|
96
|
+
// if (data === undefined) data = this.set({ key, symbol });
|
|
97
|
+
// return data;
|
|
98
|
+
const symbolKey = 'sds_sym_' + this.max++;
|
|
99
|
+
ws.send(tv.resolveSymbol({ chartSession: key, symbolKey, symbol }));
|
|
100
|
+
this.values[symbol] = { key: symbolKey };
|
|
101
|
+
return this.values[symbol];
|
|
102
|
+
},
|
|
103
|
+
};
|
|
87
104
|
|
|
88
|
-
// #resolved;
|
|
89
105
|
#token = null;
|
|
90
|
-
#maxSymbolKey = 1;
|
|
91
106
|
|
|
92
107
|
constructor() {
|
|
93
108
|
// this.#resolved = new Map();
|
|
94
109
|
}
|
|
95
110
|
|
|
96
|
-
close() {
|
|
97
|
-
|
|
111
|
+
async close() {
|
|
112
|
+
// token delete !!!
|
|
113
|
+
ws.close();
|
|
98
114
|
}
|
|
99
115
|
|
|
100
116
|
getAll() {
|
|
@@ -130,23 +146,31 @@ module.exports = class Client {
|
|
|
130
146
|
});
|
|
131
147
|
}
|
|
132
148
|
|
|
133
|
-
async connect({ url, options, login, pass, result }) {
|
|
134
|
-
this.#token = await this.getToken({ login, pass });
|
|
135
|
-
|
|
149
|
+
async connect({ url, options, login, pass, result, token }) {
|
|
150
|
+
this.#token = token || await this.getToken({ login, pass });
|
|
151
|
+
|
|
136
152
|
if (this.#token.length > 10) {
|
|
137
153
|
return new Promise((resolv, reject) => {
|
|
138
|
-
|
|
154
|
+
url += '?from=chart%2FKq8EfKQU%2F';
|
|
155
|
+
const date = new Date();
|
|
156
|
+
url += '&date=' + date.getFullYear() + '_' + String(date.getMonth() + 1).padStart(2, '0') + '_' + String(date.getDate()).padStart(2, '0') + '-11_25';
|
|
157
|
+
url += '&type=chart';
|
|
158
|
+
ws = new WebSocket(url, options);
|
|
159
|
+
|
|
160
|
+
const originalSend = ws.send;
|
|
161
|
+
ws.send = function(data) {
|
|
162
|
+
// console.log('Message sent:', data);
|
|
163
|
+
originalSend.apply(ws, arguments);
|
|
164
|
+
};
|
|
139
165
|
|
|
140
|
-
|
|
166
|
+
ws.onclose = () => console.log('disconnected');
|
|
141
167
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
168
|
+
ws.onerror = (error) => reject(console.error('error: ', error));
|
|
169
|
+
ws.onopen = () => {
|
|
170
|
+
ws.send(this.auth(this.#token));
|
|
171
|
+
ws.send(tv.setLocaleRu());
|
|
146
172
|
|
|
147
|
-
// const chartKey = this.createChartSession();
|
|
148
173
|
const quoteKey = this.createQuoteSmallSession();
|
|
149
|
-
// this.addQuoteSymbols({ symbols: ['NASDAQ:PYPL'] });
|
|
150
174
|
|
|
151
175
|
this.messageListner({ result });
|
|
152
176
|
resolv('open');
|
|
@@ -159,24 +183,24 @@ module.exports = class Client {
|
|
|
159
183
|
createQuoteSmallSession() {
|
|
160
184
|
const key = tv.createSession({ startsWith: 'qs_' });
|
|
161
185
|
this.#quotes.set({ key, data: { id: key, type: 'small', symbols: [] } });
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
//
|
|
186
|
+
ws.send(tv.quoteCreateSession({ session: key }));
|
|
187
|
+
ws.send(tv.setFieldsSmall({ session: key }));
|
|
188
|
+
// ws.send(tv.setFields({ session: key }));
|
|
165
189
|
return key;
|
|
166
190
|
}
|
|
167
191
|
|
|
168
192
|
createQuoteFullSession() {
|
|
169
193
|
const key = tv.createSession({ startsWith: 'qs_' });
|
|
170
194
|
this.#quotes.set({ key, data: { id: key, type: 'full', symbols: [] } });
|
|
171
|
-
|
|
195
|
+
ws.send(tv.quoteCreateSession({ session: key }));
|
|
172
196
|
return key;
|
|
173
197
|
}
|
|
174
198
|
|
|
175
199
|
createChartSession() {
|
|
176
200
|
const key = tv.createSession({ startsWith: 'cs_' });
|
|
177
201
|
this.#charts.set({ key, data: { id: key, symbol: '', period: 0, symbolKey: '', frame: '', i: '', deleted: false } });
|
|
178
|
-
|
|
179
|
-
|
|
202
|
+
ws.send(tv.chartCreateSession({ chartSession: key }));
|
|
203
|
+
ws.send(tv.switchTimezone({ chartSession: key, tz: 'Etc/UTC' }));
|
|
180
204
|
return key;
|
|
181
205
|
}
|
|
182
206
|
|
|
@@ -189,9 +213,8 @@ module.exports = class Client {
|
|
|
189
213
|
result.exist.push(symbol);
|
|
190
214
|
} else {
|
|
191
215
|
key = this.#quotes.add({ symbol });
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// this.#ws.send(tv.quoteFastSymbol({ session: key, symbol }));
|
|
216
|
+
ws.send(tv.quoteAddSymbol({ session: key, symbol }));
|
|
217
|
+
// ws.send(tv.quoteFastSymbol({ session: key, symbol }));
|
|
195
218
|
result.add.push(symbol);
|
|
196
219
|
}
|
|
197
220
|
});
|
|
@@ -202,39 +225,31 @@ module.exports = class Client {
|
|
|
202
225
|
const key = this.#quotes.getBySymbol({ symbol });
|
|
203
226
|
if (!key) return 'unlisted';
|
|
204
227
|
this.#quotes.delete({ key, symbol });
|
|
205
|
-
|
|
228
|
+
ws.send(tv.quoteRemoveSymbols({ session: key, symbol }));
|
|
206
229
|
return 'delete';
|
|
207
230
|
}
|
|
208
231
|
|
|
209
|
-
resolveSymbol({ key, symbol }) {
|
|
210
|
-
const symbolKey = 'sds_sym_' + this.#maxSymbolKey++;
|
|
211
|
-
this.#ws.send(tv.resolveSymbol({ chartSession: key, symbolKey, symbol }));
|
|
212
|
-
return symbolKey;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
232
|
addChartSymbol({ symbol, period, limit }) {
|
|
216
233
|
let key = this.#charts.getBySymbolPeriod({ symbol, period });
|
|
217
234
|
if (key) {
|
|
218
|
-
console.warn('addChartSymbol exist');
|
|
235
|
+
console.warn('addChartSymbol exist:', key, symbol, period);
|
|
219
236
|
return 'exist';
|
|
220
237
|
}
|
|
221
|
-
|
|
222
238
|
// console.warn('modules addChartSymbol1', symbol, period, limit, key);
|
|
223
|
-
const
|
|
224
|
-
if (
|
|
239
|
+
const deleted = this.#charts.getDeleted();
|
|
240
|
+
if (deleted !== null && deleted.limit >= limit) return this.updateChartSymbol({ symbol, period, limit, last: { symbol: deleted.symbol, period: parseInt(deleted.period) }});
|
|
225
241
|
|
|
226
242
|
key = this.createChartSession();
|
|
227
243
|
const data = this.#charts.get({ key });
|
|
228
244
|
|
|
229
|
-
data.symbolKey = this.
|
|
245
|
+
data.symbolKey = this.#symbols.getSymbol({ key, symbol }).key;
|
|
230
246
|
data.symbol = symbol;
|
|
231
247
|
data.period = period;
|
|
232
248
|
data.frame = 'sds_' + Object.keys(this.#charts.values).length;
|
|
233
249
|
data.i = 's' + 1;
|
|
250
|
+
data.limit = limit;
|
|
234
251
|
|
|
235
|
-
|
|
236
|
-
// this.#resolved.set(symbol, { key: data.symbolKey });
|
|
237
|
-
this.#ws.send(
|
|
252
|
+
ws.send(
|
|
238
253
|
tv.createSeries({
|
|
239
254
|
chartSession: key,
|
|
240
255
|
frame: data.frame,
|
|
@@ -244,49 +259,56 @@ module.exports = class Client {
|
|
|
244
259
|
limit,
|
|
245
260
|
}),
|
|
246
261
|
);
|
|
247
|
-
// console.
|
|
262
|
+
// console.warn('addChartSymbol4', periods[period], data);
|
|
248
263
|
this.#charts.set({ key, data });
|
|
249
|
-
|
|
250
264
|
return 'add';
|
|
251
265
|
}
|
|
252
266
|
|
|
253
267
|
updateChartSymbol({ symbol, period, limit, last }) {
|
|
254
|
-
// period = parseInt(period);
|
|
255
|
-
// last.period = parseInt(last.period);
|
|
256
268
|
const key = this.#charts.getBySymbolPeriod({ symbol: last.symbol, period: last.period });
|
|
257
269
|
const data = this.#charts.get({ key });
|
|
258
270
|
|
|
259
271
|
// console.warn('modules updateChartSymbol 1: ', symbol, period, limit, last, data);
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
272
|
+
// const alreadyKey = this.#charts.getBySymbolPeriod({ symbol, period })
|
|
273
|
+
// if (alreadyKey) {
|
|
274
|
+
// // console.warn('updateChartSymbol exist: ', alreadyKey);
|
|
275
|
+
// this.#charts.delete({ key });
|
|
276
|
+
// // console.warn('updateChartSymbol exist');
|
|
277
|
+
// return 'exist';
|
|
278
|
+
// }
|
|
268
279
|
|
|
269
|
-
data.symbolKey = this.
|
|
280
|
+
data.symbolKey = this.#symbols.getSymbol({ key, symbol }).key;
|
|
270
281
|
data.symbol = symbol;
|
|
271
282
|
data.period = period;
|
|
272
283
|
data.i = 's' + (parseInt(data.i.replace(/[^0-9]/g, '')) + 1);
|
|
273
|
-
|
|
284
|
+
|
|
285
|
+
ws.send(
|
|
274
286
|
tv.modifySeries({
|
|
275
287
|
chartSession: key,
|
|
276
288
|
frame: data.frame,
|
|
277
289
|
increment: data.i,
|
|
278
290
|
symbolKey: data.symbolKey,
|
|
279
291
|
interval: periods[period],
|
|
280
|
-
limit,
|
|
281
292
|
}),
|
|
282
293
|
);
|
|
283
294
|
this.#charts.set({ key, data });
|
|
295
|
+
if (data.limit < limit) {
|
|
296
|
+
ws.send(tv.moreData({ chartSession: key, frame: data.frame, add: limit - data.limit }));
|
|
297
|
+
data.limit = limit;
|
|
298
|
+
}
|
|
284
299
|
return 'update';
|
|
285
300
|
}
|
|
286
301
|
|
|
302
|
+
deleteChartSymbol({ symbol, period }) {
|
|
303
|
+
let key = this.#charts.getBySymbolPeriod({ symbol, period });
|
|
304
|
+
if (!key) return void console.warn('deleteChartSymbol empty key');
|
|
305
|
+
this.#charts.delete({ key });
|
|
306
|
+
return void console.log('deleteChartSymbol: ', key);
|
|
307
|
+
}
|
|
308
|
+
|
|
287
309
|
messageListner({ result }) {
|
|
288
|
-
|
|
289
|
-
if (
|
|
310
|
+
ws.on('message', (raw) => {
|
|
311
|
+
if (ws.readyState !== ws.OPEN) return;
|
|
290
312
|
|
|
291
313
|
// console.log('raw: ', JSON.stringify(raw.toString()));
|
|
292
314
|
let session = '';
|
|
@@ -296,13 +318,9 @@ module.exports = class Client {
|
|
|
296
318
|
if (packet === undefined) {
|
|
297
319
|
console.warn('undefined: ', raw.toString());
|
|
298
320
|
} else {
|
|
299
|
-
// eslint-disable-next-line no-lonely-if
|
|
300
321
|
if (packet.type === 'ping') {
|
|
301
322
|
// console.info('pong', packet);
|
|
302
|
-
|
|
303
|
-
// } else if (packet.type === 'protocol_error') {
|
|
304
|
-
// console.warn('protocol_error', packet);
|
|
305
|
-
// this.close();
|
|
323
|
+
ws.send(tv.createPong({ value: packet.data }));
|
|
306
324
|
} else if (packet.type === 'qsd') {
|
|
307
325
|
send = packet.data[1].v;
|
|
308
326
|
name = send.bid === undefined && send.ask === undefined ? 'data' : 'levelI';
|
|
@@ -335,12 +353,12 @@ module.exports = class Client {
|
|
|
335
353
|
} else if (['series', 'symbol', 'quote', 'session'].includes(packet.type)) {
|
|
336
354
|
// console.info(packet);
|
|
337
355
|
} else {
|
|
338
|
-
console.
|
|
356
|
+
// console.error('error', raw.toString());
|
|
339
357
|
result('error', raw.toString())
|
|
340
358
|
}
|
|
341
359
|
}
|
|
342
|
-
name = null;
|
|
343
|
-
send = null;
|
|
360
|
+
// name = null;
|
|
361
|
+
// send = null;
|
|
344
362
|
});
|
|
345
363
|
});
|
|
346
364
|
}
|
package/lib/tradingView.js
CHANGED
|
@@ -35,8 +35,7 @@ class TradingView {
|
|
|
35
35
|
// }
|
|
36
36
|
|
|
37
37
|
// await utils.pause();
|
|
38
|
-
|
|
39
|
-
return 'eyJhbGciOiJSUzUxMiIsImtpZCI6IkdaeFUiLCJ0eXAiOiJKV1QifQ.eyJ1c2VyX2lkIjoxMjI1ODcxMiwiZXhwIjoxNzA1OTE3OTE1LCJpYXQiOjE3MDU5MDM1MTUsInBsYW4iOiJwcm9fcHJlbWl1bSIsImV4dF9ob3VycyI6MSwicGVybSI6IiIsInN0dWR5X3Blcm0iOiJ0di1wcm9zdHVkaWVzLHR2LWNoYXJ0X3BhdHRlcm5zLHR2LXZvbHVtZWJ5cHJpY2UsdHYtY2hhcnRwYXR0ZXJucyIsIm1heF9zdHVkaWVzIjoyNSwibWF4X2Z1bmRhbWVudGFscyI6MTAsIm1heF9jaGFydHMiOjgsIm1heF9hY3RpdmVfYWxlcnRzIjo0MDAsIm1heF9zdHVkeV9vbl9zdHVkeSI6MjQsIm1heF9vdmVyYWxsX2FsZXJ0cyI6MjAwMCwibWF4X2FjdGl2ZV9wcmltaXRpdmVfYWxlcnRzIjo0MDAsIm1heF9hY3RpdmVfY29tcGxleF9hbGVydHMiOjQwMCwibWF4X2Nvbm5lY3Rpb25zIjo1MH0.Zoe1DAU3Fn2XpNNvI7uYK0JGHEsNs_OjTqBsnj8vsqWWeDDaOFPVO5m_DLuaUaSFZ4w3diQtgqfeovyPzzUCFDooGEF9FRypY9-zTjGbV0pbQajx-a8X3j79qxvLWe7VYg7cx5RQJGBoN7CGIPzrdpvNvVEYGb_QqXOPy_-F1BE';
|
|
38
|
+
return 'eyJhbGciOiJSUzUxMiIsImtpZCI6IkdaeFUiLCJ0eXAiOiJKV1QifQ.eyJ1c2VyX2lkIjoxMjI1ODcxMiwiZXhwIjoxNzI0OTI1MjkyLCJpYXQiOjE3MjQ5MTA4OTIsInBsYW4iOiJwcm9fcHJlbWl1bSIsImV4dF9ob3VycyI6MSwicGVybSI6InVzLXN0b2NrcyxuYXNkYXFfZ2lkcyxvdGMsbnlzZSxuYXNkYXEsYW1leCIsInN0dWR5X3Blcm0iOiJ0di1jaGFydHBhdHRlcm5zLHR2LXByb3N0dWRpZXMsdHYtY2hhcnRfcGF0dGVybnMsdHYtdm9sdW1lYnlwcmljZSIsIm1heF9zdHVkaWVzIjoyNSwibWF4X2Z1bmRhbWVudGFscyI6MTAsIm1heF9jaGFydHMiOjgsIm1heF9hY3RpdmVfYWxlcnRzIjo0MDAsIm1heF9zdHVkeV9vbl9zdHVkeSI6MjQsImZpZWxkc19wZXJtaXNzaW9ucyI6WyJyZWZib25kcyJdLCJtYXhfb3ZlcmFsbF9hbGVydHMiOjIwMDAsIm1heF9hY3RpdmVfcHJpbWl0aXZlX2FsZXJ0cyI6NDAwLCJtYXhfYWN0aXZlX2NvbXBsZXhfYWxlcnRzIjo0MDAsIm1heF9jb25uZWN0aW9ucyI6NTB9.UT2AdPBEAWk6HJEa6isX4gjVqlfThn8bgOVl3Xa36U36Qifg5xXz9Va8q7DWSY3Smaap2wX4cBF4UQXv1t66Q0TQvFudLuvA2dnetBAHYZSOJIi2PGdG1KuMaCRshUuuH9mxgw_xPGITAuQsbBPZJLTOxq5pQN05pZnedC7SaMs';
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
async getSymbol({ symbol, type }) {
|
|
@@ -60,9 +59,7 @@ class TradingView {
|
|
|
60
59
|
|
|
61
60
|
createSession({ startsWith }) {
|
|
62
61
|
let session = startsWith;
|
|
63
|
-
while (session.length < 12)
|
|
64
|
-
session += letters[Math.floor(Math.random() * letters.length)];
|
|
65
|
-
}
|
|
62
|
+
while (session.length < 12) session += letters[Math.floor(Math.random() * letters.length)];
|
|
66
63
|
return session;
|
|
67
64
|
}
|
|
68
65
|
|
|
@@ -269,10 +266,10 @@ class TradingView {
|
|
|
269
266
|
// symbolKey - id запрошенного тиккера
|
|
270
267
|
// frame - рамка или окно для данной серии
|
|
271
268
|
// increment - инкрементируемый номер изменений запрашиваемого графика в данном frame (таймефрейм)
|
|
272
|
-
createSeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey,
|
|
269
|
+
createSeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, period = '60', limit = 1000 }) {
|
|
273
270
|
// console.warn('createSeries', chartSession, frame, increment, symbolKey, interval, limit);
|
|
274
271
|
return this.formatWSPacket({
|
|
275
|
-
packet: { m: 'create_series', p: [chartSession, frame, increment, symbolKey,
|
|
272
|
+
packet: { m: 'create_series', p: [chartSession, frame, increment, symbolKey, period, limit] },
|
|
276
273
|
});
|
|
277
274
|
}
|
|
278
275
|
|
|
@@ -287,13 +284,22 @@ class TradingView {
|
|
|
287
284
|
return this.formatWSPacket({ packet: { m: 'remove_study', p: [ session, st ] } });
|
|
288
285
|
}
|
|
289
286
|
|
|
290
|
-
modifySeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60'
|
|
287
|
+
modifySeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60' }) {
|
|
291
288
|
// console.warn('modify_series', chartSession, frame, increment, symbolKey, interval, limit);
|
|
292
289
|
return this.formatWSPacket({
|
|
293
290
|
packet: { m: 'modify_series', p: [chartSession, frame, increment, symbolKey, interval] },
|
|
294
291
|
});
|
|
295
292
|
}
|
|
296
293
|
|
|
294
|
+
moreData({ chartSession, frame, add }) {
|
|
295
|
+
return this.formatWSPacket({ packet: { m: 'request_more_data', p: [chartSession, frame, add] } });
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
moreTickmark({chartSession, frame, add}) {
|
|
299
|
+
// "m":"request_more_tickmarks","p":["cs_lslcBHYaqGTT","sds_1",10]
|
|
300
|
+
return this.formatWSPacket({ packet: { m: 'request_more_tickmarks', p: [chartSession, frame, add] } });
|
|
301
|
+
}
|
|
302
|
+
|
|
297
303
|
createPong({ value }) {
|
|
298
304
|
return this.formatWSPacket({ packet: '~h~' + value });
|
|
299
305
|
}
|