UNPKG

@blackphoenixslo/trading-bot-framework

Version:

A comprehensive framework for building trading bots with support for TradingView, various market data providers, MongoDB, Google Sheets, and Discord alerts.

134 lines (112 loc) 4.63 kB
const cryptoDataAPI = require("./main-bot--cryptoDataAPI"); const priceSeries = require("./main-bot--priceSeries"); const time = require("./main-bot--time"); const correlations = {}; // Returns the correlation coefficient between 2 number arrays // Source: https://gist.github.com/matt-west/6500993?permalink_comment_id=3718526#gistcomment-3718526 correlations.pearsonCorrelationCoefficient = (x, y) => { const promedio = l => l.reduce((s, a) => s + a, 0) / l.length const calc = (v, prom) => Math.sqrt(v.reduce((s, a) => (s + a * a), 0) - n * prom * prom) let n = x.length let nn = 0 for (let i = 0; i < n; i++, nn++) { if ((!x[i] && x[i] !== 0) || (!y[i] && y[i] !== 0)) { nn-- continue } x[nn] = x[i] y[nn] = y[i] } if (n !== nn) { x = x.splice(0, nn) y = y.splice(0, nn) n = nn } const prom_x = promedio(x), prom_y = promedio(y) return (x .map((e, i) => ({ x: e, y: y[i] })) .reduce((v, a) => v + a.x * a.y, 0) - n * prom_x * prom_y ) / (calc(x, prom_x) * calc(y, prom_y)) } correlations.getAverageCorrelationBetweenCoins = async (coin1, coin2, dayPeriods) => { let getHourlyCandlesticks = false; let getDailyCandlesticks = false; dayPeriods.forEach((period) => { if (period > 30) { getDailyCandlesticks = true; } else { getHourlyCandlesticks = true; } }) //console.log("Get daily candlesticks", getDailyCandlesticks); //console.log("Get hourly candlesticks", getHourlyCandlesticks); let hourlyCandlesticks1 = null; let hourlyCandlesticks2 = null; if (getHourlyCandlesticks) { //console.log(getDailyCandlesticks == false ? Math.max(...dayPeriods) : 30); const startTime = time.getTimeDaysAgo(getDailyCandlesticks == false ? Math.max(...dayPeriods) : 30); hourlyCandlesticks1 = await cryptoDataAPI.getCandlesticks({ symbol: `${coin1}USDT`, interval: "1h", startTime: startTime, limit: 1000 }); hourlyCandlesticks2 = await cryptoDataAPI.getCandlesticks({ symbol: `${coin2}USDT`, interval: "1h", startTime: startTime, limit: 1000 }); } let dailyCandlesticks1 = null; let dailyCandlesticks2 = null; if (getDailyCandlesticks) { const startTime = time.getTimeDaysAgo(Math.max(...dayPeriods)); dailyCandlesticks1 = await cryptoDataAPI.getCandlesticks({ symbol: `${coin1}USDT`, interval: "1d", startTime: startTime, limit: 1000 }); dailyCandlesticks2 = await cryptoDataAPI.getCandlesticks({ symbol: `${coin2}USDT`, interval: "1d", startTime: startTime, limit: 1000 }); } var correlationSum = 0; dayPeriods.forEach((period) => { var periodCandlesticks1 = null; var periodCandlesticks2 = null; if (period > 30) { //console.log("Using daily candlesticks for", period) periodCandlesticks1 = dailyCandlesticks1; periodCandlesticks2 = dailyCandlesticks2; } else { //console.log("Using hourly candlesticks for", period) periodCandlesticks1 = hourlyCandlesticks1; periodCandlesticks2 = hourlyCandlesticks2; } if (period != Math.max(...dayPeriods)) { const timestamp = time.getTimeDaysAgo(period); var indexOfCandlestick = 0; for (var i = 0; i < periodCandlesticks1.length; i++) { if (periodCandlesticks1[i][0] >= (timestamp - (7200 * 1000))) { indexOfCandlestick = i; break; }; }; periodCandlesticks1 = periodCandlesticks1.slice(indexOfCandlestick); periodCandlesticks2 = periodCandlesticks2.splice(indexOfCandlestick); }; //console.log(`Number of candlesticks for ${period} days: ${periodCandlesticks1.length}`); const coin1Prices = priceSeries.getClosePrices(periodCandlesticks1); const coin2Prices = priceSeries.getClosePrices(periodCandlesticks2); const detrendedCoin1Prices = priceSeries.detrend(coin1Prices); const detrendedCoin2Prices = priceSeries.detrend(coin2Prices); correlationSum += correlations.pearsonCorrelationCoefficient(detrendedCoin1Prices, detrendedCoin2Prices); }); return correlationSum / dayPeriods.length; } module.exports = correlations;