market-data-tradingview-ws 0.0.11 → 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 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
- this.#ws.close();
111
+ async close() {
112
+ // token delete !!!
113
+ ws.close();
98
114
  }
99
115
 
100
116
  getAll() {
@@ -130,22 +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 });
149
+ async connect({ url, options, login, pass, result, token }) {
150
+ this.#token = token || await this.getToken({ login, pass });
151
+
135
152
  if (this.#token.length > 10) {
136
153
  return new Promise((resolv, reject) => {
137
- this.#ws = new WebSocket(url, options);
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
+ };
138
165
 
139
- this.#ws.onclose = () => console.log('disconnected');
166
+ ws.onclose = () => console.log('disconnected');
140
167
 
141
- this.#ws.onerror = (error) => reject(console.error('error: ', error));
142
- this.#ws.onopen = () => {
143
- this.#ws.send(this.auth(this.#token));
144
- this.#ws.send(tv.setLocaleRu());
168
+ ws.onerror = (error) => reject(console.error('error: ', error));
169
+ ws.onopen = () => {
170
+ ws.send(this.auth(this.#token));
171
+ ws.send(tv.setLocaleRu());
145
172
 
146
- // const chartKey = this.createChartSession();
147
173
  const quoteKey = this.createQuoteSmallSession();
148
- // this.addQuoteSymbols({ symbols: ['NASDAQ:PYPL'] });
149
174
 
150
175
  this.messageListner({ result });
151
176
  resolv('open');
@@ -158,24 +183,24 @@ module.exports = class Client {
158
183
  createQuoteSmallSession() {
159
184
  const key = tv.createSession({ startsWith: 'qs_' });
160
185
  this.#quotes.set({ key, data: { id: key, type: 'small', symbols: [] } });
161
- this.#ws.send(tv.quoteCreateSession({ session: key }));
162
- this.#ws.send(tv.setFieldsSmall({ session: key }));
163
- // this.#ws.send(tv.setFields({ session: key }));
186
+ ws.send(tv.quoteCreateSession({ session: key }));
187
+ ws.send(tv.setFieldsSmall({ session: key }));
188
+ // ws.send(tv.setFields({ session: key }));
164
189
  return key;
165
190
  }
166
191
 
167
192
  createQuoteFullSession() {
168
193
  const key = tv.createSession({ startsWith: 'qs_' });
169
194
  this.#quotes.set({ key, data: { id: key, type: 'full', symbols: [] } });
170
- this.#ws.send(tv.quoteCreateSession({ session: key }));
195
+ ws.send(tv.quoteCreateSession({ session: key }));
171
196
  return key;
172
197
  }
173
198
 
174
199
  createChartSession() {
175
200
  const key = tv.createSession({ startsWith: 'cs_' });
176
201
  this.#charts.set({ key, data: { id: key, symbol: '', period: 0, symbolKey: '', frame: '', i: '', deleted: false } });
177
- this.#ws.send(tv.chartCreateSession({ chartSession: key }));
178
- this.#ws.send(tv.switchTimezone({ chartSession: key, tz: 'Etc/UTC' }));
202
+ ws.send(tv.chartCreateSession({ chartSession: key }));
203
+ ws.send(tv.switchTimezone({ chartSession: key, tz: 'Etc/UTC' }));
179
204
  return key;
180
205
  }
181
206
 
@@ -188,9 +213,8 @@ module.exports = class Client {
188
213
  result.exist.push(symbol);
189
214
  } else {
190
215
  key = this.#quotes.add({ symbol });
191
- // console.log(key, symbol);
192
- this.#ws.send(tv.quoteAddSymbol({ session: key, symbol }));
193
- // this.#ws.send(tv.quoteFastSymbol({ session: key, symbol }));
216
+ ws.send(tv.quoteAddSymbol({ session: key, symbol }));
217
+ // ws.send(tv.quoteFastSymbol({ session: key, symbol }));
194
218
  result.add.push(symbol);
195
219
  }
196
220
  });
@@ -201,39 +225,31 @@ module.exports = class Client {
201
225
  const key = this.#quotes.getBySymbol({ symbol });
202
226
  if (!key) return 'unlisted';
203
227
  this.#quotes.delete({ key, symbol });
204
- this.#ws.send(tv.quoteRemoveSymbols({ session: key, symbol }));
228
+ ws.send(tv.quoteRemoveSymbols({ session: key, symbol }));
205
229
  return 'delete';
206
230
  }
207
231
 
208
- resolveSymbol({ key, symbol }) {
209
- const symbolKey = 'sds_sym_' + this.#maxSymbolKey++;
210
- this.#ws.send(tv.resolveSymbol({ chartSession: key, symbolKey, symbol }));
211
- return symbolKey;
212
- }
213
-
214
232
  addChartSymbol({ symbol, period, limit }) {
215
233
  let key = this.#charts.getBySymbolPeriod({ symbol, period });
216
234
  if (key) {
217
- console.warn('addChartSymbol exist');
235
+ console.warn('addChartSymbol exist:', key, symbol, period);
218
236
  return 'exist';
219
237
  }
220
-
221
238
  // console.warn('modules addChartSymbol1', symbol, period, limit, key);
222
- const exist = this.#charts.getDeleted();
223
- if (exist !== null) return this.updateChartSymbol({ symbol, period, limit, last: { symbol: exist.symbol, period: parseInt(exist.period) }});
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) }});
224
241
 
225
242
  key = this.createChartSession();
226
243
  const data = this.#charts.get({ key });
227
244
 
228
- data.symbolKey = this.resolveSymbol({ key, symbol });
245
+ data.symbolKey = this.#symbols.getSymbol({ key, symbol }).key;
229
246
  data.symbol = symbol;
230
247
  data.period = period;
231
248
  data.frame = 'sds_' + Object.keys(this.#charts.values).length;
232
249
  data.i = 's' + 1;
250
+ data.limit = limit;
233
251
 
234
- // this.#ws.send(tv.resolveSymbol({ chartSession: key, symbolKey: data.symbolKey, symbol }));
235
- // this.#resolved.set(symbol, { key: data.symbolKey });
236
- this.#ws.send(
252
+ ws.send(
237
253
  tv.createSeries({
238
254
  chartSession: key,
239
255
  frame: data.frame,
@@ -243,49 +259,56 @@ module.exports = class Client {
243
259
  limit,
244
260
  }),
245
261
  );
246
- // console.log('addChartSymbol4', periods[period], data);
262
+ // console.warn('addChartSymbol4', periods[period], data);
247
263
  this.#charts.set({ key, data });
248
-
249
264
  return 'add';
250
265
  }
251
266
 
252
267
  updateChartSymbol({ symbol, period, limit, last }) {
253
- // period = parseInt(period);
254
- // last.period = parseInt(last.period);
255
268
  const key = this.#charts.getBySymbolPeriod({ symbol: last.symbol, period: last.period });
256
269
  const data = this.#charts.get({ key });
257
270
 
258
271
  // console.warn('modules updateChartSymbol 1: ', symbol, period, limit, last, data);
259
-
260
- const alreadyKey = this.#charts.getBySymbolPeriod({ symbol, period })
261
- if (alreadyKey) {
262
- // console.warn('updateChartSymbol exist: ', alreadyKey);
263
- this.#charts.delete({ key });
264
- console.warn('updateChartSymbol exist');
265
- return 'exist';
266
- }
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
+ // }
267
279
 
268
- data.symbolKey = this.resolveSymbol({ key, symbol });
280
+ data.symbolKey = this.#symbols.getSymbol({ key, symbol }).key;
269
281
  data.symbol = symbol;
270
282
  data.period = period;
271
283
  data.i = 's' + (parseInt(data.i.replace(/[^0-9]/g, '')) + 1);
272
- this.#ws.send(
284
+
285
+ ws.send(
273
286
  tv.modifySeries({
274
287
  chartSession: key,
275
288
  frame: data.frame,
276
289
  increment: data.i,
277
290
  symbolKey: data.symbolKey,
278
291
  interval: periods[period],
279
- limit,
280
292
  }),
281
293
  );
282
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
+ }
283
299
  return 'update';
284
300
  }
285
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
+
286
309
  messageListner({ result }) {
287
- this.#ws.on('message', (raw) => {
288
- if (this.#ws.readyState !== this.#ws.OPEN) return;
310
+ ws.on('message', (raw) => {
311
+ if (ws.readyState !== ws.OPEN) return;
289
312
 
290
313
  // console.log('raw: ', JSON.stringify(raw.toString()));
291
314
  let session = '';
@@ -295,17 +318,13 @@ module.exports = class Client {
295
318
  if (packet === undefined) {
296
319
  console.warn('undefined: ', raw.toString());
297
320
  } else {
298
- // eslint-disable-next-line no-lonely-if
299
321
  if (packet.type === 'ping') {
300
322
  // console.info('pong', packet);
301
- this.#ws.send(tv.createPong({ value: packet.data }));
302
- // } else if (packet.type === 'protocol_error') {
303
- // console.warn('protocol_error', packet);
304
- // this.close();
323
+ ws.send(tv.createPong({ value: packet.data }));
305
324
  } else if (packet.type === 'qsd') {
306
325
  send = packet.data[1].v;
307
326
  name = send.bid === undefined && send.ask === undefined ? 'data' : 'levelI';
308
- // console.log(packet.data[1].n);
327
+ // console.warn(packet.data[1]);
309
328
  // console.log(JSON.parse(packet.data[1].n.substring(1)).symbol);
310
329
  send.symbol = JSON.parse(packet.data[1].n.substring(1)).symbol;
311
330
  result(name, send);
@@ -334,12 +353,12 @@ module.exports = class Client {
334
353
  } else if (['series', 'symbol', 'quote', 'session'].includes(packet.type)) {
335
354
  // console.info(packet);
336
355
  } else {
337
- console.warn('error', raw.toString());
356
+ // console.error('error', raw.toString());
338
357
  result('error', raw.toString())
339
358
  }
340
359
  }
341
- name = null;
342
- send = null;
360
+ // name = null;
361
+ // send = null;
343
362
  });
344
363
  });
345
364
  }
@@ -35,7 +35,7 @@ class TradingView {
35
35
  // }
36
36
 
37
37
  // await utils.pause();
38
- return 'eyJhbGciOiJSUzUxMiIsImtpZCI6IkdaeFUiLCJ0eXAiOiJKV1QifQ.eyJ1c2VyX2lkIjoxMjI1ODcxMiwiZXhwIjoxNjkwNzkzMjIwLCJpYXQiOjE2OTA3Nzg4MjAsInBsYW4iOiJwcm9fcHJlbWl1bSIsImV4dF9ob3VycyI6MSwicGVybSI6IiIsInN0dWR5X3Blcm0iOiJ0di1jaGFydF9wYXR0ZXJucyx0di1jaGFydHBhdHRlcm5zLHR2LXByb3N0dWRpZXMsdHYtdm9sdW1lYnlwcmljZSIsIm1heF9zdHVkaWVzIjoyNSwibWF4X2Z1bmRhbWVudGFscyI6MCwibWF4X2NoYXJ0cyI6OCwibWF4X2FjdGl2ZV9hbGVydHMiOjQwMCwibWF4X3N0dWR5X29uX3N0dWR5IjoyNCwibWF4X2FjdGl2ZV9wcmltaXRpdmVfYWxlcnRzIjo0MDAsIm1heF9hY3RpdmVfY29tcGxleF9hbGVydHMiOjQwMCwibWF4X2Nvbm5lY3Rpb25zIjo1MH0.pZQgM_oTZMnm1Qb4qBf6CfM9dHKltp2T3O2g_VVoK9l66UngEL8mLdeH7-ZpUZ8Y50rV5yr0ND8WRPsRH2w2izk_SNMD63p6GJzXXGPvILgirXW3SFa7HmaHv8Xp6SPhQTWb-ahyv_2GUIueKTvHWBNF5-eBnqYeoXQeWkRFsLA';
38
+ return 'eyJhbGciOiJSUzUxMiIsImtpZCI6IkdaeFUiLCJ0eXAiOiJKV1QifQ.eyJ1c2VyX2lkIjoxMjI1ODcxMiwiZXhwIjoxNzI0OTI1MjkyLCJpYXQiOjE3MjQ5MTA4OTIsInBsYW4iOiJwcm9fcHJlbWl1bSIsImV4dF9ob3VycyI6MSwicGVybSI6InVzLXN0b2NrcyxuYXNkYXFfZ2lkcyxvdGMsbnlzZSxuYXNkYXEsYW1leCIsInN0dWR5X3Blcm0iOiJ0di1jaGFydHBhdHRlcm5zLHR2LXByb3N0dWRpZXMsdHYtY2hhcnRfcGF0dGVybnMsdHYtdm9sdW1lYnlwcmljZSIsIm1heF9zdHVkaWVzIjoyNSwibWF4X2Z1bmRhbWVudGFscyI6MTAsIm1heF9jaGFydHMiOjgsIm1heF9hY3RpdmVfYWxlcnRzIjo0MDAsIm1heF9zdHVkeV9vbl9zdHVkeSI6MjQsImZpZWxkc19wZXJtaXNzaW9ucyI6WyJyZWZib25kcyJdLCJtYXhfb3ZlcmFsbF9hbGVydHMiOjIwMDAsIm1heF9hY3RpdmVfcHJpbWl0aXZlX2FsZXJ0cyI6NDAwLCJtYXhfYWN0aXZlX2NvbXBsZXhfYWxlcnRzIjo0MDAsIm1heF9jb25uZWN0aW9ucyI6NTB9.UT2AdPBEAWk6HJEa6isX4gjVqlfThn8bgOVl3Xa36U36Qifg5xXz9Va8q7DWSY3Smaap2wX4cBF4UQXv1t66Q0TQvFudLuvA2dnetBAHYZSOJIi2PGdG1KuMaCRshUuuH9mxgw_xPGITAuQsbBPZJLTOxq5pQN05pZnedC7SaMs';
39
39
  }
40
40
 
41
41
  async getSymbol({ symbol, type }) {
@@ -59,9 +59,7 @@ class TradingView {
59
59
 
60
60
  createSession({ startsWith }) {
61
61
  let session = startsWith;
62
- while (session.length < 12) {
63
- session += letters[Math.floor(Math.random() * letters.length)];
64
- }
62
+ while (session.length < 12) session += letters[Math.floor(Math.random() * letters.length)];
65
63
  return session;
66
64
  }
67
65
 
@@ -173,6 +171,8 @@ class TradingView {
173
171
  'logoid',
174
172
  'lp',
175
173
  'lp_time',
174
+ 'rtc',
175
+ 'rtc_time',
176
176
  'trade',
177
177
  'bid',
178
178
  'bid_size',
@@ -266,10 +266,10 @@ class TradingView {
266
266
  // symbolKey - id запрошенного тиккера
267
267
  // frame - рамка или окно для данной серии
268
268
  // increment - инкрементируемый номер изменений запрашиваемого графика в данном frame (таймефрейм)
269
- createSeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60', limit = 1000 }) {
269
+ createSeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, period = '60', limit = 1000 }) {
270
270
  // console.warn('createSeries', chartSession, frame, increment, symbolKey, interval, limit);
271
271
  return this.formatWSPacket({
272
- packet: { m: 'create_series', p: [chartSession, frame, increment, symbolKey, interval, limit] },
272
+ packet: { m: 'create_series', p: [chartSession, frame, increment, symbolKey, period, limit] },
273
273
  });
274
274
  }
275
275
 
@@ -284,13 +284,22 @@ class TradingView {
284
284
  return this.formatWSPacket({ packet: { m: 'remove_study', p: [ session, st ] } });
285
285
  }
286
286
 
287
- modifySeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60', limit = 1000 }) {
287
+ modifySeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60' }) {
288
288
  // console.warn('modify_series', chartSession, frame, increment, symbolKey, interval, limit);
289
289
  return this.formatWSPacket({
290
290
  packet: { m: 'modify_series', p: [chartSession, frame, increment, symbolKey, interval] },
291
291
  });
292
292
  }
293
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
+
294
303
  createPong({ value }) {
295
304
  return this.formatWSPacket({ packet: '~h~' + value });
296
305
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "market-data-tradingview-ws",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "marketData from Tradingview ws",
5
5
  "main": "index.js",
6
6
  "scripts": {