maher-tradingview-api
Version:
Tradingview instant stocks API, indicator alerts, trading bot, and more !
260 lines (222 loc) • 8.86 kB
JavaScript
// Advanced Technical Indicators Implementation
class AdvancedTechnicalIndicators {
constructor() {
this.indicators = new Map();
}
// Calculate Exponential Moving Average (EMA)
calculateEMA(data, period) {
const k = 2 / (period + 1);
let ema = data[0];
const result = [ema];
for (let i = 1; i < data.length; i++) {
ema = data[i] * k + ema * (1 - k);
result.push(ema);
}
return result;
}
// Calculate Relative Strength Index (RSI)
calculateRSI(data, period = 14) {
const changes = [];
for (let i = 1; i < data.length; i++) {
changes.push(data[i] - data[i - 1]);
}
let gains = changes.map(change => change > 0 ? change : 0);
let losses = changes.map(change => change < 0 ? -change : 0);
const avgGain = gains.slice(0, period).reduce((sum, val) => sum + val, 0) / period;
const avgLoss = losses.slice(0, period).reduce((sum, val) => sum + val, 0) / period;
gains = gains.slice(period);
losses = losses.slice(period);
const rsi = [100 - (100 / (1 + avgGain / avgLoss))];
let lastAvgGain = avgGain;
let lastAvgLoss = avgLoss;
for (let i = 0; i < gains.length; i++) {
const gain = gains[i];
const loss = losses[i];
lastAvgGain = (lastAvgGain * (period - 1) + gain) / period;
lastAvgLoss = (lastAvgLoss * (period - 1) + loss) / period;
const rs = lastAvgGain / lastAvgLoss;
rsi.push(100 - (100 / (1 + rs)));
}
return rsi;
}
// Calculate MACD
calculateMACD(data, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) {
const fastEMA = this.calculateEMA(data, fastPeriod);
const slowEMA = this.calculateEMA(data, slowPeriod);
const macdLine = fastEMA.map((fast, i) => fast - slowEMA[i]);
const signalLine = this.calculateEMA(macdLine, signalPeriod);
const histogram = macdLine.map((macd, i) => macd - signalLine[i]);
return {
macdLine,
signalLine,
histogram
};
}
// Calculate Bollinger Bands
calculateBollingerBands(data, period = 20, standardDeviations = 2) {
const sma = [];
const upperBand = [];
const lowerBand = [];
for (let i = period - 1; i < data.length; i++) {
const slice = data.slice(i - period + 1, i + 1);
const avg = slice.reduce((sum, val) => sum + val, 0) / period;
const stdDev = Math.sqrt(
slice.reduce((sum, val) => sum + Math.pow(val - avg, 2), 0) / period
);
sma.push(avg);
upperBand.push(avg + standardDeviations * stdDev);
lowerBand.push(avg - standardDeviations * stdDev);
}
return {
middle: sma,
upper: upperBand,
lower: lowerBand
};
}
// Calculate Ichimoku Cloud
calculateIchimoku(high, low, conversionPeriod = 9, basePeriod = 26, spanPeriod = 52, displacement = 26) {
const conversion = [];
const base = [];
const spanA = [];
const spanB = [];
// Calculate Conversion Line (Tenkan-sen)
for (let i = conversionPeriod - 1; i < high.length; i++) {
const highSlice = high.slice(i - conversionPeriod + 1, i + 1);
const lowSlice = low.slice(i - conversionPeriod + 1, i + 1);
conversion.push((Math.max(...highSlice) + Math.min(...lowSlice)) / 2);
}
// Calculate Base Line (Kijun-sen)
for (let i = basePeriod - 1; i < high.length; i++) {
const highSlice = high.slice(i - basePeriod + 1, i + 1);
const lowSlice = low.slice(i - basePeriod + 1, i + 1);
base.push((Math.max(...highSlice) + Math.min(...lowSlice)) / 2);
}
// Calculate Leading Span A (Senkou Span A)
for (let i = 0; i < conversion.length && i < base.length; i++) {
spanA.push((conversion[i] + base[i]) / 2);
}
// Calculate Leading Span B (Senkou Span B)
for (let i = spanPeriod - 1; i < high.length; i++) {
const highSlice = high.slice(i - spanPeriod + 1, i + 1);
const lowSlice = low.slice(i - spanPeriod + 1, i + 1);
spanB.push((Math.max(...highSlice) + Math.min(...lowSlice)) / 2);
}
return {
conversion,
base,
spanA: [...Array(displacement).fill(null), ...spanA],
spanB: [...Array(displacement).fill(null), ...spanB]
};
}
// Calculate Volume Profile
calculateVolumeProfile(prices, volumes, levels = 12) {
const minPrice = Math.min(...prices);
const maxPrice = Math.max(...prices);
const priceRange = maxPrice - minPrice;
const levelHeight = priceRange / levels;
const profile = Array(levels).fill(0);
const levelPrices = Array(levels).fill(0).map((_, i) => minPrice + levelHeight * i);
prices.forEach((price, i) => {
const levelIndex = Math.floor((price - minPrice) / levelHeight);
if (levelIndex >= 0 && levelIndex < levels) {
profile[levelIndex] += volumes[i];
}
});
return {
profile,
levelPrices
};
}
// Render Advanced Indicators
renderAdvancedIndicator(canvasId, type, data, options = {}) {
const existingIndicator = this.indicators.get(canvasId);
if (existingIndicator) {
existingIndicator.destroy();
}
const ctx = document.getElementById(canvasId)?.getContext('2d');
if (!ctx) return;
let chartConfig;
switch (type) {
case 'ichimoku':
chartConfig = this.createIchimokuConfig(data, options);
break;
case 'volumeProfile':
chartConfig = this.createVolumeProfileConfig(data, options);
break;
default:
console.warn(`Unknown indicator type: ${type}`);
return;
}
const chart = new Chart(ctx, chartConfig);
this.indicators.set(canvasId, chart);
return chart;
}
// Create Ichimoku Cloud Configuration
createIchimokuConfig(data, options) {
return {
type: 'line',
data: {
labels: data.labels,
datasets: [
{
label: 'Conversion Line',
data: data.conversion,
borderColor: '#2196F3',
fill: false,
pointRadius: 0
},
{
label: 'Base Line',
data: data.base,
borderColor: '#FF5722',
fill: false,
pointRadius: 0
},
{
label: 'Leading Span A',
data: data.spanA,
borderColor: '#4CAF50',
fill: false,
pointRadius: 0
},
{
label: 'Leading Span B',
data: data.spanB,
borderColor: '#FFC107',
fill: false,
pointRadius: 0
}
]
},
options: {
...options,
responsive: true,
maintainAspectRatio: false
}
};
}
// Create Volume Profile Configuration
createVolumeProfileConfig(data, options) {
return {
type: 'bar',
data: {
labels: data.levelPrices.map(price => price.toFixed(2)),
datasets: [{
label: 'Volume Profile',
data: data.profile,
backgroundColor: 'rgba(0, 136, 204, 0.5)',
borderColor: 'rgba(0, 136, 204, 1)',
borderWidth: 1
}]
},
options: {
...options,
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y'
}
};
}
}
// Export the advanced indicators
window.AdvancedTechnicalIndicators = new AdvancedTechnicalIndicators();