@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
package/test.js
CHANGED
|
@@ -1,155 +1,64 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
/* eslint-disable import/no-dynamic-require */
|
|
3
|
+
/* eslint-disable no-restricted-syntax */
|
|
4
|
+
/* eslint-disable global-require */
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
1
7
|
require('@mathieuc/console')(
|
|
2
8
|
'§', // Character you want to use (defaut: '§')
|
|
3
9
|
true, // Active timestamp (defaut: false)
|
|
4
10
|
);
|
|
5
11
|
|
|
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
|
-
chart.onUpdate(() => {
|
|
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...
|
|
12
|
+
const TESTS = {};
|
|
13
|
+
|
|
14
|
+
function err(name) {
|
|
15
|
+
return (...msg) => {
|
|
16
|
+
TESTS[name].errors += 1;
|
|
17
|
+
console.error('§30§101 > §0', ...msg);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function warn(name) {
|
|
22
|
+
return (...msg) => {
|
|
23
|
+
TESTS[name].warnings += 1;
|
|
24
|
+
console.warn('§30§103 > §0', ...msg);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function log() {
|
|
29
|
+
return (...msg) => console.log('§30§107 > §0', ...msg);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function success() {
|
|
33
|
+
return (...msg) => console.info('§30§102 > §0', ...msg);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
(async () => {
|
|
37
|
+
console.info('§90§30§104 ==== Starting tests ==== §0');
|
|
38
|
+
|
|
39
|
+
for (const file of fs.readdirSync('./tests').filter((f) => f.endsWith('.js'))) {
|
|
40
|
+
const test = require(`./tests/${file}`);
|
|
41
|
+
const name = file.replace(/\.js/g, '');
|
|
42
|
+
TESTS[name] = { errors: 0, warnings: 0 };
|
|
43
|
+
console.log(`§90§30§107 ${name}`);
|
|
44
|
+
await new Promise((cb) => test(log(), success(), warn(name), err(name), cb));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.info('§90§30§104 ==== ALL TESTS DONE ==== §0\n');
|
|
48
|
+
Object.keys(TESTS).forEach((t) => {
|
|
49
|
+
let color = '2';
|
|
50
|
+
if (TESTS[t].warnings) color = '3';
|
|
51
|
+
if (TESTS[t].errors) color = '1';
|
|
52
|
+
|
|
53
|
+
console.info(`§90§30§10${color} ${t} §0 §91E§0: ${TESTS[t].errors}§0 §93W§0: ${TESTS[t].warnings}`);
|
|
54
|
+
// console.info(` - §91 Errors:§0 ${TESTS[t].errors}`);
|
|
55
|
+
// console.info(` - §93 Warnings:§0 ${TESTS[t].warnings}`);
|
|
144
56
|
});
|
|
145
|
-
});
|
|
146
57
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// chart.setSeries('240');
|
|
150
|
-
// }, 5000);
|
|
58
|
+
process.exit(0);
|
|
59
|
+
})();
|
|
151
60
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
console.log('§30§101 TIMEOUT §0');
|
|
63
|
+
throw new Error('Timeout');
|
|
64
|
+
}, 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,99 @@
|
|
|
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
|
+
indicator.setOption('default_qty_value', QTY);
|
|
69
|
+
|
|
70
|
+
SuperTrend.setIndicator(indicator);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
TradingView.getIndicator('PUB;uA35GeckoTA2EfgI63SD2WCSmca4njxp').then((indicator) => {
|
|
75
|
+
indicator.setOption('Show_WT_Hidden_Divergences', true);
|
|
76
|
+
indicator.setOption('Show_Stoch_Regular_Divergences', true);
|
|
77
|
+
indicator.setOption('Show_Stoch_Hidden_Divergences', true);
|
|
78
|
+
|
|
79
|
+
const CipherB = new chart.Study(indicator);
|
|
80
|
+
|
|
81
|
+
CipherB.onError((...error) => {
|
|
82
|
+
err('MarketCipher B error:', error[0]);
|
|
83
|
+
throw new Error('MarketCipher B error');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
CipherB.onUpdate(() => {
|
|
87
|
+
const last = CipherB.periods[0];
|
|
88
|
+
// MarketCipher B is not a strategy so it only sends plots values
|
|
89
|
+
success('MarketCipher B last values:', {
|
|
90
|
+
VWAP: Math.round(last.VWAP * 1000) / 1000,
|
|
91
|
+
moneyFlow: (last.RSIMFIArea >= 0) ? 'POSITIVE' : 'NEGATIVE',
|
|
92
|
+
buyCircle: last.Buy_and_sell_circle && last.VWAP > 0,
|
|
93
|
+
sellCircle: last.Buy_and_sell_circle && last.VWAP < 0,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
CipherB.remove();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
replay: Math.round(Date.now() / 1000) - 86400 * 10,
|
|
15
|
+
range: 1,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
chart.onError((...error) => {
|
|
19
|
+
err('Chart error', error);
|
|
20
|
+
throw new Error('Chart error');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let finished = false;
|
|
24
|
+
async function step() {
|
|
25
|
+
log('Next');
|
|
26
|
+
await chart.replayStep(1);
|
|
27
|
+
if (!finished) step();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
chart.onReplayLoaded(async () => {
|
|
31
|
+
log('START REPLAY MODE');
|
|
32
|
+
await chart.replayStart(200);
|
|
33
|
+
|
|
34
|
+
setTimeout(async () => {
|
|
35
|
+
await chart.replayStop();
|
|
36
|
+
log('STOP REPLAY MODE');
|
|
37
|
+
step();
|
|
38
|
+
}, 1000);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
chart.onReplayPoint((p) => {
|
|
42
|
+
success('Point ->', p);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
chart.onReplayEnd(async () => {
|
|
46
|
+
finished = true;
|
|
47
|
+
chart.delete();
|
|
48
|
+
await client.end();
|
|
49
|
+
cb();
|
|
50
|
+
});
|
|
51
|
+
};
|