@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.
- package/README.md +15 -2
- package/examples/AllPrivateIndicators.js +4 -4
- package/examples/CustomChartType.js +1 -0
- package/examples/Errors.js +147 -153
- package/examples/FakeReplayMode.js +41 -0
- package/examples/PinePermManage.js +57 -0
- package/examples/ReplayMode.js +97 -0
- package/main.js +2 -0
- package/package.json +5 -7
- package/src/FormData.js +35 -0
- package/src/chart/session.js +190 -16
- package/src/classes/PinePermManager.js +142 -0
- package/src/client.js +1 -1
- package/src/miscRequests.js +5 -33
- package/src/quote/session.js +1 -0
- package/src/request.js +37 -0
- package/test.js +56 -147
- package/tests/1. Search.js +18 -0
- package/tests/2. QuoteSession.js +54 -0
- package/tests/3. SimpleChart.js +61 -0
- package/tests/4. Indicators.js +99 -0
- package/tests/5. BuiltInIndicator.js +41 -0
- package/tests/6. FakeReplayMode.js +59 -0
- package/tests/7. ReplayMode.js +51 -0
- package/tests/8. CustomChartTypes.js +115 -0
- package/tests/9. AllErrors.js +146 -0
- package/tests/disabled/x. Template.js +24 -0
- package/.github/FUNDING.yml +0 -1
- package/tests/alerts/discordWH.js +0 -76
- package/tests/alerts/drawings.js +0 -41
- package/tests/alerts/envLoader.js +0 -11
- package/tests/alerts/manualAlert.js +0 -77
- package/tests/alerts/sentNotifs.js +0 -16
- package/tests/alerts/strategyAlert.js +0 -94
- package/tests/analysis.js +0 -13
- package/tests/indicator.js +0 -42
- package/tests/prices.js +0 -33
- package/tests/strategy.js +0 -56
|
@@ -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
|
+
};
|
package/.github/FUNDING.yml
DELETED
|
@@ -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
|
-
};
|
package/tests/alerts/drawings.js
DELETED
|
@@ -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
|
-
})();
|
package/tests/indicator.js
DELETED
|
@@ -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
|
-
});
|