@mathieuc/tradingview 3.0.1 → 3.2.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.
@@ -0,0 +1,115 @@
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
+
13
+ chart.onError((...error) => {
14
+ err('Chart error', error);
15
+ throw new Error('Chart error');
16
+ });
17
+
18
+ /* (0s) Heikin Ashi chart */
19
+ setTimeout(() => {
20
+ log('Setting chart type to: HeikinAshi');
21
+
22
+ chart.setMarket('BINANCE:BTCEUR', {
23
+ type: 'HeikinAshi',
24
+ timeframe: 'D',
25
+ });
26
+ }, 0);
27
+
28
+ /* (1s) Renko chart */
29
+ setTimeout(() => {
30
+ log('Setting chart type to: Renko');
31
+
32
+ chart.setMarket('BINANCE:BTCEUR', {
33
+ type: 'Renko',
34
+ timeframe: 'D',
35
+ inputs: {
36
+ source: 'close',
37
+ sources: 'Close',
38
+ boxSize: 3,
39
+ style: 'ATR',
40
+ atrLength: 14,
41
+ wicks: true,
42
+ },
43
+ });
44
+ }, 1000);
45
+
46
+ /* (2s) Line Break chart */
47
+ setTimeout(() => {
48
+ log('Setting chart type to: LineBreak');
49
+
50
+ chart.setMarket('BINANCE:BTCEUR', {
51
+ type: 'LineBreak',
52
+ timeframe: 'D',
53
+ inputs: {
54
+ source: 'close',
55
+ lb: 3,
56
+ },
57
+ });
58
+ }, 2000);
59
+
60
+ /* (3s) Kagi chart */
61
+ setTimeout(() => {
62
+ log('Setting chart type to: Kagi');
63
+
64
+ chart.setMarket('BINANCE:BTCEUR', {
65
+ type: 'Kagi',
66
+ timeframe: 'D',
67
+ inputs: {
68
+ source: 'close',
69
+ style: 'ATR',
70
+ atrLength: 14,
71
+ reversalAmount: 1,
72
+ },
73
+ });
74
+ }, 3000);
75
+
76
+ /* (4s) Point & Figure chart */
77
+ setTimeout(() => {
78
+ log('Setting chart type to: PointAndFigure');
79
+
80
+ chart.setMarket('BINANCE:BTCEUR', {
81
+ type: 'PointAndFigure',
82
+ timeframe: 'D',
83
+ inputs: {
84
+ sources: 'Close',
85
+ reversalAmount: 3,
86
+ boxSize: 1,
87
+ style: 'ATR',
88
+ atrLength: 14,
89
+ oneStepBackBuilding: false,
90
+ },
91
+ });
92
+ }, 4000);
93
+
94
+ /* (5s) Range chart */
95
+ setTimeout(() => {
96
+ log('Setting chart type to: Range');
97
+
98
+ chart.setMarket('BINANCE:BTCEUR', {
99
+ type: 'Range',
100
+ timeframe: 'D',
101
+ inputs: {
102
+ range: 1,
103
+ phantomBars: false,
104
+ },
105
+ });
106
+ }, 5000);
107
+
108
+ /* (6s) Delete chart, close client */
109
+ setTimeout(async () => {
110
+ success('Closing client...');
111
+ chart.delete();
112
+ await client.end();
113
+ cb();
114
+ }, 6000);
115
+ };
@@ -0,0 +1,146 @@
1
+ const TradingView = require('../main');
2
+
3
+ module.exports = async (log, success, warn, err, cb) => {
4
+ const client = new TradingView.Client(); // Creates a websocket client
5
+
6
+ const tests = [
7
+ (next) => { /* Testing "Credentials error" */
8
+ log('Testing "Credentials error" error:');
9
+
10
+ const client2 = new TradingView.Client({
11
+ token: 'FAKE_CREDENTIALS', // Set wrong credentials
12
+ });
13
+
14
+ client2.onError((...error) => {
15
+ success('=> Client error:', error);
16
+ client2.end();
17
+ next();
18
+ });
19
+ },
20
+
21
+ (next) => { /* Testing "Invalid symbol" */
22
+ log('Testing "Invalid symbol" error:');
23
+
24
+ const chart = new client.Session.Chart();
25
+ chart.onError((...error) => { // Listen for errors
26
+ success('=> Chart error:', error);
27
+ chart.delete();
28
+ next();
29
+ });
30
+
31
+ chart.setMarket('XXXXX'); // Set a wrong market
32
+ },
33
+
34
+ (next) => { /* Testing "Invalid timezone" */
35
+ log('Testing "Invalid timezone" error:');
36
+
37
+ const chart = new client.Session.Chart();
38
+ chart.onError((...error) => { // Listen for errors
39
+ success('=> Chart error:', error);
40
+ next();
41
+ });
42
+
43
+ chart.setMarket('BINANCE:BTCEUR'); // Set a market
44
+ chart.setTimezone('Nowhere/Nowhere'); // Set a fake timezone
45
+ },
46
+
47
+ (next) => { /* Testing "Custom timeframe" */
48
+ log('Testing "Custom timeframe" error:');
49
+
50
+ const chart = new client.Session.Chart();
51
+ chart.onError((...error) => { // Listen for errors
52
+ success('=> Chart error:', error);
53
+ chart.delete();
54
+ next();
55
+ });
56
+
57
+ chart.setMarket('BINANCE:BTCEUR', { // Set a market
58
+ timeframe: '20', // Set a custom timeframe
59
+ /*
60
+ Timeframe '20' isn't available because we are
61
+ not logged in as a premium TradingView account
62
+ */
63
+ });
64
+ },
65
+
66
+ (next) => { /* Testing "Invalid timeframe" */
67
+ log('Testing "Invalid timeframe" error:');
68
+
69
+ const chart = new client.Session.Chart();
70
+ chart.onError((...error) => { // Listen for errors
71
+ success('=> Chart error:', error);
72
+ next();
73
+ });
74
+
75
+ chart.setMarket('BINANCE:BTCEUR', { // Set a market
76
+ timeframe: 'XX', // Set a wrong timeframe
77
+ });
78
+ },
79
+
80
+ (next) => { /* Testing "Study not auth" */
81
+ log('Testing "Study not auth" error:');
82
+
83
+ const chart = new client.Session.Chart();
84
+ chart.onError((...error) => { // Listen for errors
85
+ success('=> Chart error:', error);
86
+ next();
87
+ });
88
+
89
+ chart.setMarket('BINANCE:BTCEUR', { // Set a market
90
+ timeframe: '15',
91
+ type: 'Renko',
92
+ });
93
+
94
+ chart.onUpdate(() => {
95
+ log('DATA', chart.periods[0]);
96
+ });
97
+ },
98
+
99
+ (next) => { /* Testing "Set the market before" */
100
+ log('Testing "Set the market before..." error:');
101
+
102
+ const chart = new client.Session.Chart();
103
+ chart.onError((...error) => { // Listen for errors
104
+ success('=> Chart error:', error);
105
+ chart.delete();
106
+ next();
107
+ });
108
+
109
+ chart.setSeries('15'); // Set series before setting the market
110
+ },
111
+
112
+ (next) => { /* Testing "Inexistent indicator" */
113
+ log('Testing "Inexistent indicator" error:');
114
+
115
+ TradingView.getIndicator('STD;XXXXXXX')
116
+ .catch((error) => {
117
+ success('=> API error:', [error.message]);
118
+ next();
119
+ });
120
+ },
121
+
122
+ async (next) => { /* Testing "Invalid value" */
123
+ log('Testing "Invalid value" error:');
124
+
125
+ const chart = new client.Session.Chart();
126
+ chart.setMarket('BINANCE:BTCEUR'); // Set a market
127
+
128
+ const ST = await TradingView.getIndicator('STD;Supertrend');
129
+ ST.setOption('Factor', -1); // This will cause an error
130
+
131
+ const Supertrend = new chart.Study(ST);
132
+ Supertrend.onError((...error) => {
133
+ success('=> Study error:', error);
134
+ chart.delete();
135
+ next();
136
+ });
137
+ },
138
+ ];
139
+
140
+ (async () => {
141
+ // eslint-disable-next-line no-restricted-syntax, no-await-in-loop
142
+ for (const t of tests) await new Promise(t);
143
+ success(`Crashtests ${tests.length}/${tests.length} done !`);
144
+ cb();
145
+ })();
146
+ };
@@ -0,0 +1,24 @@
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
+ };
@@ -1 +0,0 @@
1
- github: Mathieu2301
@@ -1,76 +0,0 @@
1
- const https = require('https');
2
-
3
- /**
4
- * @typedef {Object} WebhookMessage Represents a Discord webhook message
5
- * @property {string} content
6
- * @property {Embed[]} [embeds]
7
- */
8
-
9
- /**
10
- * @typedef {Object} Embed Discord Embed
11
- * @property {string} [title]
12
- * @property {string} [description]
13
- * @property {number} [color]
14
- * @property {string} [url]
15
- * @property {string} [timestamp]
16
-
17
- * @property {Object} [author]
18
- * @property {string} [author.name]
19
- * @property {string} [author.icon_url]
20
- * @property {string} [author.url]
21
-
22
- * @property {Object} [thumbnail]
23
- * @property {string} [thumbnail.url]
24
-
25
- * @property {Object} [footer]
26
- * @property {string} [footer.text]
27
- * @property {string} [footer.icon_url]
28
- */
29
-
30
- /**
31
- * @typedef {Object} SendResult
32
- * @property {boolean} success
33
- * @property {Object} [result] If error
34
- * @property {string[]} [result.webhook_id]
35
- */
36
-
37
- /**
38
- * Create an instance of Discord Webhook API
39
- * @param {string} token Discord Webhook token (after .../api/webhooks/)
40
- */
41
-
42
- module.exports = function createInstance(token = '') {
43
- /**
44
- * Send a message
45
- * @name MessageSender
46
- * @param {WebhookMessage} message
47
- * @returns {Promise<SendResult>}
48
- */
49
- return (message) => new Promise((cb, err) => {
50
- const req = https.request({
51
- method: 'POST',
52
- hostname: 'discordapp.com',
53
- path: `/api/webhooks/${token}`,
54
- headers: {
55
- 'Content-Type': 'application/json',
56
- },
57
- maxRedirects: 20,
58
- }, (res) => {
59
- let data = '';
60
- res.on('data', (d) => { data += d; });
61
- res.on('end', () => {
62
- if (!data) cb({ success: true });
63
- else {
64
- cb({
65
- success: false,
66
- result: JSON.parse(data),
67
- });
68
- }
69
- });
70
- });
71
-
72
- req.on('error', err);
73
- req.write(JSON.stringify(message));
74
- req.end();
75
- });
76
- };
@@ -1,41 +0,0 @@
1
- require('./envLoader');
2
- const marketAPI = require('../../main');
3
-
4
- if (!process.env.LAYOUT_ID) console.error('You need to set a layout id');
5
-
6
- const market = marketAPI(false);
7
-
8
- console.log('Connecting...');
9
-
10
- (async () => {
11
- /*
12
- * Important ! If you want to get a layout without login, you have to
13
- * set it in public mode. If you get an error, please wait few minutes.
14
- * Try getting to https://www.tradingview.com/chart/LAYOUT_ID/ in incognito mode.
15
- */
16
- const user = (process.env.SESSION_ID) ? await market.getUser(process.env.SESSION_ID) : {};
17
- console.log('Connected as', user.firstName || user.username || 'anonymous', '!');
18
-
19
- console.log(`Gettings drawings of '${process.env.LAYOUT_ID}' layout...`);
20
-
21
- const drawings = await market.getDrawings(process.env.LAYOUT_ID, '', {
22
- id: user.id,
23
- session: user.session,
24
- });
25
-
26
- const lines = drawings.filter((d) => (
27
- ['LineToolHorzLine', 'LineToolRay', 'LineToolTrendLine', 'LineToolHorzRay'].includes(d.type)
28
- && d.state.linestyle === 0
29
- && d.state.linewidth === 4
30
- ));
31
-
32
- console.log(
33
- `Found ${drawings.length} result(s) including ${lines.length} thick line(s):`,
34
- lines.map((l) => ({
35
- market: l.symbol,
36
- type: l.type,
37
- points: l.points,
38
- text: l.state.text,
39
- })),
40
- );
41
- })();
@@ -1,11 +0,0 @@
1
- const fs = require('fs');
2
-
3
- if (fs.existsSync('.env')) {
4
- const envFile = fs.readFileSync('.env', 'utf8');
5
- envFile.split('\n') // LF
6
- .forEach((l) => {
7
- const s = l.split('=');
8
- // eslint-disable-next-line
9
- if (s[1]) process.env[s[0]] = s[1];
10
- });
11
- }
@@ -1,77 +0,0 @@
1
- require('./envLoader');
2
- const { getSentNotifs, addSentNotifs } = require('./sentNotifs');
3
- const marketAPI = require('../../main');
4
- const discordWH = require('./discordWH')(process.env.DISCORD_TOKEN);
5
-
6
- if (!process.env.SYMBOLS) process.env.SYMBOLS = 'BTCEUR';
7
- if (!process.env.PERIOD) process.env.PERIOD = '240';
8
-
9
- const market = marketAPI(false);
10
-
11
- market.on('logged', () => {
12
- process.env.SYMBOLS.split(',').forEach((symbol) => {
13
- console.log('Listen', symbol);
14
-
15
- market.initChart({
16
- symbol,
17
- period: process.env.PERIOD,
18
- range: 30,
19
- timezone: 'Europe/Paris',
20
- indicators: [
21
- { name: 'CIPHER_A', id: 'PUB;vrOJcNRPULteowIsuP6iHn3GIxBJdXwT', version: '1.0' },
22
- {
23
- name: 'CIPHER_B',
24
- id: 'PUB;uA35GeckoTA2EfgI63SD2WCSmca4njxp',
25
- settings: [ // Activate Stoch divergences
26
- true, true, true, true, true, true, 9, 12,
27
- 'hlc3', 3, 53, 60, 100, -53, -60, -75, true,
28
- true, true, 45, -65, true, 15, -40, true, 60,
29
- 150, 2.5, false, 'close', 14, 30, 60, false,
30
- false, 60, 30, true, true, false, 'close', 14,
31
- 14, 3, 3, true, true, false, 'close', 10, 23,
32
- 50, 0.5, false, false, '720', 0, 0, 0, 0, 0, 0,
33
- false, '60', '240', 0, 0, false, '240', false,
34
- ],
35
- version: '15.0',
36
- },
37
- ],
38
- }, (periods) => {
39
- if (!periods[0].CIPHER_B) return;
40
-
41
- const pBefore = periods[1];
42
- const p = periods[0];
43
-
44
- const gapBefore = pBefore.CIPHER_B.VWAP;
45
- const gap = p.CIPHER_B.VWAP;
46
-
47
- const notifID = `${symbol}@${p.$time}@BULL_TRIGGER`;
48
-
49
- if (
50
- p.CIPHER_B.WTWave1 <= 0 && p.CIPHER_B.WTWave1 > -35
51
- && gapBefore < 0 && gapBefore < gap
52
- && pBefore.CIPHER_B.WTWave1 < p.CIPHER_B.WTWave1
53
- && !getSentNotifs().includes(notifID)
54
- ) {
55
- addSentNotifs(notifID);
56
- console.log(symbol, 'TRIG NOW', new Date(p.$time * 1000).toLocaleString());
57
-
58
- discordWH({
59
- content: process.env.DISCORD_MENTION,
60
- embeds: [
61
- {
62
- title: `Trigger wave on ${symbol} !`,
63
- color: 720640,
64
- description: `Cipher B trigger wave detected on ${symbol}.`,
65
- url: `https://fr.tradingview.com/chart/?symbol=${symbol}`,
66
- timestamp: new Date(p.$time * 1000),
67
- footer: {
68
- text: 'TradingView',
69
- icon_url: 'https://tradingview.com/favicon.ico',
70
- },
71
- },
72
- ],
73
- });
74
- }
75
- });
76
- });
77
- });
@@ -1,16 +0,0 @@
1
- const fs = require('fs');
2
-
3
- const sentNotifsFile = './sentNotifs.txt';
4
-
5
- exports.getSentNotifs = () => {
6
- if (!fs.existsSync(sentNotifsFile)) fs.writeFileSync(sentNotifsFile, '');
7
- return (fs.readFileSync(sentNotifsFile, 'utf8') || '').split(';').filter((n) => n);
8
- };
9
-
10
- exports.addSentNotifs = (notif = '') => {
11
- if (!fs.existsSync(sentNotifsFile)) fs.writeFileSync(sentNotifsFile, '');
12
- fs.writeFileSync(
13
- sentNotifsFile,
14
- `${fs.readFileSync(sentNotifsFile, 'utf8') || ''}${notif};`,
15
- );
16
- };
@@ -1,94 +0,0 @@
1
- require('./envLoader');
2
- const { getSentNotifs, addSentNotifs } = require('./sentNotifs');
3
- const marketAPI = require('../../main');
4
- const discordWH = require('./discordWH')(process.env.DISCORD_TOKEN);
5
-
6
- const markets = [
7
- {
8
- symbol: 'EURUSD',
9
- period: '1D',
10
- settings: {
11
- 1: 21, // HMA 1 Length
12
- 3: 89, // HMA 2 Length
13
- 5: 7, // RSI Length
14
- 8: 2, // Stop Loss (%)
15
- 9: 1, // Take Profit (%)
16
- },
17
- },
18
- {
19
- symbol: 'GBPUSD',
20
- period: '1D',
21
- settings: {
22
- 1: 220, // HMA 1 Length
23
- 3: 150, // HMA 2 Length
24
- 5: 1, // RSI Length
25
- 8: 2, // Stop Loss (%)
26
- 9: 1, // Take Profit (%)
27
- },
28
- },
29
- {
30
- symbol: 'USDCAD',
31
- period: '1D',
32
- settings: {
33
- 1: 21, // HMA 1 Length
34
- 3: 89, // HMA 2 Length
35
- 5: 10, // RSI Length
36
- 8: 3, // Stop Loss (%)
37
- 9: 2, // Take Profit (%)
38
- },
39
- },
40
- ];
41
-
42
- const market = marketAPI(false);
43
-
44
- market.on('logged', () => {
45
- markets.forEach((mrk) => {
46
- console.log('Listen', mrk.symbol);
47
-
48
- market.initChart({
49
- symbol: mrk.symbol,
50
- period: mrk.period || '1D',
51
- range: mrk.range || 30,
52
- timezone: mrk.timezone || 'Europe/Paris',
53
- indicators: [
54
- // My Magimix Indicator
55
- {
56
- name: 'MAGIMIX',
57
- id: 'USER;d90a5e852ddc439b994db6beff14d702',
58
- version: mrk.version || 'last',
59
- settings: mrk.settings || [],
60
- },
61
- ],
62
- }, ({ 0: p }) => {
63
- if (!p.MAGIMIX) return;
64
-
65
- const signalType = p.MAGIMIX.Longsignal ? 'LONG' : 'SHORT';
66
- const notifID = `${mrk.symbol}@MAGIMIX@${p.$time}@${signalType}`;
67
-
68
- if (
69
- (p.MAGIMIX.Longsignal || p.MAGIMIX.Shortsignal)
70
- && !getSentNotifs().includes(notifID)
71
- ) {
72
- addSentNotifs(notifID);
73
- console.log(mrk.symbol, 'SIGNAL', new Date(p.$time * 1000).toLocaleString());
74
-
75
- discordWH({
76
- content: process.env.DISCORD_MENTION,
77
- embeds: [
78
- {
79
- title: `Magimix ${signalType} signal for ${mrk.symbol} !`,
80
- color: p.MAGIMIX.Longsignal ? 3066993 : 15158332,
81
- description: `Magimix ${signalType} signal for ${mrk.symbol} at ${p.$prices.close} !`,
82
- url: `https://fr.tradingview.com/chart/?symbol=${mrk.symbol}`,
83
- timestamp: new Date(p.$time * 1000),
84
- footer: {
85
- text: 'TradingView',
86
- icon_url: 'https://tradingview.com/favicon.ico',
87
- },
88
- },
89
- ],
90
- });
91
- }
92
- });
93
- });
94
- });
package/tests/analysis.js DELETED
@@ -1,13 +0,0 @@
1
- const marketAPI = require('../main');
2
-
3
- (async () => {
4
- const market = marketAPI(false);
5
-
6
- const searchBTC = (await market.search('bitcoin euro', 'crypto'))[0];
7
- console.log('Found Bitcoin / Euro:', searchBTC);
8
-
9
- const TA = await searchBTC.getTA();
10
- console.log('Full technical analysis for Bitcoin:', TA);
11
-
12
- // You can also use this way: await market.getTA('crypto', 'BINANCE:BTCEUR');
13
- })();
@@ -1,42 +0,0 @@
1
- const marketAPI = require('../main');
2
-
3
- const market = marketAPI(false);
4
-
5
- market.on('logged', () => {
6
- market.initChart({
7
- symbol: 'COINBASE:BTCEUR',
8
- period: '240',
9
- range: 50,
10
- indicators: [
11
- { name: 'ACCU_DISTRIB', id: 'STD;Accumulation_Distribution', version: '25' },
12
- { name: 'CIPHER_A', id: 'PUB;vrOJcNRPULteowIsuP6iHn3GIxBJdXwT', version: '1.0' },
13
- {
14
- name: 'CIPHER_B',
15
- id: 'PUB;uA35GeckoTA2EfgI63SD2WCSmca4njxp',
16
- settings: [ // Activate Stoch divergences
17
- true, true, true, true, true, true, 9, 12,
18
- 'hlc3', 3, 53, 60, 100, -53, -60, -75, true,
19
- true, true, 45, -65, true, 15, -40, true, 60,
20
- 150, 2.5, false, 'close', 14, 30, 60, false,
21
- false, 60, 30, true, true, false, 'close', 14,
22
- 14, 3, 3, true, true, false, 'close', 10, 23,
23
- 50, 0.5, false, false, '720', 0, 0, 0, 0, 0, 0,
24
- false, '60', '240', 0, 0, false, '240', false,
25
- ],
26
- version: '15.0',
27
- },
28
- // Color Changing Moving Average
29
- { name: 'CCMA', id: 'PUB;5nawr3gCESvSHQfOhrLPqQqT4zM23w3X', version: '6.0' },
30
- ],
31
- }, (periods) => {
32
- if (!periods[0].CIPHER_B) return;
33
- if (!periods[0].CCMA) return;
34
-
35
- console.log('Last period:', {
36
- price: periods[0].$prices.close,
37
- moneyFlow: (periods[0].CIPHER_B.RSIMFIArea >= 0) ? 'POSITIVE' : 'NEGATIVE',
38
- VWAP: periods[0].CIPHER_B.VWAP,
39
- MA: (periods[0].CCMA.Plot <= periods[0].$prices.close) ? 'ABOVE' : 'UNDER',
40
- });
41
- });
42
- });