// Qoutex Trading Bot Simulator - Frontend Logic class TradingBot { constructor() { this.balance = 10000; this.equity = 10000; this.positions = []; this.trades = []; this.wins = 0; this.losses = 0; this.isRunning = false; this.interval = null; this.currentPrice = 1.1000; this.chartData = []; this.chartLabels = []; this.initChart(); this.loadEventListeners(); this.startPriceSimulation(); } initChart() { const ctx = document.getElementById('priceChart').getContext('2d'); this.chart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [{ label: 'Price', data: [], borderColor: 'rgb(102, 126, 234)', backgroundColor: 'rgba(102, 126, 234, 0.1)', tension: 0.1, fill: true }] }, options: { responsive: true, maintainAspectRatio: true, plugins: { legend: { display: true, position: 'top' } }, scales: { y: { ticks: { callback: function(value) { return '$' + value.toFixed(4); } } } } } }); } loadEventListeners() { document.getElementById('startBot').addEventListener('click', () => this.startBot()); document.getElementById('stopBot').addEventListener('click', () => this.stopBot()); document.getElementById('pair').addEventListener('change', (e) => this.changePair(e.target.value)); } startPriceSimulation() { setInterval(() => { if (!this.isRunning) return; // Simulate price movement with random walk + trend const change = (Math.random() - 0.5) * 0.002; this.currentPrice += change; // Update chart this.chartLabels.push(new Date().toLocaleTimeString()); this.chartData.push(this.currentPrice); if (this.chartData.length > 50) { this.chartData.shift(); this.chartLabels.shift(); } this.chart.data.labels = this.chartLabels; this.chart.data.datasets[0].data = this.chartData; this.chart.update(); // Update equity display this.updateEquity(); // Execute trading signals this.executeStrategy(); }, 1000); } executeStrategy() { const strategy = document.getElementById('strategy').value; let signal = null; switch(strategy) { case 'rsi': signal = this.rsiStrategy(); break; case 'macd': signal = this.macdStrategy(); break; case 'bollinger': signal = this.bollingerStrategy(); break; } if (signal && this.positions.length === 0) { this.openPosition(signal); } // Check for take profit / stop loss this.checkPositionExit(); } rsiStrategy() { // Simplified RSI calculation using price changes const period = 14; if (this.chartData.length < period) return null; let gains = 0; let losses = 0; for (let i = this.chartData.length - period; i < this.chartData.length - 1; i++) { const change = this.chartData[i + 1] - this.chartData[i]; if (change > 0) gains += change; else losses -= change; } const avgGain = gains / period; const avgLoss = losses / period; const rs = avgGain / avgLoss; const rsi = 100 - (100 / (1 + rs)); // RSI signals if (rsi < 30) return 'BUY'; if (rsi > 70) return 'SELL'; return null; } macdStrategy() { // Simplified MACD strategy if (this.chartData.length < 26) return null; const ema12 = this.calculateEMA(12); const ema26 = this.calculateEMA(26); const macd = ema12 - ema26; const signal = this.calculateSignal(macd); if (macd > signal && this.previousMACD <= this.previousSignal) return 'BUY'; if (macd < signal && this.previousMACD >= this.previousSignal) return 'SELL'; this.previousMACD = macd; this.previousSignal = signal; return null; } bollingerStrategy() { if (this.chartData.length < 20) return null; const sma = this.calculateSMA(20); const stdDev = this.calculateStdDev(20); const upperBand = sma + (stdDev * 2); const lowerBand = sma - (stdDev * 2); const currentPrice = this.currentPrice; if (currentPrice < lowerBand) return 'BUY'; if (currentPrice > upperBand) return 'SELL'; return null; } calculateEMA(period) { const multiplier = 2 / (period + 1); let ema = this.chartData[this.chartData.length - period]; for (let i = this.chartData.length - period + 1; i < this.chartData.length; i++) { ema = (this.chartData[i] - ema) * multiplier + ema; } return ema; } calculateSMA(period) { const slice = this.chartData.slice(-period); return slice.reduce((a, b) => a + b, 0) / period; } calculateStdDev(period) { const sma = this.calculateSMA(period); const slice = this.chartData.slice(-period); const variance = slice.reduce((acc, price) => acc + Math.pow(price - sma, 2), 0) / period; return Math.sqrt(variance); } calculateSignal(macd) { // Simplified signal line (9-period EMA of MACD) return macd * 0.9; } openPosition(signal) { const lotSize = parseFloat(document.getElementById('lotSize').value); const stopLoss = parseFloat(document.getElementById('stopLoss').value); const takeProfit = parseFloat(document.getElementById('takeProfit').value); const position = { id: Date.now(), type: signal, entryPrice: this.currentPrice, lotSize: lotSize, stopLoss: stopLoss, takeProfit: takeProfit, openTime: new Date() }; this.positions.push(position); this.addTradeLog(`OPEN ${signal}: ${lotSize} lots at ${this.currentPrice.toFixed(4)}`); } checkPositionExit() { for (let i = 0; i < this.positions.length; i++) { const pos = this.positions[i]; let exitPrice = null; let reason = ''; if (pos.type === 'BUY') { const profitTarget = pos.entryPrice + (pos.takeProfit * 0.0001); const stopLossPrice = pos.entryPrice - (pos.stopLoss * 0.0001); if (this.currentPrice >= profitTarget) { exitPrice = profitTarget; reason = 'Take Profit'; this.wins++; } else if (this.currentPrice <= stopLossPrice) { exitPrice = stopLossPrice; reason = 'Stop Loss'; this.losses++; } } else if (pos.type === 'SELL') { const profitTarget = pos.entryPrice - (pos.takeProfit * 0.0001); const stopLossPrice = pos.entryPrice + (pos.stopLoss * 0.0001); if (this.currentPrice <= profitTarget) { exitPrice = profitTarget; reason = 'Take Profit'; this.wins++; } else if (this.currentPrice >= stopLossPrice) { exitPrice = stopLossPrice; reason = 'Stop Loss'; this.losses++; } } if (exitPrice) { const profit = this.calculateProfit(pos, exitPrice); this.balance += profit; this.trades.push({ ...pos, exitPrice, profit, reason }); this.positions.splice(i, 1); this.addTradeLog(`CLOSE ${pos.type}: ${reason} - Profit: $${profit.toFixed(2)}`); i--; } } this.updateStats(); } calculateProfit(position, exitPrice) { const pipDifference = Math.abs(exitPrice - position.entryPrice) / 0.0001; const profit = pipDifference * position.lotSize * 10; return position.type === 'BUY' ? profit : -profit; } updateEquity() { let floatingPL = 0; for (const pos of this.positions) { if (pos.type === 'BUY') { floatingPL += (this.currentPrice - pos.entryPrice) / 0.0001 * pos.lotSize * 10; } else { floatingPL += (pos.entryPrice - this.currentPrice) / 0.0001 * pos.lotSize * 10; } } this.equity = this.balance + floatingPL; document.getElementById('equity').textContent = `$${this.equity.toFixed(2)}`; } updateStats() { document.getElementById('balance').textContent = `$${this.balance.toFixed(2)}`; const totalPnL = this.balance - 10000; document.getElementById('pnl').textContent = `${totalPnL >= 0 ? '+' : ''}$${totalPnL.toFixed(2)}`; document.getElementById('pnl').className = totalPnL >= 0 ? 'stat-value profit' : 'stat-value loss'; const totalTrades = this.wins + this.losses; const winRate = totalTrades > 0 ? (this.wins / totalTrades * 100).toFixed(1) : 0; document.getElementById('winRate').textContent = `${winRate}%`; document.getElementById('totalTrades').textContent = totalTrades; } addTradeLog(message) { const logDiv = document.getElementById('tradeLog'); const entry = document.createElement('div'); entry.className = `trade-entry trade-${message.includes('BUY') ? 'buy' : 'sell'}`; entry.innerHTML = `[${new Date().toLocaleTimeString()}] ${message}`; logDiv.insertBefore(entry, logDiv.firstChild); if (logDiv.children.length > 50) { logDiv.removeChild(logDiv.lastChild); } } changePair(pair) { this.addTradeLog(`Changed trading pair to ${pair}`); // Reset price based on pair switch(pair) { case 'EURUSD': this.currentPrice = 1.1000; break; case 'GBPUSD': this.currentPrice = 1.3000; break; case 'BTCUSD': this.currentPrice = 50000; break; } } startBot() { if (!this.isRunning) { this.isRunning = true; document.getElementById('botStatus').className = 'status status-active'; document.getElementById('botStatusText').textContent = 'Running'; this.addTradeLog('🤖 Bot started'); } } stopBot() { if (this.isRunning) { this.isRunning = false; document.getElementById('botStatus').className = 'status status-inactive'; document.getElementById('botStatusText').textContent = 'Stopped'; this.addTradeLog('🛑 Bot stopped'); } } } // Initialize the bot const tradingBot = new TradingBot();