@mathieuc/tradingview 3.0.1 → 3.3.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/.eslintrc.js +6 -0
- package/README.md +28 -2
- package/docs/DOCS.md +3 -0
- package/examples/AllPrivateIndicators.js +4 -4
- package/examples/BuiltInIndicator.js +1 -1
- package/examples/CustomChartType.js +1 -0
- package/examples/Errors.js +147 -153
- package/examples/FakeReplayMode.js +41 -0
- package/examples/GetDrawings.js +26 -0
- package/examples/PinePermManage.js +57 -0
- package/examples/ReplayMode.js +97 -0
- package/examples/UserLogin.js +16 -0
- package/main.js +2 -0
- package/package.json +6 -9
- package/src/FormData.js +36 -0
- package/src/chart/session.js +193 -17
- package/src/chart/study.js +68 -68
- package/src/classes/BuiltInIndicator.js +1 -0
- package/src/classes/PineIndicator.js +7 -7
- package/src/classes/PinePermManager.js +143 -0
- package/src/client.js +17 -10
- package/src/miscRequests.js +148 -103
- package/src/protocol.js +7 -1
- package/src/quote/session.js +1 -0
- package/src/request.js +37 -0
- package/src/types.js +6 -2
- package/src/utils.js +6 -0
- package/test.js +58 -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 +100 -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/.github/FUNDING.yml +0 -1
- package/examples/CurrentTimeframe.js +0 -34
- package/examples/_RenkoIndicator.js +0 -41
- 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
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(
|
|
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/quote/session.js
CHANGED
package/src/request.js
ADDED
|
@@ -0,0 +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<{ 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,155 +1,66 @@
|
|
|
1
|
+
/* eslint-disable no-continue */
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
/* eslint-disable import/no-dynamic-require */
|
|
4
|
+
/* eslint-disable no-restricted-syntax */
|
|
5
|
+
/* eslint-disable global-require */
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
1
8
|
require('@mathieuc/console')(
|
|
2
9
|
'§', // Character you want to use (defaut: '§')
|
|
3
10
|
true, // Active timestamp (defaut: false)
|
|
4
11
|
);
|
|
5
12
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const last = chart.periods[0];
|
|
52
|
-
if (!last) return;
|
|
53
|
-
log(`Market last period: ${last.close}`);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
TradingView.getIndicator('STD;Supertrend%Strategy').then((indicator) => {
|
|
57
|
-
indicator.setOption('commission_type', 'percent');
|
|
58
|
-
indicator.setOption('commission_value', 0);
|
|
59
|
-
indicator.setOption('initial_capital', 25000);
|
|
60
|
-
indicator.setOption('default_qty_value', 20);
|
|
61
|
-
indicator.setOption('default_qty_type', 'percent_of_equity');
|
|
62
|
-
indicator.setOption('currency', 'EUR');
|
|
63
|
-
indicator.setOption('pyramiding', 10);
|
|
64
|
-
|
|
65
|
-
const SuperTrend = new chart.Study(indicator);
|
|
66
|
-
|
|
67
|
-
SuperTrend.onReady(() => {
|
|
68
|
-
log('SuperTrend ready !');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
SuperTrend.onError((...err) => {
|
|
72
|
-
log('SuperTrend ERROR:', err[0]);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// let QTY = 10;
|
|
76
|
-
// setInterval(() => {
|
|
77
|
-
// QTY += 10;
|
|
78
|
-
// console.log('TRY WITH', QTY, '%');
|
|
79
|
-
// indicator.setOption('default_qty_value', QTY);
|
|
80
|
-
|
|
81
|
-
// SuperTrend.setIndicator(indicator);
|
|
82
|
-
// }, 5000);
|
|
83
|
-
|
|
84
|
-
SuperTrend.onUpdate((changes) => {
|
|
85
|
-
// MarketCipher B is a strategy so it sends a strategy report
|
|
86
|
-
log('SuperTrend update:', changes);
|
|
87
|
-
|
|
88
|
-
const perfReport = SuperTrend.strategyReport.performance;
|
|
89
|
-
|
|
90
|
-
log('Performance report:', {
|
|
91
|
-
total: {
|
|
92
|
-
trades: perfReport.all.totalTrades,
|
|
93
|
-
perf: `${Math.round(perfReport.all.netProfitPercent * 10000) / 100} %`,
|
|
94
|
-
profit: `${Math.round(perfReport.all.netProfit * 1000) / 1000} €`,
|
|
95
|
-
},
|
|
96
|
-
buy: {
|
|
97
|
-
trades: perfReport.long.totalTrades,
|
|
98
|
-
perf: `${Math.round(perfReport.long.netProfitPercent * 10000) / 100} %`,
|
|
99
|
-
profit: `${Math.round(perfReport.long.netProfit * 1000) / 1000} €`,
|
|
100
|
-
},
|
|
101
|
-
sell: {
|
|
102
|
-
trades: perfReport.short.totalTrades,
|
|
103
|
-
perf: `${Math.round(perfReport.short.netProfitPercent * 10000) / 100} %`,
|
|
104
|
-
profit: `${Math.round(perfReport.short.netProfit * 1000) / 1000} €`,
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
if (changes.includes('fullReport')) {
|
|
109
|
-
log('Last trade:', SuperTrend.strategyReport.trades[0]);
|
|
110
|
-
// Do something...
|
|
111
|
-
|
|
112
|
-
// // Remove SuperTrend strategy from the chart
|
|
113
|
-
// SuperTrend.remove();
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
TradingView.getIndicator('PUB;uA35GeckoTA2EfgI63SD2WCSmca4njxp').then((indicator) => {
|
|
119
|
-
indicator.setOption('Show_WT_Hidden_Divergences', true);
|
|
120
|
-
indicator.setOption('Show_Stoch_Regular_Divergences', true);
|
|
121
|
-
indicator.setOption('Show_Stoch_Hidden_Divergences', true);
|
|
122
|
-
|
|
123
|
-
const CipherB = new chart.Study(indicator);
|
|
124
|
-
|
|
125
|
-
CipherB.onReady(() => {
|
|
126
|
-
log('MarketCipher B ready !');
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
CipherB.onError((...err) => {
|
|
130
|
-
log('MarketCipher B ERROR:', err[0]);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
CipherB.onUpdate(() => {
|
|
134
|
-
const last = CipherB.periods[0];
|
|
135
|
-
// MarketCipher B is not a strategy so it only sends plots values
|
|
136
|
-
log('MarketCipher B last values:', {
|
|
137
|
-
VWAP: Math.round(last.VWAP * 1000) / 1000,
|
|
138
|
-
moneyFlow: (last.RSIMFIArea >= 0) ? 'POSITIVE' : 'NEGATIVE',
|
|
139
|
-
buyCircle: last.Buy_and_sell_circle && last.VWAP > 0,
|
|
140
|
-
sellCircle: last.Buy_and_sell_circle && last.VWAP < 0,
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Do something...
|
|
13
|
+
const TESTS = {};
|
|
14
|
+
|
|
15
|
+
function err(name) {
|
|
16
|
+
return (...msg) => {
|
|
17
|
+
TESTS[name].errors += 1;
|
|
18
|
+
console.error('§30§101 > §0', ...msg);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function warn(name) {
|
|
23
|
+
return (...msg) => {
|
|
24
|
+
TESTS[name].warnings += 1;
|
|
25
|
+
console.warn('§30§103 > §0', ...msg);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function log() {
|
|
30
|
+
return (...msg) => console.log('§30§107 > §0', ...msg);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function success() {
|
|
34
|
+
return (...msg) => console.info('§30§102 > §0', ...msg);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
(async () => {
|
|
38
|
+
console.info('§90§30§104 ==== Starting tests ==== §0');
|
|
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;
|
|
42
|
+
const test = require(`./tests/${file}`);
|
|
43
|
+
const name = file.replace(/\.js/g, '');
|
|
44
|
+
TESTS[name] = { errors: 0, warnings: 0 };
|
|
45
|
+
console.log(`§90§30§107 ${name}`);
|
|
46
|
+
await new Promise((cb) => test(log(), success(), warn(name), err(name), cb));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.info('§90§30§104 ==== ALL TESTS DONE ==== §0\n');
|
|
50
|
+
Object.keys(TESTS).forEach((t) => {
|
|
51
|
+
let color = '2';
|
|
52
|
+
if (TESTS[t].warnings) color = '3';
|
|
53
|
+
if (TESTS[t].errors) color = '1';
|
|
54
|
+
|
|
55
|
+
console.info(`§90§30§10${color} ${t} §0 §91E§0: ${TESTS[t].errors}§0 §93W§0: ${TESTS[t].warnings}`);
|
|
56
|
+
// console.info(` - §91 Errors:§0 ${TESTS[t].errors}`);
|
|
57
|
+
// console.info(` - §93 Warnings:§0 ${TESTS[t].warnings}`);
|
|
144
58
|
});
|
|
145
|
-
});
|
|
146
59
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// chart.setSeries('240');
|
|
150
|
-
// }, 5000);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
})();
|
|
151
62
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
console.log('§30§101 TIMEOUT §0');
|
|
65
|
+
throw new Error('Timeout');
|
|
66
|
+
}, 60000);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const TradingView = require('../main');
|
|
2
|
+
|
|
3
|
+
module.exports = async (log, success, warn, err, cb) => {
|
|
4
|
+
log('Searching market: \'BINANCE:\'');
|
|
5
|
+
const markets = await TradingView.searchMarket('BINANCE:');
|
|
6
|
+
success('Found', markets.length, 'markets');
|
|
7
|
+
|
|
8
|
+
log('Searching indicator: \'RSI\'');
|
|
9
|
+
const indicators = await TradingView.searchIndicator('RSI');
|
|
10
|
+
success('Found', indicators.length, 'indicators');
|
|
11
|
+
|
|
12
|
+
if (markets.length < 10 || indicators.length < 10) {
|
|
13
|
+
err('Not enough results');
|
|
14
|
+
throw new Error('Not enough results');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
cb();
|
|
18
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const TradingView = require('../main');
|
|
2
|
+
|
|
3
|
+
module.exports = (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 quoteSession = new client.Session.Quote({
|
|
12
|
+
fields: 'all',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const BTC = new quoteSession.Market('BTCEUR');
|
|
16
|
+
|
|
17
|
+
BTC.onLoaded(() => {
|
|
18
|
+
success('BTCEUR LOADED');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const keys = [
|
|
22
|
+
'volume', 'update_mode', 'type', 'timezone',
|
|
23
|
+
'short_name', 'rtc_time', 'rtc', 'rchp', 'ch',
|
|
24
|
+
'rch', 'provider_id', 'pro_name', 'pricescale',
|
|
25
|
+
'prev_close_price', 'original_name', 'lp',
|
|
26
|
+
'open_price', 'minmove2', 'minmov', 'lp_time',
|
|
27
|
+
'low_price', 'is_tradable', 'high_price',
|
|
28
|
+
'fractional', 'exchange', 'description',
|
|
29
|
+
'current_session', 'currency_code', 'chp',
|
|
30
|
+
'currency-logoid', 'base-currency-logoid',
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
BTC.onData(async (data) => {
|
|
34
|
+
const rsKeys = Object.keys(data);
|
|
35
|
+
success('BTCEUR DATA');
|
|
36
|
+
if (rsKeys.length <= 2) return;
|
|
37
|
+
|
|
38
|
+
keys.forEach((k) => {
|
|
39
|
+
if (!rsKeys.includes(k)) {
|
|
40
|
+
err(`Missing '${k}' key in`, rsKeys);
|
|
41
|
+
throw new Error('Missing key');
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
quoteSession.delete();
|
|
46
|
+
await client.end();
|
|
47
|
+
cb();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
BTC.onError((...error) => {
|
|
51
|
+
err('BTCEUR ERROR:', error);
|
|
52
|
+
throw new Error('Missing key');
|
|
53
|
+
});
|
|
54
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
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.setMarket('BINANCE:BTCEUR', { // Set the market
|
|
14
|
+
timeframe: 'D',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
chart.onError((...error) => {
|
|
18
|
+
err('Chart error', error);
|
|
19
|
+
throw new Error('Chart error');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
chart.onSymbolLoaded(() => { // When the symbol is successfully loaded
|
|
23
|
+
success(`Market "${chart.infos.description}" loaded !`);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Wait 3 seconds and set the market to BINANCE:ETHEUR
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
log('Setting market to BINANCE:ETHEUR...');
|
|
29
|
+
chart.setMarket('BINANCE:ETHEUR', {
|
|
30
|
+
timeframe: 'D',
|
|
31
|
+
});
|
|
32
|
+
}, 2000);
|
|
33
|
+
|
|
34
|
+
// Wait 4 seconds and set the timeframe to 15 minutes
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
log('Setting timeframe to 15 minutes...');
|
|
37
|
+
chart.setSeries('15');
|
|
38
|
+
}, 3000);
|
|
39
|
+
|
|
40
|
+
// Wait 5 seconds and set the chart type to "Heikin Ashi"
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
log('Setting the chart type to "Heikin Ashi"...');
|
|
43
|
+
chart.setMarket('BINANCE:ETHEUR', {
|
|
44
|
+
timeframe: 'D',
|
|
45
|
+
type: 'HeikinAshi',
|
|
46
|
+
});
|
|
47
|
+
}, 4000);
|
|
48
|
+
|
|
49
|
+
// Wait 7 seconds and close the chart
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
log('Closing the chart...');
|
|
52
|
+
chart.delete();
|
|
53
|
+
}, 5000);
|
|
54
|
+
|
|
55
|
+
// Wait 8 seconds and close the client
|
|
56
|
+
setTimeout(async () => {
|
|
57
|
+
log('Closing the client...');
|
|
58
|
+
await client.end();
|
|
59
|
+
cb();
|
|
60
|
+
}, 6000);
|
|
61
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
TradingView.getIndicator('STD;Supertrend%Strategy').then((indicator) => {
|
|
22
|
+
indicator.setOption('commission_type', 'percent');
|
|
23
|
+
indicator.setOption('commission_value', 0);
|
|
24
|
+
indicator.setOption('initial_capital', 25000);
|
|
25
|
+
indicator.setOption('default_qty_value', 20);
|
|
26
|
+
indicator.setOption('default_qty_type', 'percent_of_equity');
|
|
27
|
+
indicator.setOption('currency', 'EUR');
|
|
28
|
+
indicator.setOption('pyramiding', 10);
|
|
29
|
+
|
|
30
|
+
const SuperTrend = new chart.Study(indicator);
|
|
31
|
+
|
|
32
|
+
SuperTrend.onError((...error) => {
|
|
33
|
+
err('SuperTrend error', error[0]);
|
|
34
|
+
throw new Error('SuperTrend error');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
let QTY = 10;
|
|
38
|
+
|
|
39
|
+
SuperTrend.onUpdate(async () => {
|
|
40
|
+
// MarketCipher B is a strategy so it sends a strategy report
|
|
41
|
+
const perfReport = SuperTrend.strategyReport.performance;
|
|
42
|
+
|
|
43
|
+
success('Performances:', {
|
|
44
|
+
total: {
|
|
45
|
+
trades: perfReport.all.totalTrades,
|
|
46
|
+
perf: `${Math.round(perfReport.all.netProfitPercent * 10000) / 100} %`,
|
|
47
|
+
},
|
|
48
|
+
buy: {
|
|
49
|
+
trades: perfReport.long.totalTrades,
|
|
50
|
+
perf: `${Math.round(perfReport.long.netProfitPercent * 10000) / 100} %`,
|
|
51
|
+
},
|
|
52
|
+
sell: {
|
|
53
|
+
trades: perfReport.short.totalTrades,
|
|
54
|
+
perf: `${Math.round(perfReport.short.netProfitPercent * 10000) / 100} %`,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (QTY >= 50) {
|
|
59
|
+
SuperTrend.remove();
|
|
60
|
+
chart.delete();
|
|
61
|
+
await client.end();
|
|
62
|
+
cb();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
QTY += 10;
|
|
67
|
+
log('TRY WITH', QTY, '%');
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
indicator.setOption('default_qty_value', QTY);
|
|
70
|
+
SuperTrend.setIndicator(indicator);
|
|
71
|
+
}, 1000);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
TradingView.getIndicator('PUB;uA35GeckoTA2EfgI63SD2WCSmca4njxp').then((indicator) => {
|
|
76
|
+
indicator.setOption('Show_WT_Hidden_Divergences', true);
|
|
77
|
+
indicator.setOption('Show_Stoch_Regular_Divergences', true);
|
|
78
|
+
indicator.setOption('Show_Stoch_Hidden_Divergences', true);
|
|
79
|
+
|
|
80
|
+
const CipherB = new chart.Study(indicator);
|
|
81
|
+
|
|
82
|
+
CipherB.onError((...error) => {
|
|
83
|
+
err('MarketCipher B error:', error[0]);
|
|
84
|
+
throw new Error('MarketCipher B error');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
CipherB.onUpdate(() => {
|
|
88
|
+
const last = CipherB.periods[0];
|
|
89
|
+
// MarketCipher B is not a strategy so it only sends plots values
|
|
90
|
+
success('MarketCipher B last values:', {
|
|
91
|
+
VWAP: Math.round(last.VWAP * 1000) / 1000,
|
|
92
|
+
moneyFlow: (last.RSIMFIArea >= 0) ? 'POSITIVE' : 'NEGATIVE',
|
|
93
|
+
buyCircle: last.Buy_and_sell_circle && last.VWAP > 0,
|
|
94
|
+
sellCircle: last.Buy_and_sell_circle && last.VWAP < 0,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
CipherB.remove();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
const volumeProfile = new TradingView.BuiltInIndicator('VbPFixed@tv-basicstudies-139!');
|
|
22
|
+
|
|
23
|
+
volumeProfile.setOption('first_bar_time', Date.now() - 10 ** 8);
|
|
24
|
+
|
|
25
|
+
const VOL = new chart.Study(volumeProfile);
|
|
26
|
+
VOL.onUpdate(async () => {
|
|
27
|
+
VOL.graphic.horizHists
|
|
28
|
+
.filter((h) => h.lastBarTime === 0) // We only keep recent volume infos
|
|
29
|
+
.sort((a, b) => b.priceHigh - a.priceHigh)
|
|
30
|
+
.forEach((h) => {
|
|
31
|
+
success(
|
|
32
|
+
`~ ${Math.round((h.priceHigh + h.priceLow) / 2)} € :`,
|
|
33
|
+
`${'_'.repeat(h.rate[0] / 3)}${'_'.repeat(h.rate[1] / 3)}`,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
chart.delete();
|
|
38
|
+
await client.end();
|
|
39
|
+
cb();
|
|
40
|
+
});
|
|
41
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
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: 'D',
|
|
14
|
+
range: -1,
|
|
15
|
+
to: Math.round(Date.now() / 1000) - 86400 * 7,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
chart.onError((...error) => {
|
|
19
|
+
err('Chart error', error);
|
|
20
|
+
throw new Error('Chart error');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let interval = NaN;
|
|
24
|
+
let consec = 1;
|
|
25
|
+
let lastTime = 0;
|
|
26
|
+
|
|
27
|
+
chart.onUpdate(async () => {
|
|
28
|
+
const times = chart.periods.map((p) => p.time);
|
|
29
|
+
|
|
30
|
+
if (lastTime === times[0]) {
|
|
31
|
+
consec += 1;
|
|
32
|
+
warn(`Same lastTime ${lastTime}, ${consec} times in a row`);
|
|
33
|
+
} else consec = 1;
|
|
34
|
+
[lastTime] = times;
|
|
35
|
+
|
|
36
|
+
if (consec >= 10) {
|
|
37
|
+
chart.delete();
|
|
38
|
+
await client.end();
|
|
39
|
+
cb();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const intrval = times[0] - times[1];
|
|
43
|
+
if (Number.isNaN(interval) && times.length >= 2) interval = intrval;
|
|
44
|
+
|
|
45
|
+
if (!Number.isNaN(interval) && interval !== intrval) {
|
|
46
|
+
throw new Error(`Wrong interval: ${intrval} (should be ${interval})`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
log('Next ->', times[0]);
|
|
50
|
+
|
|
51
|
+
if ((times[0] + 86400) * 1000 > Date.now()) {
|
|
52
|
+
chart.delete();
|
|
53
|
+
await client.end();
|
|
54
|
+
cb();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
chart.fetchMore(-1);
|
|
58
|
+
});
|
|
59
|
+
};
|