market-data-tradingview-ws 0.0.2 → 0.0.4

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/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use strict';
2
+
1
3
  const Client = require('./lib/client.js');
2
4
 
3
5
  exports.Client = Client;
package/lib/client.js CHANGED
@@ -1,50 +1,93 @@
1
- const WebSocket = require('ws');
2
- const tradingView = require('./tradingView.js');
3
-
4
- const tv = new tradingView();
1
+ /* eslint-disable prefer-const */
2
+ /* eslint-disable no-unused-vars */
3
+ 'use strict';
5
4
 
6
- const sessions = {
7
- values: new Map(),
5
+ const WebSocket = require('ws');
6
+ const tv = require('./tradingView.js');
8
7
 
8
+ const quotes = {
9
+ values: {},
9
10
  set({ key, data }) {
10
11
  if (data) {
11
- this.values.set(key, data);
12
+ this.values[key] = data;
13
+ }
14
+ },
15
+ add({ symbol }) {
16
+ for (let key in this.values) {
17
+ this.values[key].symbols.push(symbol);
18
+ return key;
12
19
  }
20
+ return null;
13
21
  },
14
22
  get({ key }) {
15
- return this.values.get(key);
23
+ return this.values[key];
16
24
  },
17
- getKeys() {
18
- return this.values.keys();
25
+ getBySymbol({ symbol }) {
26
+ for (let key in this.values) {
27
+ if (this.values[key].symbols.includes(symbol)) return key;
28
+ }
29
+ return null;
19
30
  },
20
- getKeyByType({ type }) {
21
- let session = '';
22
- this.values.forEach((value, key) => {
23
- if (type === value.type) session = key;
24
- });
25
- return session;
31
+ delete({ key, symbol }) {
32
+ const arr = this.values[key].symbols;
33
+ const index = arr.indexOf(symbol);
34
+ if (index !== -1) arr.splice(index, 1);
35
+ },
36
+ };
37
+
38
+ const charts = {
39
+ values: {},
40
+ set({ key, data }) {
41
+ if (data) {
42
+ this.values[key] = data;
43
+ }
44
+ },
45
+ get({ key }) {
46
+ return this.values[key];
47
+ },
48
+ getBySymbolPeriod({ symbol, period }) {
49
+ for (let key of Object.keys(this.values)) {
50
+ if (this.values[key].symbol === symbol && this.values[key].period === period) return key;
51
+ }
52
+ return null;
26
53
  },
27
54
  };
28
55
 
56
+ const periods = {
57
+ 60: '1',
58
+ 300: '5',
59
+ 900: '15',
60
+ 1800: '30',
61
+ 3600: '60',
62
+ 14400: '240',
63
+ 86400: '1D',
64
+ };
65
+
29
66
  module.exports = class Client {
30
67
  #ws;
31
- #sessions; // = new Map();
68
+ #charts;
69
+ #quotes;
70
+ #resolved;
32
71
  #token = null;
72
+ maxSymbolKey = 0;
33
73
  constructor() {
34
- this.#sessions = sessions;
74
+ this.#charts = charts;
75
+ this.#quotes = quotes;
76
+ this.#resolved = new Map();
35
77
  }
36
78
 
37
79
  close() {
80
+ // console.log(this.#sessions.values, this.#charts.values, this.#quotes.values);
38
81
  this.#ws.close();
39
82
  }
40
83
 
41
- getSession({ key }) {
42
- return this.#sessions.get({ key });
84
+ getAll() {
85
+ return { quotes: this.#quotes.values, charts: this.#charts.values };
43
86
  }
44
87
 
45
- getSessionKeys() {
46
- return this.#sessions.values.keys();
47
- }
88
+ // getSessionKeys() {
89
+ // return this.#sessions.values.keys();
90
+ // }
48
91
 
49
92
  async getToken({ login, pass }) {
50
93
  return tv.getToken({ login, pass });
@@ -75,42 +118,125 @@ module.exports = class Client {
75
118
  };
76
119
  });
77
120
  }
121
+ return null;
78
122
  }
79
123
 
80
- createSession({ type }) {
81
- const startsWith = type === 'chart' ? 'cs_' : 'qs_';
82
- const key = tv.createSession({ startsWith });
83
- const session = sessions.set({ key, data: { type, symbols: [] } });
84
- // console.log(key, session);
85
- if (type === 'chart') {
86
- this.#ws.send(tv.wsCreateChartSession({ chartSession: key }));
87
- this.#ws.send(tv.switchTimezone({ chartSession: key, tz: 'Etc/UTC' }));
88
- } else {
89
- this.#ws.send(tv.wsQuoteCreateSession({ session: key }));
90
- this.#ws.send(tv.setFieldsChart({ session: key }));
91
- }
92
- return session;
124
+ createQuoteSession() {
125
+ const key = tv.createSession({ startsWith: 'qs_' });
126
+ this.#quotes.set({ key, data: { id: key, symbols: [] } });
127
+ this.#ws.send(tv.wsQuoteCreateSession({ session: key }));
128
+ this.#ws.send(tv.setFieldsChart({ session: key }));
129
+ return key;
93
130
  }
94
131
 
95
- addQuoteSymbols({ symbolIds }) {
96
- const key = this.#sessions.getKeyByType({ type: 'quote' });
97
- this.#ws.send(tv.quoteAddSymbols({ session: key, symbolIds }));
132
+ createChartSession() {
133
+ const key = tv.createSession({ startsWith: 'cs_' });
134
+ this.#charts.set({ key, data: { id: key, symbol: '', period: '', symbolKey: '', frame: '', i: '' } });
135
+ this.#ws.send(tv.wsCreateChartSession({ chartSession: key }));
136
+ this.#ws.send(tv.switchTimezone({ chartSession: key, tz: 'Etc/UTC' }));
137
+ return key;
138
+ }
139
+
140
+ addQuoteSymbols({ symbols }) {
141
+ const result = { add: [], exist: [] };
142
+ if (Object.keys(this.#quotes.values).length === 0) this.createQuoteSession();
143
+ symbols.forEach((symbol) => {
144
+ let key = this.#quotes.getBySymbol({ symbol });
145
+ if (key) {
146
+ result.exist.push(symbol);
147
+ } else {
148
+ key = this.#quotes.add({ symbol });
149
+ console.log(key, symbol);
150
+ this.#ws.send(tv.quoteAddSymbols({ session: key, symbols: [symbol] }));
151
+ // this.#ws.send(tv.quoteFastSymbols({ session: key, symbols }));
152
+ result.add.push(symbol);
153
+ }
154
+ });
155
+ return result;
156
+ }
98
157
 
99
- const data = this.#sessions.get({ key });
100
- // console.log(key, data);
101
- symbolIds.forEach((each) => data.symbols.push(each));
102
- this.#sessions.set({ key, data });
158
+ deleteQuoteSymbol({ symbol }) {
159
+ const key = this.#quotes.getBySymbol({ symbol });
160
+ if (!key) return 'unlisted';
161
+ this.#quotes.delete({ key, symbol });
162
+ this.#ws.send(tv.quoteRemoveSymbols({ session: key, symbol }));
163
+ return 'delete';
164
+ }
165
+
166
+ addChartSymbol({ symbol, period, limit }) {
167
+ let key = this.#charts.getBySymbolPeriod({ symbol, period });
168
+ if (key) return 'exist';
169
+ console.log('addChartSymbol', symbol, period, limit, key);
170
+ key = this.createChartSession();
171
+ const data = this.#charts.get({ key });
172
+
173
+ data.symbol = symbol;
174
+ data.period = period;
175
+ data.symbolKey = 'sds_sym_' + ++this.maxSymbolKey;
176
+ data.frame = 'sds_' + Object.keys(this.#charts.values).length;
177
+ data.i = 's' + 1;
178
+
179
+ this.#ws.send(tv.resolveSymbol({ chartSession: key, symbolKey: data.symbolKey, symbol }));
180
+ this.#resolved.set(symbol, { key: data.symbolKey });
181
+ this.#ws.send(
182
+ tv.createSeries({
183
+ chartSession: key,
184
+ frame: data.frame,
185
+ increment: data.i,
186
+ symbolKey: data.symbolKey,
187
+ interval: periods[period],
188
+ limit,
189
+ }),
190
+ );
191
+ console.log('addChartSymbol1', periods[period], data);
192
+ this.#charts.set({ key, data });
193
+
194
+ return 'add';
195
+ }
196
+
197
+ updateChartSymbol({ symbol, period, limit, exist }) {
198
+ let key = this.#charts.getBySymbolPeriod({ symbol: exist.symbol, period: exist.period });
199
+ const data = this.#charts.get({ key });
200
+
201
+ console.log('updateChartSymbol', symbol, exist.symbol, data);
202
+
203
+ if (this.#resolved.has(symbol)) {
204
+ data.symbolKey = this.#resolved.get(symbol).key;
205
+ } else {
206
+ data.symbolKey = 'sds_sym_' + ++this.maxSymbolKey;
207
+ this.#ws.send(tv.resolveSymbol({ chartSession: key, symbolKey: data.symbolKey, symbol }));
208
+ this.#resolved.set(symbol, { key: data.symbolKey });
209
+ }
210
+
211
+ data.symbol = symbol;
212
+ data.period = period;
213
+ data.i = 's' + (parseInt(data.i.replace(/[^0-9]/g, '')) + 1);
214
+ this.#ws.send(
215
+ tv.modifySeries({
216
+ chartSession: key,
217
+ frame: data.frame,
218
+ increment: data.i,
219
+ symbolKey: data.symbolKey,
220
+ interval: periods[period],
221
+ limit,
222
+ }),
223
+ );
224
+ console.log('updateChartSymbol1', key, data);
225
+ this.#charts.set({ key, data });
226
+ return 'update';
103
227
  }
104
228
 
105
229
  messageListner({ result }) {
106
230
  this.#ws.on('message', (raw) => {
107
231
  if (this.#ws.readyState !== this.#ws.OPEN) return;
108
232
 
233
+ // console.log('raw: ', JSON.stringify(raw.toString()));
109
234
  let session = '';
110
235
  tv.parsePacket({ str: raw }).forEach((packet) => {
111
236
  if (packet === undefined) {
112
237
  console.log('undefined: ', raw.toString());
113
238
  } else {
239
+ // eslint-disable-next-line no-lonely-if
114
240
  if (packet.type === 'ping') {
115
241
  // console.info('pong', packet);
116
242
  this.#ws.send(tv.createPong({ value: packet.data }));
@@ -118,39 +244,39 @@ module.exports = class Client {
118
244
  console.warn('protocol_error', packet);
119
245
  this.close();
120
246
  } else if (packet.type === 'qsd') {
121
- session = sessions.get({ key: packet.data[0] });
122
- // console.log('qsd', packet.data, session);
123
247
  const send = packet.data[1].v;
248
+ const name = send.bid !== undefined && send.ask !== undefined ? 'levelI' : 'data';
124
249
  send.symbol = packet.data[1].n;
125
- // console.log(JSON.stringify([packet.type, send]));
126
- result({ packet: send });
250
+ result(name, send);
127
251
  } else if (['du', 'timescale_update'].includes(packet.type)) {
128
- session = sessions.get({ key: packet.data[0] });
129
- // console.log('du', packet.data, session);
130
- result({ packet });
131
- // const arr = [];
132
- // for (var key in packet.data[1].s1.s) {
133
- // const send = {
134
- // symbol: session.symbolId,
135
- // end: packet.data[1].s1.s[key + 1] !== undefined ? packet.data[1].s1.s[key + 1].v[0] : packet.data[1].s1.lbs.bar_close_time,
136
- // };
137
- // console.log(key, packet.data[1].s1.s);
138
- // [send.start, send.open, send.low, send.high, send.close, send.passed] = packet.data[1].s1.s[key].v;
139
- // console.log(send);
140
- // arr.push(send);
141
- // }
142
- // [send.start, send.open, send.low, send.high, send.close, send.passed] = packet.data[1].s1.s.v;
143
- // console.log(JSON.stringify([packet.type, arr]));
144
- } else if (['series', 'symbol', 'quote'].includes(packet.type)) {
145
- console.info(packet);
252
+ session = this.#charts.get({ key: packet.data[0] });
253
+ if (packet.data[1][session.frame].s.length > 0) {
254
+ const send = {
255
+ symbol: session.symbol,
256
+ period: session.period,
257
+ chart: [],
258
+ end: packet.data[1][session.frame].lbs.bar_close_time,
259
+ };
260
+ for (let each of packet.data[1][session.frame].s) {
261
+ send.chart.push({
262
+ open: each.v[1],
263
+ high: each.v[2],
264
+ low: each.v[3],
265
+ close: each.v[4],
266
+ timestamp: each.v[0] * 1000,
267
+ // turnover: bar.TradeCount,
268
+ volume: each.v[5],
269
+ });
270
+ }
271
+ result(packet.type === 'du' ? 'chart_update' : 'chart_history', send);
272
+ }
273
+ } else if (['series', 'symbol', 'quote', 'session'].includes(packet.type)) {
274
+ // console.info(packet);
146
275
  } else {
147
276
  console.warn('error', raw.toString());
148
277
  }
149
- // else {
150
- // console.log('received: %s', raw);
151
- // }
152
278
  }
153
279
  });
154
280
  });
155
281
  }
156
- }
282
+ };
@@ -1,12 +1,15 @@
1
- const Utils = require('./utils.js');
2
- const u = new Utils();
1
+ /* eslint-disable no-unused-vars */
2
+ 'use strict';
3
+
4
+ // const Utils = require('./utils.js');
5
+ // const utils = new Utils();
3
6
 
4
7
  const letters = 'abcdefghijklmnopqrstuvwxyz';
5
8
  const cleanerRgx = /~h~/g;
6
9
  const splitterRgx = /~m~[0-9]{1,}~m~/g;
7
10
  const urlSymbolSearch = 'https://symbol-search.tradingview.com/symbol_search';
8
11
 
9
- module.exports = class tradingView {
12
+ class TradingView {
10
13
  async getToken({ login, pass }) {
11
14
  const url = 'https://www.tradingview.com/accounts/signin/';
12
15
  const headers = {
@@ -31,7 +34,7 @@ module.exports = class tradingView {
31
34
  // return data.user.auth_token;
32
35
  // }
33
36
 
34
- // await u.pause();
37
+ // await utils.pause();
35
38
  return 'eyJhbGciOiJSUzUxMiIsImtpZCI6IkdaeFUiLCJ0eXAiOiJKV1QifQ.eyJ1c2VyX2lkIjoxMjI1ODcxMiwiZXhwIjoxNjkwNzkzMjIwLCJpYXQiOjE2OTA3Nzg4MjAsInBsYW4iOiJwcm9fcHJlbWl1bSIsImV4dF9ob3VycyI6MSwicGVybSI6IiIsInN0dWR5X3Blcm0iOiJ0di1jaGFydF9wYXR0ZXJucyx0di1jaGFydHBhdHRlcm5zLHR2LXByb3N0dWRpZXMsdHYtdm9sdW1lYnlwcmljZSIsIm1heF9zdHVkaWVzIjoyNSwibWF4X2Z1bmRhbWVudGFscyI6MCwibWF4X2NoYXJ0cyI6OCwibWF4X2FjdGl2ZV9hbGVydHMiOjQwMCwibWF4X3N0dWR5X29uX3N0dWR5IjoyNCwibWF4X2FjdGl2ZV9wcmltaXRpdmVfYWxlcnRzIjo0MDAsIm1heF9hY3RpdmVfY29tcGxleF9hbGVydHMiOjQwMCwibWF4X2Nvbm5lY3Rpb25zIjo1MH0.pZQgM_oTZMnm1Qb4qBf6CfM9dHKltp2T3O2g_VVoK9l66UngEL8mLdeH7-ZpUZ8Y50rV5yr0ND8WRPsRH2w2izk_SNMD63p6GJzXXGPvILgirXW3SFa7HmaHv8Xp6SPhQTWb-ahyv_2GUIueKTvHWBNF5-eBnqYeoXQeWkRFsLA';
36
39
  }
37
40
 
@@ -97,18 +100,23 @@ module.exports = class tradingView {
97
100
  return { type: 'ping', data: packet }; // Ping
98
101
  } else if (packet.m && packet.p) {
99
102
  // Normal packet
100
- if (packet.m.startsWith('du')) return { type: packet.m, data: packet.p };
101
- if (packet.m.startsWith('timescale') || packet.m.startsWith('qsd')) return { type: packet.m, data: packet.p };
103
+ // if (packet.m.startsWith('du')) return { type: packet.m, data: packet.p };
104
+ if (packet.m.startsWith('timescale') || packet.m.startsWith('qsd') || packet.m.startsWith('du'))
105
+ return { type: packet.m, data: packet.p };
106
+ // return new Map([
107
+ // ['type', packet.m],
108
+ // ['data', packet.p],
109
+ // ]);
102
110
  if (packet.m.startsWith('series') || packet.m.startsWith('symbol') || packet.m.startsWith('quote')) {
103
111
  const type = packet.m.split('_');
104
112
  return { type: type[0], data: { sub: type[1], detail: packet.p, time: packet.t_ms ? packet.t_ms : Date.now() } };
105
113
  } else {
106
- return { type: 'msg', data: parsed.data };
114
+ return { type: 'msg', data: packet.data };
107
115
  }
108
116
  // const session = packet.p[0];
109
117
 
110
118
  // if (session && this.#sessions[session]) {
111
- // this.#sessions[session].onData(parsed);
119
+ // this.#sessions[session].onData(packet);
112
120
  //
113
121
  // }
114
122
  } else if (packet.session_id) {
@@ -175,39 +183,57 @@ module.exports = class tradingView {
175
183
  });
176
184
  }
177
185
 
178
- quoteAddSymbols({ session, symbolIds }) {
179
- return this.formatWSPacket({ packet: { m: 'quote_add_symbols', p: [session, ...symbolIds] } });
186
+ quoteAddSymbols({ session, symbols }) {
187
+ console.log('quoteAddSymbols', session, symbols);
188
+ return this.formatWSPacket({ packet: { m: 'quote_add_symbols', p: [session, ...symbols] } });
180
189
  }
181
190
 
182
- quoteRemoveSymbols({ session, symbolId }) {
183
- return this.formatWSPacket({ packet: { m: 'quote_remove_symbols', p: [session, symbolId] } });
191
+ quoteFastSymbols({ session, symbols }) {
192
+ console.log('quoteFastSymbols', session, symbols);
193
+ return this.formatWSPacket({
194
+ packet: { m: 'quote_fast_symbols', p: [session, '={"adjustment":"splits","currency-id":"USD","symbol":"BATS:PYPL"}', ...symbols] },
195
+ });
196
+ }
197
+
198
+ quoteRemoveSymbols({ session, symbol }) {
199
+ return this.formatWSPacket({ packet: { m: 'quote_remove_symbols', p: [session, symbol] } });
184
200
  }
185
201
 
186
202
  switchTimezone({ chartSession, tz = 'Etc/UTC' }) {
187
203
  return this.formatWSPacket({ packet: { m: 'switch_timezone', p: [chartSession, tz] } });
188
204
  }
189
205
 
190
- resolveSymbol({ chartSession, rSymbolId, symbolId }) {
206
+ resolveSymbol({ chartSession, symbolKey, symbol }) {
207
+ console.log('resolveSymbol', chartSession, symbolKey, symbol);
191
208
  return this.formatWSPacket({
192
209
  packet: {
193
210
  m: 'resolve_symbol',
194
- p: [chartSession, rSymbolId, '={"symbol":"' + symbolId + '","adjustment":"splits","session":"extended"}'],
211
+ p: [chartSession, symbolKey, '=' + JSON.stringify({ symbol, adjustment: 'splits', session: 'extended' })],
195
212
  },
196
213
  });
197
214
  }
198
215
 
199
- createSeries({ chartSession, id = 1, interval = '60', total_candle = 1000 }) {
216
+ // symbolKey - id запрошенного тиккера
217
+ // frame - рамка или окно для данной серии
218
+ // increment - инкрементируемый номер изменений запрашиваемого графика в данном frame (таймефрейм)
219
+ createSeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60', limit = 1000 }) {
220
+ console.log('createSeries', chartSession, frame, increment, symbolKey, interval, limit);
200
221
  return this.formatWSPacket({
201
- packet: { m: 'create_series', p: [chartSession, 's' + id, 's' + id, 'symbol_1', interval, total_candle] },
222
+ packet: { m: 'create_series', p: [chartSession, frame, increment, symbolKey, interval, limit] },
202
223
  });
203
224
  }
204
225
 
205
- modifySeries({ chartSession, rSymbolId, symbolId }) {
226
+ // study = {id: st1 (st2, st3, st4 ...), name: 'Volume@tv-basicstudies-221', details: { length: 20, col_prev_close: false}
227
+ createStudy({ chartSession, study, series = 'st1', frame = 'sds_1' }) {
206
228
  return this.formatWSPacket({
207
- packet: {
208
- m: 'resolve_symbol',
209
- p: [chartSession, 'symbol_' + id, '={"symbol":"' + symbolId + '","adjustment":"splits","session":"extended"}'],
210
- },
229
+ packet: { m: 'create_study', p: [chartSession, study.id, series, frame, study.name, study.details] },
230
+ });
231
+ }
232
+
233
+ modifySeries({ chartSession, frame = 'sds_1', increment = 's1', symbolKey, interval = '60', limit = 1000 }) {
234
+ console.log('modify_series', chartSession, frame, increment, symbolKey, interval, limit);
235
+ return this.formatWSPacket({
236
+ packet: { m: 'modify_series', p: [chartSession, frame, increment, symbolKey, interval] },
211
237
  });
212
238
  }
213
239
 
@@ -215,3 +241,5 @@ module.exports = class tradingView {
215
241
  return this.formatWSPacket({ packet: '~h~' + value });
216
242
  }
217
243
  }
244
+
245
+ module.exports = new TradingView();
package/lib/utils.js CHANGED
@@ -1,3 +1,4 @@
1
+ 'use strict';
1
2
  // import https from 'https';
2
3
 
3
4
  module.exports = class Utils {
@@ -36,4 +37,4 @@ module.exports = class Utils {
36
37
  // req.end(content);
37
38
  // });
38
39
  // }
39
- }
40
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "market-data-tradingview-ws",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "marketData from Tradingview ws",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/old.js DELETED
@@ -1,141 +0,0 @@
1
- 'use strict';
2
-
3
- process.title = 'socket_client';
4
-
5
- const urlWS = 'wss://data.tradingview.com/socket.io/websocket';
6
-
7
- const login = 'sulimenko@ptfin.kz';
8
- const pass = '7n8zGZ8v27pH';
9
- const token = '';
10
- const interval = '5';
11
- const total_candle = 100;
12
-
13
- const stop = async () => {
14
- const closed = new Promise((resolve) => {
15
- setTimeout(() => {
16
- resolve(console.log('exit'));
17
- }, 1000);
18
- });
19
-
20
- for (const sessionKey of sessions.values.keys()) {
21
- sessions.values.delete(sessionKey);
22
- console.log('session clear: ', sessionKey);
23
- }
24
- socket.close();
25
- await closed;
26
- process.exit(1);
27
- };
28
-
29
- function changeWSSymbol({ key, chartkey, symbolId }) {
30
- const s = sessions.get({ key });
31
- const c = sessions.get({ key: chartkey });
32
- const queue = [];
33
-
34
- // console.log(s, symbolId, id, c, chartkey, sessions);
35
- if (s.symbolId) queue.push(tv.removeSymbols({ session: s.main, symbolId: s.symbolId }));
36
- queue.push(tv.addSymbols({ session: s.main, symbolId }));
37
- queue.push(tv.resolveSymbol({ chartSession: c.main, id, symbolId }));
38
-
39
- queue.forEach((each) => {
40
- console.log(each);
41
- socket.send(each);
42
- });
43
- id++;
44
- sessions.set({ key, val: { main: key, symbolId } });
45
- sessions.set({ key: chartkey, val: { main: chartkey, symbolId } });
46
- }
47
-
48
- (async () => {
49
-
50
- // const data = await tv.getSymbol({ symbol: 'TSLA', type: 'stock' }); // NASDAQ:TSLA
51
- // const data = await tv.getSymbol({ symbol: 'MRNA', type: 'stock' }); // NASDAQ:MRNA
52
- const data = await tv.getSymbol({ symbol: 'BTCUSDT', type: 'crypto' });
53
- // console.log('symbol: ', data);
54
-
55
- const symbolId = tv.getSymbolId({ data });
56
- console.log(symbolId);
57
-
58
- socket = new WebSocket(urlWS, { origin: 'https://data.tradingview.com' });
59
- // // const socket = new WebSocket('wss://data.tradingview.com/socket.io/websocket?&type=chart', { origin: 'https://s.tradingview.com' });
60
-
61
- const sessionKey = tv.createSession({ startsWith: 'qs_' });
62
- const chartSessionKey = tv.createSession({ startsWith: 'cs_' });
63
- sessions.set({ key: sessionKey, val: { main: sessionKey } });
64
- sessions.set({ key: chartSessionKey, val: { main: chartSessionKey } });
65
- let session = sessions.get({ key: sessionKey });
66
- let chartSession = sessions.get({ key: chartSessionKey });
67
- // console.log(session);
68
-
69
- socket.on('open', (e) => {
70
- console.log('open');
71
- socket.send(auth());
72
-
73
- socket.send(tv.wsCreateChartSession({ chartSession: chartSession.main }));
74
- socket.send(tv.switchTimezone({ chartSession: chartSession.main, tz: 'Etc/UTC' }));
75
- socket.send(tv.wsCreateSession({ session: session.main }));
76
- // socket.send(tv.resolveSymbol({ chartSession, id: 1, symbolId }));
77
- changeWSSymbol({ key: session.main, chartkey: chartSession.main, symbolId });
78
-
79
- socket.send(tv.setFieldsChart({ session: session.main }));
80
- socket.send(tv.createSeries({ chartSession: chartSession.main, id: 1, interval, total_candle }));
81
-
82
- // setTimeout(() => {
83
- // addWSSymbol({ key: session.main, symbolId: 'NASDAQ:TSLA' });
84
- setTimeout(() => {
85
- changeWSSymbol({ key: session.main, chartkey: chartSession.main, symbolId: 'NASDAQ:TSLA' });
86
- }, 10000);
87
- // }, 10000);
88
- });
89
-
90
- socket.on('message', (raw) => {
91
- const response = tv.parsePacket({ readyState: socket.readyState, str: raw });
92
- // console.log(response, response === undefined);
93
- response.forEach((packet) => {
94
- // console.log(packet);
95
- if (packet === undefined) {
96
- console.log('undefined: ', raw.toString());
97
- } else {
98
- if (packet.type === 'ping') {
99
- // console.log('pong', packet);
100
- socket.send(tv.createPong({ value: packet.data }));
101
- } else if (packet.type === 'protocol_error') {
102
- console.log('protocol_error', packet);
103
- socket.close();
104
- } else if (packet.type === 'qsd') {
105
- session = sessions.get({ key: packet.data[0] });
106
- // console.log(packet.data, session, sessions);
107
- const send = packet.data[1].v;
108
- send.symbol = session.symbolId;
109
- console.log(JSON.stringify([packet.type, send]));
110
- } else if (['du', 'timescale_update'].includes(packet.type)) {
111
- session = sessions.get({ key: packet.data[0] });
112
- // console.log(packet.data, session, sessions);
113
- const arr = [];
114
- for (var key in packet.data[1].s1.s) {
115
- const send = {
116
- symbol: session.symbolId,
117
- end: packet.data[1].s1.s[key + 1] !== undefined ? packet.data[1].s1.s[key + 1].v[0] : packet.data[1].s1.lbs.bar_close_time,
118
- };
119
- // console.log(key, packet.data[1].s1.s);
120
- [send.start, send.open, send.low, send.high, send.close, send.passed] = packet.data[1].s1.s[key].v;
121
- // console.log(send);
122
- arr.push(send);
123
- }
124
- // [send.start, send.open, send.low, send.high, send.close, send.passed] = packet.data[1].s1.s.v;
125
- console.log(JSON.stringify([packet.type, arr]));
126
- } else {
127
- console.log('error', raw.toString());
128
- }
129
- // else {
130
- // console.log('received: %s', raw);
131
- // }
132
- }
133
- });
134
- });
135
- // // setTimeout(async () => {
136
- // // console.log('exit');
137
- // // }, 3000);
138
-
139
- process.on('SIGINT', stop);
140
- process.on('SIGTERM', stop);
141
- })();
package/server.js DELETED
@@ -1,91 +0,0 @@
1
- 'use strict';
2
-
3
- process.title = 'marketDataClient';
4
-
5
- const Client = './lib/client.js';
6
- const Utils = './lib/utils.js';
7
- const u = new Utils();
8
-
9
- const url = 'wss://data.tradingview.com/socket.io/websocket';
10
- const options = { origin: 'https://data.tradingview.com' };
11
-
12
- const login = 'sulimenko@ptfin.kz';
13
- const pass = '7n8zGZ8v27pH';
14
-
15
- const interval = '5';
16
- const total_candle = 100;
17
-
18
- const marketData = new Client();
19
-
20
- const clients = new Map();
21
- const symbolQuotes = new Map();
22
-
23
- const stop = async () => {
24
- const closed = new Promise((resolve) => {
25
- setTimeout(() => {
26
- resolve(console.log('exit'));
27
- }, 1000);
28
- });
29
-
30
- // for (const sessionKey of marketData.getSessionKeys()) {
31
- // let data = marketData.getSession({ key: sessionKey });
32
- // console.log('session clear: ', sessionKey, data);
33
- // }
34
- marketData.close();
35
- await closed;
36
- console.log(clients, symbolQuotes);
37
- process.exit(1);
38
- };
39
-
40
- const result = ({ packet }) => {
41
- let data = symbolQuotes.get(packet.symbol);
42
- if (!data) data = {};
43
- Object.keys(packet).forEach((key) => {
44
- // console.log(key, data, packet);
45
- data[key] = packet[key];
46
- });
47
- symbolQuotes.set(packet.symbol, data);
48
-
49
- clients.forEach((each) => {
50
- if (each.quote.includes(packet.symbol)) {
51
- each.client({ acc: each.acc, packet });
52
- }
53
- });
54
- };
55
-
56
- // function changeWSSymbol({ key, chartkey, symbolId }) {
57
- // const s = sessions.get({ key });
58
- // const c = sessions.get({ key: chartkey });
59
- // const queue = [];
60
-
61
- // // console.log(s, symbolId, id, c, chartkey, sessions);
62
- // if (s.symbolId) queue.push(tv.removeSymbols({ session: s.main, symbolId: s.symbolId }));
63
- // queue.push(tv.addSymbols({ session: s.main, symbolId }));
64
- // queue.push(tv.resolveSymbol({ chartSession: c.main, id, symbolId }));
65
-
66
- // queue.forEach((each) => {
67
- // console.log(each);
68
- // socket.send(each);
69
- // });
70
- // id++;
71
- // sessions.set({ key, val: { main: key, symbolId } });
72
- // sessions.set({ key: chartkey, val: { main: chartkey, symbolId } });
73
- // }
74
-
75
- (async () => {
76
- clients.set('123', { acc: '123', quote: ['NASDAQ:TSLA', 'NASDAQ:META'], client: ({ acc, packet }) => console.log(acc, packet) });
77
- clients.set('U444', { acc: 'U444', quote: ['NASDAQ:MRNA', 'NASDAQ:LI'], client: ({ acc, packet }) => console.log(acc, packet) });
78
-
79
- const status = await marketData.connect({ url, options, login, pass, result });
80
- console.log(status);
81
- // await u.pause(2000);
82
- marketData.createSession({ type: 'chart' });
83
- marketData.createSession({ type: 'quote' });
84
-
85
- clients.forEach((each) => {
86
- marketData.addQuoteSymbols({ symbolIds: each.quote });
87
- });
88
-
89
- process.on('SIGINT', stop);
90
- process.on('SIGTERM', stop);
91
- })();