@mathieuc/tradingview 3.4.6 → 3.5.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.
package/.env.sample ADDED
@@ -0,0 +1,2 @@
1
+ SESSION=... # Your sessionid cookie
2
+ SIGNATURE=... # Your signature cookie
@@ -4,12 +4,13 @@ const TradingView = require('../main');
4
4
  * This example creates a chart with all user's private indicators
5
5
  */
6
6
 
7
- if (!process.argv[2]) throw Error('Please specify your \'sessionid\' cookie');
8
- if (!process.argv[3]) throw Error('Please specify your \'signature\' cookie');
7
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
8
+ throw Error('Please set your sessionid and signature cookies');
9
+ }
9
10
 
10
11
  const client = new TradingView.Client({
11
- token: process.argv[2],
12
- signature: process.argv[3],
12
+ token: process.env.SESSION,
13
+ signature: process.env.SIGNATURE,
13
14
  });
14
15
 
15
16
  const chart = new client.Session.Chart();
@@ -17,8 +18,15 @@ chart.setMarket('BINANCE:BTCEUR', {
17
18
  timeframe: 'D',
18
19
  });
19
20
 
20
- TradingView.getPrivateIndicators(process.argv[2]).then((indicList) => {
21
- indicList.forEach(async (indic) => {
21
+ (async () => {
22
+ const indicList = await TradingView.getPrivateIndicators(process.argv[2]);
23
+
24
+ if (!indicList.length) {
25
+ console.error('Your account has no private indicators');
26
+ process.exit(0);
27
+ }
28
+
29
+ for (const indic of indicList) {
22
30
  const privateIndic = await indic.get();
23
31
  console.log('Loading indicator', indic.name, '...');
24
32
 
@@ -32,5 +40,5 @@ TradingView.getPrivateIndicators(process.argv[2]).then((indicList) => {
32
40
  console.log('Plot values', indicator.periods);
33
41
  console.log('Strategy report', indicator.strategyReport);
34
42
  });
35
- });
36
- });
43
+ }
44
+ })();
@@ -6,19 +6,24 @@ const TradingView = require('../main');
6
6
 
7
7
  const volumeProfile = new TradingView.BuiltInIndicator('VbPFixed@tv-basicstudies-241!');
8
8
 
9
- const AUTHENTICATED_INDICATORS = [
9
+ const needAuth = ![
10
10
  'VbPFixed@tv-basicstudies-241',
11
11
  'VbPFixed@tv-basicstudies-241!',
12
12
  'Volume@tv-basicstudies-241',
13
- ];
13
+ ].includes(volumeProfile.type);
14
14
 
15
- if (!process.argv[2] && !AUTHENTICATED_INDICATORS.includes(volumeProfile.type)) {
16
- throw Error('Please specify your \'sessionid\' cookie');
15
+ if (needAuth && (!process.env.SESSION || !process.env.SIGNATURE)) {
16
+ throw Error('Please set your sessionid and signature cookies');
17
17
  }
18
18
 
19
- const client = new TradingView.Client({
20
- token: process.argv[2],
21
- });
19
+ const client = new TradingView.Client(
20
+ needAuth
21
+ ? {
22
+ token: process.env.SESSION,
23
+ signature: process.env.SIGNATURE,
24
+ }
25
+ : {},
26
+ );
22
27
 
23
28
  const chart = new client.Session.Chart();
24
29
  chart.setMarket('BINANCE:BTCEUR', {
@@ -6,9 +6,12 @@ const TradingView = require('../main');
6
6
  */
7
7
 
8
8
  const client = new TradingView.Client({
9
- /* Token is only required if you want to use intraday
10
- timeframes (if you have a paid TradingView account) */
11
- token: process.argv[2],
9
+ /*
10
+ Token and signature are only required if you want to use
11
+ intraday timeframes (if you have a paid TradingView account)
12
+ */
13
+ token: process.env.SESSION,
14
+ signature: process.env.SIGNATURE,
12
15
  });
13
16
 
14
17
  const chart = new client.Session.Chart();
@@ -4,10 +4,13 @@ const TradingView = require('../main');
4
4
  * This example tests custom timeframes like 1 second
5
5
  */
6
6
 
7
- if (!process.argv[2]) throw Error('Please specify your \'sessionid\' cookie');
7
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
8
+ throw Error('Please set your sessionid and signature cookies');
9
+ }
8
10
 
9
11
  const client = new TradingView.Client({
10
- token: process.argv[2],
12
+ token: process.env.SESSION,
13
+ signature: process.env.SIGNATURE,
11
14
  });
12
15
 
13
16
  const chart = new client.Session.Chart();
@@ -4,7 +4,15 @@ const TradingView = require('../main');
4
4
  * This example tests many types of errors
5
5
  */
6
6
 
7
- const client = new TradingView.Client(); // Creates a websocket client
7
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
8
+ throw Error('Please set your sessionid and signature cookies');
9
+ }
10
+
11
+ // Creates a websocket client
12
+ const client = new TradingView.Client({
13
+ token: process.env.SESSION,
14
+ signature: process.env.SIGNATURE,
15
+ });
8
16
 
9
17
  const tests = [
10
18
  (next) => { /* Testing "Credentials error" */
@@ -11,7 +11,7 @@ const client = new Client();
11
11
  const chart = new client.Session.Chart();
12
12
 
13
13
  chart.setMarket('BINANCE:BTCEUR', {
14
- timeframe: 'D',
14
+ timeframe: '240',
15
15
  range: -1, // Range is negative, so 'to' means 'from'
16
16
  to: Math.round(Date.now() / 1000) - 86400 * 7, // Seven days before now
17
17
  // to: 1600000000,
@@ -31,10 +31,10 @@ chart.onUpdate(async () => {
31
31
 
32
32
  console.log('Next ->', times[0]);
33
33
 
34
- if ((times[0] + 86400) * 1000 > Date.now()) {
34
+ if (times[0] > ((Date.now() / 1000) - 86400 * 1)) {
35
35
  await client.end();
36
36
  console.log('Done !', times.length);
37
37
  }
38
38
 
39
- chart.fetchMore(-1);
39
+ chart.fetchMore(-2);
40
40
  });
@@ -5,13 +5,20 @@ const TradingView = require('../main');
5
5
  * of candles before or after a timestamp
6
6
  */
7
7
 
8
- const client = new TradingView.Client();
8
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
9
+ throw Error('Please set your sessionid and signature cookies');
10
+ }
11
+
12
+ const client = new TradingView.Client({
13
+ token: process.env.SESSION,
14
+ signature: process.env.SIGNATURE,
15
+ });
9
16
 
10
17
  const chart = new client.Session.Chart();
11
18
  chart.setMarket('BINANCE:BTCEUR', {
12
19
  timeframe: '240',
13
20
  range: 2, // Can be positive to get before or negative to get after
14
- to: 1600000000,
21
+ to: 1700000000,
15
22
  });
16
23
 
17
24
  // This works with indicators
@@ -5,14 +5,16 @@ const TradingView = require('../main');
5
5
  */
6
6
 
7
7
  // First parameter must be the layoutID
8
- // (if the layout is private) Second parameter must be the sessionid cookie
9
- // (if the layout is private) Third parameter must be the userid (you can use getUser function)
8
+ // If the layout is private:
9
+ // - Second parameter must be the userid (you can use getUser function)
10
+ // - You should provide your sessionid and signature cookies in .env file
10
11
 
11
12
  if (!process.argv[2]) throw Error('Please specify a layoutID');
12
13
 
13
14
  TradingView.getDrawings(process.argv[2], null, {
14
- session: process.argv[3],
15
- id: process.argv[4],
15
+ session: process.env.SESSION,
16
+ signature: process.env.SIGNATURE,
17
+ id: process.argv[3],
16
18
  }).then((drawings) => {
17
19
  console.log(`Found ${drawings.length} drawings:`, drawings.map((d) => ({
18
20
  id: d.id,
@@ -5,7 +5,14 @@ const TradingView = require('../main');
5
5
  * as 'lines', 'labels', 'boxes', 'tables', 'polygons', etc...
6
6
  */
7
7
 
8
- const client = new TradingView.Client();
8
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
9
+ throw Error('Please set your sessionid and signature cookies');
10
+ }
11
+
12
+ const client = new TradingView.Client({
13
+ token: process.env.SESSION,
14
+ signature: process.env.SIGNATURE,
15
+ });
9
16
 
10
17
  const chart = new client.Session.Chart();
11
18
  chart.setMarket('BINANCE:BTCEUR', {
@@ -29,7 +36,7 @@ TradingView.getIndicator('STD;Zig_Zag').then((indic) => {
29
36
  STD.onUpdate(() => {
30
37
  console.log('Graphic data:', STD.graphic);
31
38
  // console.log('Tables:', changes, STD.graphic.tables);
32
- // console.log('Cells', STD.graphic.tables[0].cells());
39
+ // console.log('Cells:', STD.graphic.tables[0].cells());
33
40
  client.end();
34
41
  });
35
42
  });
@@ -4,16 +4,23 @@ const TradingView = require('../main');
4
4
  * This examples synchronously fetches data from 3 indicators
5
5
  */
6
6
 
7
- const client = new TradingView.Client();
8
- const chart = new client.Session.Chart();
9
- chart.setMarket('BINANCE:DOTUSDT');
7
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
8
+ throw Error('Please set your sessionid and signature cookies');
9
+ }
10
+
11
+ const client = new TradingView.Client({
12
+ token: process.env.SESSION,
13
+ signature: process.env.SIGNATURE,
14
+ });
10
15
 
11
16
  function getIndicData(indicator) {
12
- return new Promise((res) => {
13
- const STD = new chart.Study(indicator);
17
+ const chart = new client.Session.Chart();
18
+ chart.setMarket('BINANCE:DOTUSDT');
19
+ const STD = new chart.Study(indicator);
14
20
 
15
- console.log(`Getting "${indicator.description}"...`);
21
+ console.log(`Getting "${indicator.description}"...`);
16
22
 
23
+ return new Promise((res) => {
17
24
  STD.onUpdate(() => {
18
25
  res(STD.periods);
19
26
  console.log(`"${indicator.description}" done !`);
@@ -5,11 +5,21 @@ const { PinePermManager } = require('../main');
5
5
  * and tests all the available functions
6
6
  */
7
7
 
8
- const sessionid = process.argv[2];
9
- const signature = process.argv[3];
10
- const pineid = process.argv[4];
8
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
9
+ throw Error('Please set your sessionid and signature cookies');
10
+ }
11
11
 
12
- const manager = new PinePermManager(sessionid, signature, pineid);
12
+ const pineid = process.argv[2];
13
+
14
+ if (!pineid) throw Error('Please specify a pine id as first argument');
15
+
16
+ console.log('Pine ID:', pineid);
17
+
18
+ const manager = new PinePermManager(
19
+ process.env.SESSION,
20
+ process.env.SIGNATURE,
21
+ pineid,
22
+ );
13
23
 
14
24
  (async () => {
15
25
  console.log('Users:', await manager.getUsers());
@@ -5,6 +5,18 @@ const TradingView = require('../main');
5
5
  * indicator data and stores it in a 'periods' variable
6
6
  */
7
7
 
8
+ if (!process.env.SESSION || !process.env.SIGNATURE) {
9
+ throw Error('Please set your sessionid and signature cookies');
10
+ }
11
+
12
+ console.log('----- Testing ReplayMode: -----');
13
+
14
+ const client = new TradingView.Client({
15
+ token: process.env.SESSION,
16
+ signature: process.env.SIGNATURE,
17
+ });
18
+ const chart = new client.Session.Chart();
19
+
8
20
  const config = {
9
21
  symbol: 'BINANCE:BTCEUR',
10
22
  timeframe: 'D',
@@ -12,11 +24,6 @@ const config = {
12
24
  // startFrom: 1600000000,
13
25
  };
14
26
 
15
- console.log('----- Testing ReplayMode: -----');
16
-
17
- const client = new TradingView.Client();
18
- const chart = new client.Session.Chart();
19
-
20
27
  chart.setMarket(config.symbol, {
21
28
  timeframe: config.timeframe,
22
29
  replay: config.startFrom,
@@ -2,10 +2,10 @@ const TradingView = require('../main');
2
2
 
3
3
  /**
4
4
  * This example tests the searching functions such
5
- * as 'searchMarket' and 'searchIndicator'
5
+ * as 'searchMarketV3' and 'searchIndicator'
6
6
  */
7
7
 
8
- TradingView.searchMarket('BINANCE:').then((rs) => {
8
+ TradingView.searchMarketV3('BINANCE:').then((rs) => {
9
9
  console.log('Found Markets:', rs);
10
10
  });
11
11
 
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@mathieuc/tradingview",
3
- "version": "3.4.6",
3
+ "version": "3.5.1",
4
4
  "description": "Tradingview instant stocks API, indicator alerts, trading bot, and more !",
5
5
  "main": "main.js",
6
6
  "scripts": {
7
- "test": "vitest"
7
+ "test": "vitest",
8
+ "example": "node --env-file=.env",
9
+ "example:dev": "nodemon --env-file=.env"
8
10
  },
9
11
  "repository": {
10
12
  "type": "git",
@@ -37,6 +39,6 @@
37
39
  "eslint": "^7.25.0",
38
40
  "eslint-config-airbnb-base": "^14.2.1",
39
41
  "eslint-plugin-import": "^2.22.1",
40
- "vitest": "^0.31.1"
42
+ "vitest": "^0.31.4"
41
43
  }
42
44
  }
@@ -331,6 +331,7 @@ module.exports = (client) => class ChartSession {
331
331
  * @param {number} [options.range] Number of loaded periods/candles (Default: 100)
332
332
  * @param {number} [options.to] Last candle timestamp (Default is now)
333
333
  * @param {'splits' | 'dividends'} [options.adjustment] Market adjustment
334
+ * @param {boolean} [options.backadjustment] Market backadjustment of futures contracts
334
335
  * @param {'regular' | 'extended'} [options.session] Chart session
335
336
  * @param {'EUR' | 'USD' | string} [options.currency] Chart currency
336
337
  * @param {ChartType} [options.type] Chart custom type
@@ -350,12 +351,15 @@ module.exports = (client) => class ChartSession {
350
351
  adjustment: options.adjustment || 'splits',
351
352
  };
352
353
 
354
+ if (options.backadjustment) symbolInit.backadjustment = 'default';
353
355
  if (options.session) symbolInit.session = options.session;
354
356
  if (options.currency) symbolInit['currency-id'] = options.currency;
355
357
 
356
358
  if (options.replay) {
357
- this.#replayMode = true;
358
- this.#client.send('replay_create_session', [this.#replaySessionID]);
359
+ if (!this.#replayMode) {
360
+ this.#replayMode = true;
361
+ this.#client.send('replay_create_session', [this.#replaySessionID]);
362
+ }
359
363
 
360
364
  this.#client.send('replay_add_series', [
361
365
  this.#replaySessionID,
@@ -543,6 +547,7 @@ module.exports = (client) => class ChartSession {
543
547
  if (this.#replayMode) this.#client.send('replay_delete_session', [this.#replaySessionID]);
544
548
  this.#client.send('chart_delete_session', [this.#chartSessionID]);
545
549
  delete this.#client.sessions[this.#chartSessionID];
550
+ delete this.#client.sessions[this.#replaySessionID];
546
551
  this.#replayMode = false;
547
552
  }
548
553
  };
@@ -40,7 +40,7 @@ class PinePermManager {
40
40
  * | 'expiration,user__username'
41
41
  * | '-expiration,user__username'
42
42
  * } order Fetching order
43
- * @returns {AuthorizationUser[]}
43
+ * @returns {Promise<AuthorizationUser[]>}
44
44
  */
45
45
  async getUsers(limit = 10, order = '-created') {
46
46
  try {
@@ -66,7 +66,7 @@ class PinePermManager {
66
66
  * Adds an user to the authorized list
67
67
  * @param {string} username User's username
68
68
  * @param {Date} [expiration] Expiration date
69
- * @returns {'ok' | 'exists' | null}
69
+ * @returns {Promise<'ok' | 'exists' | null>}
70
70
  */
71
71
  async addUser(username, expiration = null) {
72
72
  try {
@@ -100,7 +100,7 @@ class PinePermManager {
100
100
  * Modify an authorization expiration date
101
101
  * @param {string} username User's username
102
102
  * @param {Date} [expiration] New expiration date
103
- * @returns {'ok' | null}
103
+ * @returns {Promise<'ok' | null>}
104
104
  */
105
105
  async modifyExpiration(username, expiration = null) {
106
106
  try {
@@ -133,7 +133,7 @@ class PinePermManager {
133
133
  /**
134
134
  * Removes an user to the authorized list
135
135
  * @param {string} username User's username
136
- * @returns {'ok' | null}
136
+ * @returns {Promise<'ok' | null>}
137
137
  */
138
138
  async removeUser(username) {
139
139
  try {
package/src/client.js CHANGED
@@ -217,23 +217,26 @@ module.exports = class Client {
217
217
  * @prop {string} [signature] User auth token signature (in 'sessionid_sign' cookie)
218
218
  * @prop {boolean} [DEBUG] Enable debug mode
219
219
  * @prop {'data' | 'prodata' | 'widgetdata'} [server] Server type
220
+ * @prop {string} [location] Auth page location (For france: https://fr.tradingview.com/)
220
221
  */
221
222
 
222
- /** Client object
223
+ /**
224
+ * Client object
223
225
  * @param {ClientOptions} clientOptions TradingView client options
224
226
  */
225
227
  constructor(clientOptions = {}) {
226
228
  if (clientOptions.DEBUG) global.TW_DEBUG = clientOptions.DEBUG;
227
229
 
228
230
  const server = clientOptions.server || 'data';
229
- this.#ws = new WebSocket(`wss://${server}.tradingview.com/socket.io/websocket?&type=chart`, {
230
- origin: 'https://s.tradingview.com',
231
+ this.#ws = new WebSocket(`wss://${server}.tradingview.com/socket.io/websocket?type=chart`, {
232
+ origin: 'https://www.tradingview.com',
231
233
  });
232
234
 
233
235
  if (clientOptions.token) {
234
236
  misc.getUser(
235
237
  clientOptions.token,
236
238
  clientOptions.signature ? clientOptions.signature : '',
239
+ clientOptions.location ? clientOptions.location : 'https://tradingview.com',
237
240
  ).then((user) => {
238
241
  this.#sendQueue.unshift(protocol.formatWSPacket({
239
242
  m: 'set_auth_token',
@@ -428,10 +428,11 @@ module.exports = {
428
428
  * @returns {Promise<User>} Token
429
429
  */
430
430
  async getUser(session, signature = '', location = 'https://www.tradingview.com/') {
431
- const { data } = await axios.get(location, {
431
+ const { data, headers } = await axios.get(location, {
432
432
  headers: {
433
433
  cookie: genAuthCookies(session, signature),
434
434
  },
435
+ maxRedirects: 0,
435
436
  validateStatus,
436
437
  });
437
438
 
@@ -457,6 +458,10 @@ module.exports = {
457
458
  };
458
459
  }
459
460
 
461
+ if (headers.location !== location) {
462
+ return this.getUser(session, signature, headers.location);
463
+ }
464
+
460
465
  throw new Error('Wrong or expired sessionid/signature');
461
466
  },
462
467
 
package/vite.config.js CHANGED
@@ -1,6 +1,7 @@
1
1
  module.exports = {
2
2
  test: {
3
3
  testTimeout: 10000,
4
+ retry: 3,
4
5
  setupFiles: 'dotenv/config',
5
6
  },
6
7
  };