@mathieuc/tradingview 3.2.0 → 3.3.0

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 CHANGED
@@ -14,5 +14,11 @@ module.exports = {
14
14
  },
15
15
  rules: {
16
16
  'no-console': 'off',
17
+ 'import/no-extraneous-dependencies': [
18
+ 'error',
19
+ {
20
+ devDependencies: ['./test.js', './tests/**'],
21
+ },
22
+ ],
17
23
  },
18
24
  };
package/README.md CHANGED
@@ -1,14 +1,16 @@
1
- # TradingView API [![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/Mathieu2301/TradingView-API) [![GitHub stars](https://img.shields.io/github/stars/Mathieu2301/TradingView-API.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/Mathieu2301/TradingView-API/stargazers/)
1
+ # TradingView API [![GitHub stars](https://img.shields.io/github/stars/Mathieu2301/TradingView-API.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/Mathieu2301/TradingView-API/stargazers/)
2
2
 
3
3
  [![Tests](https://github.com/Mathieu2301/TradingView-API/actions/workflows/node.js.yml/badge.svg)](https://github.com/Mathieu2301/TradingView-API/actions/workflows/node.js.yml)
4
- [![Minimum node.js version](https://badgen.net/npm/node/@mathieuc/tradingview)](https://npmjs.com/@mathieuc/tradingview)
5
- [![Npm package yearly downloads](https://badgen.net/npm/dt/@mathieuc/tradingview)](https://npmjs.com/@mathieuc/tradingview)
4
+ [![CodeFactor](https://www.codefactor.io/repository/github/mathieu2301/tradingview-api/badge/main)](https://www.codefactor.io/repository/github/mathieu2301/tradingview-api/overview/main)
6
5
  [![GitHub latest commit](https://img.shields.io/github/last-commit/Mathieu2301/TradingView-API)](https://GitHub.com/Mathieu2301/TradingView-API/commit/)
6
+ [![Npm package yearly downloads](https://badgen.net/npm/dt/@mathieuc/tradingview)](https://npmjs.com/@mathieuc/tradingview)
7
+ [![Minimum node.js version](https://badgen.net/npm/node/@mathieuc/tradingview)](https://npmjs.com/@mathieuc/tradingview)
7
8
  [![Npm package version](https://badgen.net/npm/v/@mathieuc/tradingview)](https://npmjs.com/package/@mathieuc/tradingview)
8
9
 
9
10
  Get realtime market prices and indicator values from Tradingview !
10
11
 
11
12
  ## Features
13
+
12
14
  - [x] Premium features
13
15
  - [x] Automatically backtest many strategies and try many settings in a very little time
14
16
  - [x] Get drawings you made on your chart
@@ -26,6 +28,7 @@ Get realtime market prices and indicator values from Tradingview !
26
28
  - IF YOU WANT A FEATURE, ASK ME !
27
29
 
28
30
  ## Possibilities
31
+
29
32
  - Trading bot
30
33
  - Discord alerts
31
34
  - Hard backtest
@@ -33,21 +36,31 @@ Get realtime market prices and indicator values from Tradingview !
33
36
  - Free replay mode for all timeframes
34
37
 
35
38
  ___
39
+
36
40
  ## Installation
37
41
 
38
42
  Stable version:
43
+
39
44
  ```ruby
40
45
  npm i @mathieuc/tradingview
41
46
  ```
47
+
42
48
  Last version:
49
+
43
50
  ```ruby
44
51
  npm i github:Mathieu2301/TradingView-API
45
52
  ```
46
53
 
47
54
  ## Examples
55
+
48
56
  You can find all the examples and snippets in `./examples` folder.
49
57
 
58
+ ## Before opening an issue
59
+
60
+ Please look at examples and previously resolved issues before opening a new one. I can't help everyone (especially for questions that are not library related but JavaScript related). Thank you for your understanding.
50
61
  ___
62
+
51
63
  ## Problems
64
+
52
65
  If you have errors in console or unwanted behavior,
53
66
  please create an issue [here](https://github.com/Mathieu2301/Tradingview-API/issues).
package/docs/DOCS.md ADDED
@@ -0,0 +1,3 @@
1
+ # Documentation
2
+
3
+ ### All the project is now JSDoc-ed :)
@@ -7,7 +7,7 @@ const TradingView = require('../main');
7
7
 
8
8
  const volumeProfile = new TradingView.BuiltInIndicator('VbPFixed@tv-basicstudies-139!');
9
9
 
10
- if (!process.argv[2] && volumeProfile.type !== 'VbPFixed@tv-basicstudies-139!') {
10
+ if (!process.argv[2] && !['VbPFixed@tv-basicstudies-139!', 'Volume@tv-basicstudies-144'].includes(volumeProfile.type)) {
11
11
  throw Error('Please specify your \'sessionid\' cookie');
12
12
  }
13
13
 
@@ -0,0 +1,26 @@
1
+ const TradingView = require('../main');
2
+
3
+ /*
4
+ This example tests the
5
+ getDrawings function
6
+ */
7
+
8
+ // First parameter must be the layoutID
9
+ // (if the layout is private) Second parameter must be the sessionid cookie
10
+ // (if the layout is private) Third parameter must be the userid (you can use getUser function)
11
+
12
+ if (!process.argv[2]) throw Error('Please specify a layoutID');
13
+
14
+ TradingView.getDrawings(process.argv[2], null, {
15
+ session: process.argv[3],
16
+ id: process.argv[4],
17
+ }).then((drawings) => {
18
+ console.log(`Found ${drawings.length} drawings:`, drawings.map((d) => ({
19
+ id: d.id,
20
+ symbol: d.symbol,
21
+ type: d.type,
22
+ text: d.state.text,
23
+ })));
24
+ }).catch((err) => {
25
+ console.error('Error:', err.message);
26
+ });
@@ -0,0 +1,16 @@
1
+ const TradingView = require('../main');
2
+
3
+ /*
4
+ This example tests the
5
+ user login function
6
+ */
7
+
8
+ if (!process.argv[2]) throw Error('Please specify your username/email');
9
+ if (!process.argv[3]) throw Error('Please specify your password');
10
+
11
+ TradingView.loginUser(process.argv[2], process.argv[3], false).then((user) => {
12
+ console.log('User:', user);
13
+ console.log('Sessionid:', user.session);
14
+ }).catch((err) => {
15
+ console.error('Login error:', err.message);
16
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mathieuc/tradingview",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Tradingview instant stocks API, indicator alerts, trading bot, and more !",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -34,7 +34,6 @@
34
34
  "@mathieuc/console": "^1.0.1",
35
35
  "eslint": "^7.25.0",
36
36
  "eslint-config-airbnb-base": "^14.2.1",
37
- "eslint-plugin-import": "^2.22.1",
38
- "jsdoc-to-markdown": "^7.1.0"
37
+ "eslint-plugin-import": "^2.22.1"
39
38
  }
40
39
  }
package/src/FormData.js CHANGED
@@ -1,3 +1,4 @@
1
+ /** @class */
1
2
  class FormData {
2
3
  #string = '';
3
4
 
@@ -64,7 +64,9 @@ const ChartTypes = {
64
64
  * @prop {string} session Session (ex: '24x7')
65
65
  * @prop {string} session-correction Session correction
66
66
  * @prop {string} session-display Session display (ex: '24x7')
67
- *
67
+ */
68
+
69
+ /**
68
70
  * @typedef {Object} MarketInfos
69
71
  * @prop {string} series_id Used series (ex: 'ser_1')
70
72
  * @prop {string} base_currency Base currency (ex: 'BTC')
@@ -120,7 +122,7 @@ module.exports = (client) => class ChartSession {
120
122
  #replayMode = false;
121
123
 
122
124
  /** @type {Object<string, (): any>} */
123
- #replayOKCB = {}
125
+ #replayOKCB = {};
124
126
 
125
127
  /** Parent client */
126
128
  #client = client;
@@ -16,11 +16,11 @@ function getInputs(options) {
16
16
  if (options.pineId) pineInputs.pineId = options.pineId;
17
17
  if (options.pineVersion) pineInputs.pineVersion = options.pineVersion;
18
18
 
19
- Object.keys(options.inputs).forEach((inputID) => {
19
+ Object.keys(options.inputs).forEach((inputID, n) => {
20
20
  const input = options.inputs[inputID];
21
21
 
22
22
  pineInputs[inputID] = {
23
- v: input.value,
23
+ v: (input.type !== 'color') ? input.value : n,
24
24
  f: input.isFake,
25
25
  t: input.type,
26
26
  };
@@ -35,80 +35,80 @@ function getInputs(options) {
35
35
  /**
36
36
  * @typedef {Object} TradeReport Trade report
37
37
 
38
- * @property {Object} entry Trade entry
39
- * @property {string} entry.name Trade name
40
- * @property {'long' | 'short'} entry.type Entry type (long/short)
41
- * @property {number} entry.value Entry price value
42
- * @property {number} entry.time Entry timestamp
43
-
44
- * @property {Object} exit Trade exit
45
- * @property {'' | string} exit.name Trade name ('' if false exit)
46
- * @property {number} exit.value Exit price value
47
- * @property {number} exit.time Exit timestamp
48
-
49
- * @property {number} quantity Trade quantity
50
- * @property {RelAbsValue} profit Trade profit
51
- * @property {RelAbsValue} cumulative Trade cummulative profit
52
- * @property {RelAbsValue} runup Trade run-up
53
- * @property {RelAbsValue} drawdown Trade drawdown
38
+ * @prop {Object} entry Trade entry
39
+ * @prop {string} entry.name Trade name
40
+ * @prop {'long' | 'short'} entry.type Entry type (long/short)
41
+ * @prop {number} entry.value Entry price value
42
+ * @prop {number} entry.time Entry timestamp
43
+
44
+ * @prop {Object} exit Trade exit
45
+ * @prop {'' | string} exit.name Trade name ('' if false exit)
46
+ * @prop {number} exit.value Exit price value
47
+ * @prop {number} exit.time Exit timestamp
48
+
49
+ * @prop {number} quantity Trade quantity
50
+ * @prop {RelAbsValue} profit Trade profit
51
+ * @prop {RelAbsValue} cumulative Trade cummulative profit
52
+ * @prop {RelAbsValue} runup Trade run-up
53
+ * @prop {RelAbsValue} drawdown Trade drawdown
54
54
  */
55
55
 
56
56
  /**
57
57
  * @typedef {Object} PerfReport
58
- * @property {number} avgBarsInTrade Average bars in trade
59
- * @property {number} avgBarsInWinTrade Average bars in winning trade
60
- * @property {number} avgBarsInLossTrade Average bars in losing trade
61
- * @property {number} avgTrade Average trade gain
62
- * @property {number} avgTradePercent Average trade performace
63
- * @property {number} avgLosTrade Average losing trade gain
64
- * @property {number} avgLosTradePercent Average losing trade performace
65
- * @property {number} avgWinTrade Average winning trade gain
66
- * @property {number} avgWinTradePercent Average winning trade performace
67
- * @property {number} commissionPaid Commission paid
68
- * @property {number} grossLoss Gross loss value
69
- * @property {number} grossLossPercent Gross loss percent
70
- * @property {number} grossProfit Gross profit
71
- * @property {number} grossProfitPercent Gross profit percent
72
- * @property {number} largestLosTrade Largest losing trade gain
73
- * @property {number} largestLosTradePercent Largent losing trade performance (percentage)
74
- * @property {number} largestWinTrade Largest winning trade gain
75
- * @property {number} largestWinTradePercent Largest winning trade performance (percentage)
76
- * @property {number} marginCalls Margin calls
77
- * @property {number} maxContractsHeld Max Contracts Held
78
- * @property {number} netProfit Net profit
79
- * @property {number} netProfitPercent Net performance (percentage)
80
- * @property {number} numberOfLosingTrades Number of losing trades
81
- * @property {number} numberOfWiningTrades Number of winning trades
82
- * @property {number} percentProfitable Strategy winrate
83
- * @property {number} profitFactor Profit factor
84
- * @property {number} ratioAvgWinAvgLoss Ratio Average Win / Average Loss
85
- * @property {number} totalOpenTrades Total open trades
86
- * @property {number} totalTrades Total trades
58
+ * @prop {number} avgBarsInTrade Average bars in trade
59
+ * @prop {number} avgBarsInWinTrade Average bars in winning trade
60
+ * @prop {number} avgBarsInLossTrade Average bars in losing trade
61
+ * @prop {number} avgTrade Average trade gain
62
+ * @prop {number} avgTradePercent Average trade performace
63
+ * @prop {number} avgLosTrade Average losing trade gain
64
+ * @prop {number} avgLosTradePercent Average losing trade performace
65
+ * @prop {number} avgWinTrade Average winning trade gain
66
+ * @prop {number} avgWinTradePercent Average winning trade performace
67
+ * @prop {number} commissionPaid Commission paid
68
+ * @prop {number} grossLoss Gross loss value
69
+ * @prop {number} grossLossPercent Gross loss percent
70
+ * @prop {number} grossProfit Gross profit
71
+ * @prop {number} grossProfitPercent Gross profit percent
72
+ * @prop {number} largestLosTrade Largest losing trade gain
73
+ * @prop {number} largestLosTradePercent Largent losing trade performance (percentage)
74
+ * @prop {number} largestWinTrade Largest winning trade gain
75
+ * @prop {number} largestWinTradePercent Largest winning trade performance (percentage)
76
+ * @prop {number} marginCalls Margin calls
77
+ * @prop {number} maxContractsHeld Max Contracts Held
78
+ * @prop {number} netProfit Net profit
79
+ * @prop {number} netProfitPercent Net performance (percentage)
80
+ * @prop {number} numberOfLosingTrades Number of losing trades
81
+ * @prop {number} numberOfWiningTrades Number of winning trades
82
+ * @prop {number} percentProfitable Strategy winrate
83
+ * @prop {number} profitFactor Profit factor
84
+ * @prop {number} ratioAvgWinAvgLoss Ratio Average Win / Average Loss
85
+ * @prop {number} totalOpenTrades Total open trades
86
+ * @prop {number} totalTrades Total trades
87
87
  */
88
88
 
89
89
  /**
90
90
  * @typedef {Object} StrategyReport
91
- * @property {'EUR' | 'USD' | 'JPY' | '' | 'CHF'} [currency] Selected currency
92
- * @property {TradeReport[]} trades Trade list starting by the last
93
- * @property {Object} history History Chart value
94
- * @property {number[]} [history.buyHold] Buy hold values
95
- * @property {number[]} [history.buyHoldPercent] Buy hold percent values
96
- * @property {number[]} [history.drawDown] Drawdown values
97
- * @property {number[]} [history.drawDownPercent] Drawdown percent values
98
- * @property {number[]} [history.equity] Equity values
99
- * @property {number[]} [history.equityPercent] Equity percent values
100
- * @property {Object} performance Strategy performance
101
- * @property {PerfReport} [performance.all] Strategy long/short performances
102
- * @property {PerfReport} [performance.long] Strategy long performances
103
- * @property {PerfReport} [performance.short] Strategy short performances
104
- * @property {number} [performance.buyHoldReturn] Strategy Buy & Hold Return
105
- * @property {number} [performance.buyHoldReturnPercent] Strategy Buy & Hold Return percent
106
- * @property {number} [performance.maxDrawDown] Strategy max drawdown
107
- * @property {number} [performance.maxDrawDownPercent] Strategy max drawdown percent
108
- * @property {number} [performance.openPL] Strategy Open P&L (Profit And Loss)
109
- * @property {number} [performance.openPLPercent] Strategy Open P&L (Profit And Loss) percent
110
- * @property {number} [performance.sharpeRatio] Strategy Sharpe Ratio
111
- * @property {number} [performance.sortinoRatio] Strategy Sortino Ratio
91
+ * @prop {'EUR' | 'USD' | 'JPY' | '' | 'CHF'} [currency] Selected currency
92
+ * @prop {TradeReport[]} trades Trade list starting by the last
93
+ * @prop {Object} history History Chart value
94
+ * @prop {number[]} [history.buyHold] Buy hold values
95
+ * @prop {number[]} [history.buyHoldPercent] Buy hold percent values
96
+ * @prop {number[]} [history.drawDown] Drawdown values
97
+ * @prop {number[]} [history.drawDownPercent] Drawdown percent values
98
+ * @prop {number[]} [history.equity] Equity values
99
+ * @prop {number[]} [history.equityPercent] Equity percent values
100
+ * @prop {Object} performance Strategy performance
101
+ * @prop {PerfReport} [performance.all] Strategy long/short performances
102
+ * @prop {PerfReport} [performance.long] Strategy long performances
103
+ * @prop {PerfReport} [performance.short] Strategy short performances
104
+ * @prop {number} [performance.buyHoldReturn] Strategy Buy & Hold Return
105
+ * @prop {number} [performance.buyHoldReturnPercent] Strategy Buy & Hold Return percent
106
+ * @prop {number} [performance.maxDrawDown] Strategy max drawdown
107
+ * @prop {number} [performance.maxDrawDownPercent] Strategy max drawdown percent
108
+ * @prop {number} [performance.openPL] Strategy Open P&L (Profit And Loss)
109
+ * @prop {number} [performance.openPLPercent] Strategy Open P&L (Profit And Loss) percent
110
+ * @prop {number} [performance.sharpeRatio] Strategy Sharpe Ratio
111
+ * @prop {number} [performance.sortinoRatio] Strategy Sortino Ratio
112
112
  */
113
113
 
114
114
  /**
@@ -68,6 +68,7 @@ const defaultValues = {
68
68
  },
69
69
  };
70
70
 
71
+ /** @class */
71
72
  module.exports = class BuiltInIndicator {
72
73
  /** @type {BuiltInIndicatorType} */
73
74
  #type;
@@ -4,7 +4,9 @@
4
4
  * @property {string} inline Input inline name
5
5
  * @property {string} [internalID] Input internal ID
6
6
  * @property {string} [tooltip] Input tooltip
7
- * @property {'text' | 'source' | 'integer' | 'float' | 'resolution' | 'bool'} type Input type
7
+ * @property {'text' | 'source' | 'integer'
8
+ * | 'float' | 'resolution' | 'bool' | 'color'
9
+ * } type Input type
8
10
  * @property {string | number | boolean} value Input default value
9
11
  * @property {boolean} isHidden If the input is hidden
10
12
  * @property {boolean} isFake If the input is fake
@@ -26,6 +28,8 @@
26
28
  * @typedef {'Script@tv-scripting-101!'
27
29
  * | 'StrategyScript@tv-scripting-101!'} IndicatorType Indicator type
28
30
  */
31
+
32
+ /** @class */
29
33
  module.exports = class PineIndicator {
30
34
  #options;
31
35
 
@@ -113,12 +117,8 @@ module.exports = class PineIndicator {
113
117
  text: 'String',
114
118
  };
115
119
 
116
- if (
117
- (input.type === 'bool' && typeof value !== 'boolean')
118
- || (input.type === 'integer' && typeof value !== 'number')
119
- || (input.type === 'float' && typeof value !== 'number')
120
- || (input.type === 'text' && typeof value !== 'string')
121
- ) {
120
+ // eslint-disable-next-line valid-typeof
121
+ if (types[input.type] && typeof value !== types[input.type].toLowerCase()) {
122
122
  throw new Error(`Input '${input.name}' (${propI}) must be a ${types[input.type]} !`);
123
123
  }
124
124
 
@@ -10,6 +10,7 @@ const FormData = require('../FormData');
10
10
  * @prop {string} created Authorization creation date
11
11
  */
12
12
 
13
+ /** @class */
13
14
  class PinePermManager {
14
15
  sessionId;
15
16
 
@@ -39,7 +40,7 @@ class PinePermManager {
39
40
  * @returns {AuthorizationUser[]}
40
41
  */
41
42
  async getUsers(limit = 10, order = '-created') {
42
- const data = await request({
43
+ const { data } = await request({
43
44
  method: 'POST',
44
45
  host: 'www.tradingview.com',
45
46
  path: `/pine_perm/list_users/?limit=${limit}&order_by=${order}`,
@@ -69,7 +70,7 @@ class PinePermManager {
69
70
  formData.append('expiration', expiration.toString());
70
71
  }
71
72
 
72
- const data = await request({
73
+ const { data } = await request({
73
74
  method: 'POST',
74
75
  host: 'www.tradingview.com',
75
76
  path: '/pine_perm/add/',
@@ -98,7 +99,7 @@ class PinePermManager {
98
99
  formData.append('expiration', expiration.toISOString());
99
100
  }
100
101
 
101
- const data = await request({
102
+ const { data } = await request({
102
103
  method: 'POST',
103
104
  host: 'www.tradingview.com',
104
105
  path: '/pine_perm/modify_user_expiration/',
@@ -123,7 +124,7 @@ class PinePermManager {
123
124
  formData.append('pine_id', this.pineId);
124
125
  formData.append('username_recip', username);
125
126
 
126
- const data = await request({
127
+ const { data } = await request({
127
128
  method: 'POST',
128
129
  host: 'www.tradingview.com',
129
130
  path: '/pine_perm/remove/',
package/src/client.js CHANGED
@@ -15,9 +15,10 @@ const chartSessionGenerator = require('./chart/session');
15
15
  /** @typedef {Object<string, Session>} SessionList Session list */
16
16
 
17
17
  /**
18
- * @typedef {(t: string, p: []) => null} SendPacket Send a custom packet
18
+ * @callback SendPacket Send a custom packet
19
19
  * @param {string} t Packet type
20
20
  * @param {string[]} p Packet data
21
+ * @returns {void}
21
22
  */
22
23
 
23
24
  /**
@@ -33,6 +34,7 @@ const chartSessionGenerator = require('./chart/session');
33
34
  * } ClientEvent
34
35
  */
35
36
 
37
+ /** @class */
36
38
  module.exports = class Client {
37
39
  #ws;
38
40
 
@@ -79,7 +81,7 @@ module.exports = class Client {
79
81
  /**
80
82
  * When client is connected
81
83
  * @param {() => void} cb Callback
82
- * @event
84
+ * @event onConnected
83
85
  */
84
86
  onConnected(cb) {
85
87
  this.#callbacks.connected.push(cb);
@@ -88,7 +90,7 @@ module.exports = class Client {
88
90
  /**
89
91
  * When client is disconnected
90
92
  * @param {() => void} cb Callback
91
- * @event
93
+ * @event onDisconnected
92
94
  */
93
95
  onDisconnected(cb) {
94
96
  this.#callbacks.disconnected.push(cb);
@@ -105,10 +107,12 @@ module.exports = class Client {
105
107
  * @prop {string} javastudies Javastudies
106
108
  * @prop {number} auth_scheme_vsn Auth scheme type
107
109
  * @prop {string} via Socket IP
110
+ */
108
111
 
112
+ /**
109
113
  * When client is logged
110
114
  * @param {(SocketSession: SocketSession) => void} cb Callback
111
- * @event
115
+ * @event onLogged
112
116
  */
113
117
  onLogged(cb) {
114
118
  this.#callbacks.logged.push(cb);
@@ -117,7 +121,7 @@ module.exports = class Client {
117
121
  /**
118
122
  * When server is pinging the client
119
123
  * @param {(i: number) => void} cb Callback
120
- * @event
124
+ * @event onPing
121
125
  */
122
126
  onPing(cb) {
123
127
  this.#callbacks.ping.push(cb);
@@ -126,7 +130,7 @@ module.exports = class Client {
126
130
  /**
127
131
  * When unparsed data is received
128
132
  * @param {(...{}) => void} cb Callback
129
- * @event
133
+ * @event onData
130
134
  */
131
135
  onData(cb) {
132
136
  this.#callbacks.data.push(cb);
@@ -135,7 +139,7 @@ module.exports = class Client {
135
139
  /**
136
140
  * When a client error happens
137
141
  * @param {(...{}) => void} cb Callback
138
- * @event
142
+ * @event onError
139
143
  */
140
144
  onError(cb) {
141
145
  this.#callbacks.error.push(cb);
@@ -144,7 +148,7 @@ module.exports = class Client {
144
148
  /**
145
149
  * When a client event happens
146
150
  * @param {(...{}) => void} cb Callback
147
- * @event
151
+ * @event onEvent
148
152
  */
149
153
  onEvent(cb) {
150
154
  this.#callbacks.event.push(cb);
@@ -203,6 +207,7 @@ module.exports = class Client {
203
207
  while (this.isOpen && this.#logged && this.#sendQueue.length > 0) {
204
208
  const packet = this.#sendQueue.shift();
205
209
  this.#ws.send(packet);
210
+ if (global.TW_DEBUG) console.log('§90§30§107 > §0', packet);
206
211
  }
207
212
  }
208
213
 
@@ -218,7 +223,7 @@ module.exports = class Client {
218
223
  constructor(clientOptions = {}) {
219
224
  if (clientOptions.DEBUG) global.TW_DEBUG = clientOptions.DEBUG;
220
225
 
221
- this.#ws = new WebSocket('wss://widgetdata.tradingview.com/socket.io/websocket', {
226
+ this.#ws = new WebSocket('wss://data.tradingview.com/socket.io/websocket', {
222
227
  origin: 'https://s.tradingview.com',
223
228
  });
224
229
 
@@ -1,5 +1,7 @@
1
+ const os = require('os');
1
2
  const https = require('https');
2
3
  const request = require('./request');
4
+ const FormData = require('./FormData');
3
5
 
4
6
  const PinePermManager = require('./classes/PinePermManager');
5
7
  const PineIndicator = require('./classes/PineIndicator');
@@ -8,7 +10,7 @@ const indicators = ['Recommend.Other', 'Recommend.All', 'Recommend.MA'];
8
10
  const builtInIndicList = [];
9
11
 
10
12
  async function fetchScanData(tickers = [], type = '', columns = []) {
11
- let data = await request({
13
+ let { data } = await request({
12
14
  method: 'POST',
13
15
  hostname: 'scanner.tradingview.com',
14
16
  path: `/${type}/scan`,
@@ -28,11 +30,17 @@ async function fetchScanData(tickers = [], type = '', columns = []) {
28
30
  return data;
29
31
  }
30
32
 
33
+ /** @typedef {number} advice */
34
+
35
+ /**
36
+ * @typedef {{
37
+ * Other: advice,
38
+ * All: advice,
39
+ * MA: advice
40
+ * }} Period
41
+ */
42
+
31
43
  /**
32
- * @typedef {number} advice
33
- *
34
- * @typedef {{ Other: advice, All: advice, MA: advice }} Period
35
- *
36
44
  * @typedef {{
37
45
  * '1': Period,
38
46
  * '5': Period,
@@ -41,21 +49,25 @@ async function fetchScanData(tickers = [], type = '', columns = []) {
41
49
  * '240': Period,
42
50
  * '1D': Period,
43
51
  * '1W': Period,
44
- * '1M': Period,
52
+ * '1M': Period
45
53
  * }} Periods
46
- *
54
+ */
55
+
56
+ /**
47
57
  * @typedef {string | 'forex' | 'crypto'
48
58
  * | 'america' | 'australia' | 'canada' | 'egypt'
49
59
  * | 'germany' | 'india' | 'israel' | 'italy'
50
60
  * | 'luxembourg' | 'poland' | 'sweden' | 'turkey'
51
- * | 'uk' | 'vietnam'} screener
61
+ * | 'uk' | 'vietnam'} Screener
52
62
  * You can use `getScreener(exchange)` function for non-forex and non-crypto markets.
53
63
  */
54
64
 
55
65
  module.exports = {
56
66
  /**
67
+ * Get a screener from an exchange
68
+ * @function getScreener
57
69
  * @param {string} exchange Example: BINANCE, EURONEXT, NASDAQ
58
- * @returns {screener}
70
+ * @returns {Screener}
59
71
  */
60
72
  getScreener(exchange) {
61
73
  const e = exchange.toUpperCase();
@@ -78,7 +90,8 @@ module.exports = {
78
90
 
79
91
  /**
80
92
  * Get technical analysis
81
- * @param {screener} screener
93
+ * @function getTA
94
+ * @param {Screener} screener Market screener
82
95
  * @param {string} id Full market id (Example: COINBASE:BTCEUR)
83
96
  * @returns {Promise<Periods>} results
84
97
  */
@@ -104,24 +117,28 @@ module.exports = {
104
117
 
105
118
  /**
106
119
  * @typedef {Object} SearchMarketResult
107
- * @property {string} id
108
- * @property {string} exchange
109
- * @property {string} fullExchange
110
- * @property {string} screener
111
- * @property {string} symbol
112
- * @property {string} description
113
- * @property {string} type
114
- * @property {() => Promise<Periods>} getTA
120
+ * @prop {string} id Market full symbol
121
+ * @prop {string} exchange Market exchange name
122
+ * @prop {string} fullExchange Market exchange full name
123
+ * @prop {Screener | 'forex' | 'crypto'} screener Market screener
124
+ * @prop {string} symbol Market symbol
125
+ * @prop {string} description Market name
126
+ * @prop {string} type Market type
127
+ * @prop {() => Promise<Periods>} getTA Get market technical analysis
115
128
  */
116
129
 
117
130
  /**
118
131
  * Find a symbol
132
+ * @function searchMarket
119
133
  * @param {string} search Keywords
120
- * @param {'stock' | 'futures' | 'forex' | 'cfd' | 'crypto' | 'index' | 'economic'} [filter]
134
+ * @param {'stock'
135
+ * | 'futures' | 'forex' | 'cfd'
136
+ * | 'crypto' | 'index' | 'economic'
137
+ * } [filter] Caterogy filter
121
138
  * @returns {Promise<SearchMarketResult[]>} Search results
122
139
  */
123
140
  async searchMarket(search, filter = '') {
124
- const data = await request({
141
+ const { data } = await request({
125
142
  host: 'symbol-search.tradingview.com',
126
143
  path: `/symbol_search/?text=${search.replace(/ /g, '%20')}&type=${filter}`,
127
144
  origin: 'https://www.tradingview.com',
@@ -151,34 +168,35 @@ module.exports = {
151
168
 
152
169
  /**
153
170
  * @typedef {Object} SearchIndicatorResult
154
- * @property {string} id Script ID
155
- * @property {string} version Script version
156
- * @property {string} name Script complete name
157
- * @property {{ id: number, username: string }} author Author user ID
158
- * @property {string} image Image ID https://tradingview.com/i/${image}
159
- * @property {string | ''} source Script source (if available)
160
- * @property {'study' | 'strategy'} type Script type (study / strategy)
161
- * @property {'open_source' | 'closed_source' | 'invite_only'
171
+ * @prop {string} id Script ID
172
+ * @prop {string} version Script version
173
+ * @prop {string} name Script complete name
174
+ * @prop {{ id: number, username: string }} author Author user ID
175
+ * @prop {string} image Image ID https://tradingview.com/i/${image}
176
+ * @prop {string | ''} source Script source (if available)
177
+ * @prop {'study' | 'strategy'} type Script type (study / strategy)
178
+ * @prop {'open_source' | 'closed_source' | 'invite_only'
162
179
  * | 'private' | 'other'} access Script access type
163
- * @property {() => Promise<PineIndicator>} get Get the full indicator informations
180
+ * @prop {() => Promise<PineIndicator>} get Get the full indicator informations
164
181
  */
165
182
 
166
183
  /**
167
184
  * Find an indicator
185
+ * @function searchIndicator
168
186
  * @param {string} search Keywords
169
187
  * @returns {Promise<SearchIndicatorResult[]>} Search results
170
188
  */
171
189
  async searchIndicator(search = '') {
172
190
  if (!builtInIndicList.length) {
173
191
  await Promise.all(['standard', 'candlestick', 'fundamental'].map(async (type) => {
174
- builtInIndicList.push(...await request({
192
+ builtInIndicList.push(...(await request({
175
193
  host: 'pine-facade.tradingview.com',
176
194
  path: `/pine-facade/list/?filter=${type}`,
177
- }));
195
+ })).data);
178
196
  }));
179
197
  }
180
198
 
181
- const data = await request({
199
+ const { data } = await request({
182
200
  host: 'www.tradingview.com',
183
201
  path: `/pubscripts-suggest-json/?search=${search.replace(/ /g, '%20')}`,
184
202
  });
@@ -229,6 +247,7 @@ module.exports = {
229
247
 
230
248
  /**
231
249
  * Get an indicator
250
+ * @function getIndicator
232
251
  * @param {string} id Indicator ID (Like: PUB;XXXXXXXXXXXXXXXXXXXXX)
233
252
  * @param {'last' | string} [version] Wanted version of the indicator
234
253
  * @returns {Promise<PineIndicator>} Indicator
@@ -236,7 +255,7 @@ module.exports = {
236
255
  async getIndicator(id, version = 'last') {
237
256
  const indicID = id.replace(/ |%/g, '%25');
238
257
 
239
- let data = await request({
258
+ let { data } = await request({
240
259
  host: 'pine-facade.tradingview.com',
241
260
  path: `/pine-facade/translate/${indicID}/${version}`,
242
261
  }, true);
@@ -309,25 +328,74 @@ module.exports = {
309
328
 
310
329
  /**
311
330
  * @typedef {Object} User Instance of User
312
- * @property {number} id User ID
313
- * @property {string} username User username
314
- * @property {string} firstName User first name
315
- * @property {string} lastName User last name
316
- * @property {number} reputation User reputation
317
- * @property {number} following Number of following accounts
318
- * @property {number} followers Number of followers
319
- * @property {Object} notifications User's notifications
320
- * @property {number} notifications.user User notifications
321
- * @property {number} notifications.following Notification from following accounts
322
- * @property {string} session User session
323
- * @property {string} sessionHash User session hash
324
- * @property {string} privateChannel User private channel
325
- * @property {string} authToken User auth token
326
- * @property {Date} joinDate Account creation date
331
+ * @prop {number} id User ID
332
+ * @prop {string} username User username
333
+ * @prop {string} firstName User first name
334
+ * @prop {string} lastName User last name
335
+ * @prop {number} reputation User reputation
336
+ * @prop {number} following Number of following accounts
337
+ * @prop {number} followers Number of followers
338
+ * @prop {Object} notifications User's notifications
339
+ * @prop {number} notifications.user User notifications
340
+ * @prop {number} notifications.following Notification from following accounts
341
+ * @prop {string} session User session
342
+ * @prop {string} sessionHash User session hash
343
+ * @prop {string} privateChannel User private channel
344
+ * @prop {string} authToken User auth token
345
+ * @prop {Date} joinDate Account creation date
327
346
  */
328
347
 
329
348
  /**
330
- * Get a token for an user from a 'sessionid' cookie
349
+ * Get user and sessionid from username/email and password
350
+ * @function loginUser
351
+ * @param {string} username User username/email
352
+ * @param {string} password User password
353
+ * @param {boolean} [remember] Remember the session (default: false)
354
+ * @param {string} [UA] Custom UserAgent
355
+ * @returns {Promise<User>} Token
356
+ */
357
+ async loginUser(username, password, remember = true, UA = 'TWAPI/3.0') {
358
+ const formData = new FormData();
359
+ formData.append('username', username);
360
+ formData.append('password', password);
361
+ if (remember) formData.append('remember', 'on');
362
+
363
+ const { data, cookies } = await request({
364
+ method: 'POST',
365
+ host: 'www.tradingview.com',
366
+ path: '/accounts/signin/',
367
+ headers: {
368
+ referer: 'https://www.tradingview.com',
369
+ 'Content-Type': `multipart/form-data; boundary=${formData.boundary}`,
370
+ 'User-agent': `${UA} (${os.version()}; ${os.platform()}; ${os.arch()})`,
371
+ },
372
+ }, false, formData.toString());
373
+
374
+ if (data.error) throw new Error(data.error);
375
+
376
+ const cookie = cookies.find((c) => c.includes('sessionid='));
377
+ const session = (cookie.match(/sessionid=(.*?);/) ?? [])[1];
378
+
379
+ return {
380
+ id: data.user.id,
381
+ username: data.user.username,
382
+ firstName: data.user.first_name,
383
+ lastName: data.user.last_name,
384
+ reputation: data.user.reputation,
385
+ following: data.user.following,
386
+ followers: data.user.followers,
387
+ notifications: data.user.notification_count,
388
+ session,
389
+ sessionHash: data.user.session_hash,
390
+ privateChannel: data.user.private_channel,
391
+ authToken: data.user.auth_token,
392
+ joinDate: new Date(data.user.date_joined),
393
+ };
394
+ },
395
+
396
+ /**
397
+ * Get user from 'sessionid' cookie
398
+ * @function getUser
331
399
  * @param {string} session User 'sessionid' cookie
332
400
  * @param {string} [location] Auth page location (For france: https://fr.tradingview.com/)
333
401
  * @returns {Promise<User>} Token
@@ -373,6 +441,7 @@ module.exports = {
373
441
 
374
442
  /**
375
443
  * Get user's private indicators from a 'sessionid' cookie
444
+ * @function getPrivateIndicators
376
445
  * @param {string} session User 'sessionid' cookie
377
446
  * @returns {Promise<SearchIndicatorResult[]>} Search results
378
447
  */
@@ -420,12 +489,13 @@ module.exports = {
420
489
  /**
421
490
  * User credentials
422
491
  * @typedef {Object} UserCredentials
423
- * @property {number} id User ID
424
- * @property {string} session User session ('sessionid' cookie)
492
+ * @prop {number} id User ID
493
+ * @prop {string} session User session ('sessionid' cookie)
425
494
  */
426
495
 
427
496
  /**
428
497
  * Get a chart token from a layout ID and the user credentials if the layout is not public
498
+ * @function getChartToken
429
499
  * @param {string} layout The layout ID found in the layout URL (Like: 'XXXXXXXX')
430
500
  * @param {UserCredentials} [credentials] User credentials (id + session)
431
501
  * @returns {Promise<string>} Token
@@ -435,7 +505,7 @@ module.exports = {
435
505
  const userID = creds ? credentials.id : -1;
436
506
  const session = creds ? credentials.session : null;
437
507
 
438
- const data = await request({
508
+ const { data } = await request({
439
509
  host: 'www.tradingview.com',
440
510
  path: `/chart-token/?image_url=${layout}&user_id=${userID}`,
441
511
  headers: { cookie: session ? `sessionid=${session}` : '' },
@@ -448,32 +518,33 @@ module.exports = {
448
518
 
449
519
  /**
450
520
  * @typedef {Object} DrawingPoint Drawing poitn
451
- * @property {number} time_t Point X time position
452
- * @property {number} price Point Y price position
453
- * @property {number} offset Point offset
521
+ * @prop {number} time_t Point X time position
522
+ * @prop {number} price Point Y price position
523
+ * @prop {number} offset Point offset
454
524
  */
455
525
 
456
526
  /**
457
527
  * @typedef {Object} Drawing
458
- * @property {string} id Drawing ID (Like: 'XXXXXX')
459
- * @property {string} symbol Layout market symbol (Like: 'BINANCE:BUCEUR')
460
- * @property {string} ownerSource Owner user ID (Like: 'XXXXXX')
461
- * @property {string} serverUpdateTime Drawing last update timestamp
462
- * @property {string} currencyId Currency ID (Like: 'EUR')
463
- * @property {any} unitId Unit ID
464
- * @property {string} type Drawing type
465
- * @property {DrawingPoint[]} points List of drawing points
466
- * @property {number} zorder Drawing Z order
467
- * @property {string} linkKey Drawing link key
468
- * @property {Object} state Drawing state
528
+ * @prop {string} id Drawing ID (Like: 'XXXXXX')
529
+ * @prop {string} symbol Layout market symbol (Like: 'BINANCE:BUCEUR')
530
+ * @prop {string} ownerSource Owner user ID (Like: 'XXXXXX')
531
+ * @prop {string} serverUpdateTime Drawing last update timestamp
532
+ * @prop {string} currencyId Currency ID (Like: 'EUR')
533
+ * @prop {any} unitId Unit ID
534
+ * @prop {string} type Drawing type
535
+ * @prop {DrawingPoint[]} points List of drawing points
536
+ * @prop {number} zorder Drawing Z order
537
+ * @prop {string} linkKey Drawing link key
538
+ * @prop {Object} state Drawing state
469
539
  */
470
540
 
471
541
  /**
472
542
  * Get a chart token from a layout ID and the user credentials if the layout is not public
543
+ * @function getDrawings
473
544
  * @param {string} layout The layout ID found in the layout URL (Like: 'XXXXXXXX')
474
545
  * @param {string | ''} [symbol] Market filter (Like: 'BINANCE:BTCEUR')
475
546
  * @param {UserCredentials} [credentials] User credentials (id + session)
476
- * @param {number} [chartID = 1] Chart ID
547
+ * @param {number} [chartID] Chart ID
477
548
  * @returns {Promise<Drawing[]>} Drawings
478
549
  */
479
550
  async getDrawings(layout, symbol = '', credentials = {}, chartID = 1) {
@@ -481,7 +552,7 @@ module.exports = {
481
552
  const creds = credentials.id && credentials.session;
482
553
  const session = creds ? credentials.session : null;
483
554
 
484
- const data = await request({
555
+ const { data } = await request({
485
556
  host: 'charts-storage.tradingview.com',
486
557
  path: `/charts-storage/layout/${layout}/sources?chart_id=${chartID
487
558
  }&jwt=${chartToken}${symbol ? `&symbol=${symbol}` : ''}`,
package/src/protocol.js CHANGED
@@ -6,14 +6,18 @@ const JSZip = require('jszip');
6
6
  * @prop {[session: string, {}]} [p] Packet data
7
7
  */
8
8
 
9
+ const cleanerRgx = /~h~/g;
10
+ const splitterRgx = /~m~[0-9]{1,}~m~/g;
11
+
9
12
  module.exports = {
10
13
  /**
11
14
  * Parse websocket packet
15
+ * @function parseWSPacket
12
16
  * @param {string} str Websocket raw data
13
17
  * @returns {TWPacket[]} TradingView packets
14
18
  */
15
19
  parseWSPacket(str) {
16
- return str.replace(/~h~/g, '').split(/~m~[0-9]{1,}~m~/g)
20
+ return str.replace(cleanerRgx, '').split(splitterRgx)
17
21
  .map((p) => {
18
22
  if (!p) return false;
19
23
  try {
@@ -28,6 +32,7 @@ module.exports = {
28
32
 
29
33
  /**
30
34
  * Format websocket packet
35
+ * @function formatWSPacket
31
36
  * @param {TWPacket} packet TradingView packet
32
37
  * @returns {string} Websocket raw data
33
38
  */
@@ -40,6 +45,7 @@ module.exports = {
40
45
 
41
46
  /**
42
47
  * Parse compressed data
48
+ * @function parseCompressed
43
49
  * @param {string} data Compressed data
44
50
  * @returns {Promise<{}>} Parsed data
45
51
  */
package/src/request.js CHANGED
@@ -1,37 +1,37 @@
1
- const https = require('https');
2
-
3
- /**
4
- * @param {https.RequestOptions} options HTTPS Request options
5
- * @param {boolean} [raw] Get raw or JSON data
6
- * @param {string} [content] Request body content
7
- * @returns {Promise<string | object | array>} Result
8
- */
9
- function request(options = {}, raw = false, content = '') {
10
- return new Promise((cb, err) => {
11
- const req = https.request(options, (res) => {
12
- let data = '';
13
- res.on('data', (c) => { data += c; });
14
- res.on('end', () => {
15
- if (raw) {
16
- cb(data);
17
- return;
18
- }
19
-
20
- try {
21
- data = JSON.parse(data);
22
- } catch (error) {
23
- console.log(data);
24
- err(new Error('Can\'t parse server response'));
25
- return;
26
- }
27
-
28
- cb(data);
29
- });
30
- });
31
-
32
- req.on('error', err);
33
- req.end(content);
34
- });
35
- }
36
-
37
- module.exports = request;
1
+ const https = require('https');
2
+
3
+ /**
4
+ * @param {https.RequestOptions} options HTTPS Request options
5
+ * @param {boolean} [raw] Get raw or JSON data
6
+ * @param {string} [content] Request body content
7
+ * @returns {Promise<{ data: (string | object | array), cookies: string[] }>} Result
8
+ */
9
+ function request(options = {}, raw = false, content = '') {
10
+ return new Promise((cb, err) => {
11
+ const req = https.request(options, (res) => {
12
+ let data = '';
13
+ res.on('data', (c) => { data += c; });
14
+ res.on('end', () => {
15
+ if (raw) {
16
+ cb({ data, cookies: res.headers['set-cookie'] });
17
+ return;
18
+ }
19
+
20
+ try {
21
+ data = JSON.parse(data);
22
+ } catch (error) {
23
+ console.log(data);
24
+ err(new Error('Can\'t parse server response'));
25
+ return;
26
+ }
27
+
28
+ cb({ data, cookies: res.headers['set-cookie'] });
29
+ });
30
+ });
31
+
32
+ req.on('error', err);
33
+ req.end(content);
34
+ });
35
+ }
36
+
37
+ module.exports = request;
package/src/types.js CHANGED
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * @typedef {string} MarketSymbol Market symbol (like: 'BTCEUR' or 'KRAKEN:BTCEUR')
3
- *
3
+ */
4
+
5
+ /**
4
6
  * @typedef {'Etc/UTC' | 'exchange'
5
7
  * | 'Pacific/Honolulu' | 'America/Juneau' | 'America/Los_Angeles'
6
8
  * | 'America/Phoenix' | 'America/Vancouver' | 'US/Mountain'
@@ -23,7 +25,9 @@
23
25
  * | 'Asia/Taipei' | 'Asia/Seoul' | 'Asia/Tokyo' | 'Australia/Brisbane'
24
26
  * | 'Australia/Adelaide' | 'Australia/Sydney' | 'Pacific/Norfolk'
25
27
  * | 'Pacific/Auckland' | 'Pacific/Fakaofo' | 'Pacific/Chatham'} Timezone (Chart) timezone
26
- *
28
+ */
29
+
30
+ /**
27
31
  * @typedef {'1' | '3' | '5' | '15' | '30'
28
32
  * | '45' | '60' | '120' | '180' | '240'
29
33
  * | '1D' | '1W' | '1M' | 'D' | 'W' | 'M'} TimeFrame
package/src/utils.js CHANGED
@@ -1,4 +1,10 @@
1
1
  module.exports = {
2
+ /**
3
+ * Generates a session id
4
+ * @function genSessionID
5
+ * @param {String} type Session type
6
+ * @returns {string}
7
+ */
2
8
  genSessionID(type = 'xs') {
3
9
  let r = '';
4
10
  const c = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
package/test.js CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-continue */
1
2
  /* eslint-disable no-await-in-loop */
2
3
  /* eslint-disable import/no-dynamic-require */
3
4
  /* eslint-disable no-restricted-syntax */
@@ -37,6 +38,7 @@ function success() {
37
38
  console.info('§90§30§104 ==== Starting tests ==== §0');
38
39
 
39
40
  for (const file of fs.readdirSync('./tests').filter((f) => f.endsWith('.js'))) {
41
+ if (process.argv[2] && !file.startsWith(process.argv[2])) continue;
40
42
  const test = require(`./tests/${file}`);
41
43
  const name = file.replace(/\.js/g, '');
42
44
  TESTS[name] = { errors: 0, warnings: 0 };
@@ -65,9 +65,10 @@ module.exports = async (log, success, warn, err, cb) => {
65
65
 
66
66
  QTY += 10;
67
67
  log('TRY WITH', QTY, '%');
68
- indicator.setOption('default_qty_value', QTY);
69
-
70
- SuperTrend.setIndicator(indicator);
68
+ setTimeout(() => {
69
+ indicator.setOption('default_qty_value', QTY);
70
+ SuperTrend.setIndicator(indicator);
71
+ }, 1000);
71
72
  });
72
73
  });
73
74
 
@@ -1,34 +0,0 @@
1
- const TradingView = require('../main');
2
-
3
- /*
4
- This example tests an indicator that sends
5
- graphic data such as 'lines', 'labels',
6
- 'boxes', 'tables', 'polygons', etc...
7
- */
8
-
9
- const client = new TradingView.Client();
10
-
11
- const chart = new client.Session.Chart();
12
-
13
- let wantedTimeframe = '5';
14
- let timeframe = null;
15
-
16
- chart.setMarket('BINANCE:BTCEUR', {
17
- timeframe: wantedTimeframe,
18
- });
19
-
20
- chart.onSymbolLoaded(() => {
21
- timeframe = wantedTimeframe;
22
- console.log(`Timeframe is now '${timeframe}'`);
23
- });
24
-
25
- chart.onUpdate(() => {
26
- console.log(`Received data on '${timeframe}' timeframe`);
27
- });
28
-
29
- setTimeout(() => {
30
- wantedTimeframe = '240';
31
- chart.setMarket('BINANCE:BTCEUR', {
32
- timeframe: wantedTimeframe,
33
- });
34
- }, 3000);
@@ -1,41 +0,0 @@
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
- });
@@ -1,24 +0,0 @@
1
- const TradingView = require('../main');
2
-
3
- module.exports = async (log, success, warn, err, cb) => {
4
- const client = new TradingView.Client();
5
-
6
- client.onError((...error) => {
7
- err('Client error', error);
8
- throw new Error('Client error');
9
- });
10
-
11
- const chart = new client.Session.Chart();
12
- chart.setMarket('BINANCE:BTCEUR', {
13
- timeframe: '60',
14
- });
15
-
16
- chart.onError((...error) => {
17
- err('Chart error', error);
18
- throw new Error('Chart error');
19
- });
20
-
21
- chart.delete();
22
- await client.end();
23
- cb();
24
- };