// static/js/backtesting.js document.addEventListener('DOMContentLoaded', () => { const strategySelect = document.getElementById('strategy-select'); const paramsContainer = document.getElementById('params-container'); const form = document.getElementById('backtest-form'); const runBtn = document.getElementById('run-backtest-btn'); const resultsContainer = document.getElementById('results-container'); const resultsSummary = document.getElementById('results-summary'); const loadingSpinner = document.getElementById('loading-spinner'); let equityChart = null; // Variabel untuk menyimpan instance grafik const resultsLog = document.getElementById('results-log'); // Muat strategi ke dropdown async function loadStrategies() { try { const response = await fetch('/api/strategies'); if (!response.ok) throw new Error('Gagal memuat strategi.'); const strategies = await response.json(); strategySelect.innerHTML = ''; strategies.forEach(strategy => { const option = document.createElement('option'); option.value = strategy.id; option.textContent = strategy.name; strategySelect.appendChild(option); }); } catch (error) { console.error('Error loading strategies:', error); strategySelect.innerHTML = ''; } } // Muat parameter saat strategi dipilih strategySelect.addEventListener('change', async () => { const strategyId = strategySelect.value; paramsContainer.innerHTML = '
Memuat parameter...
'; if (!strategyId) { paramsContainer.innerHTML = ''; return; } try { const res = await fetch(`/api/strategies/${strategyId}/params`); const params = await res.json(); paramsContainer.innerHTML = ''; // Kosongkan lagi if (params.length > 0) { params.forEach(param => { paramsContainer.innerHTML += `Strategi ini tidak memiliki parameter kustom.
'; } } catch (err) { console.error('Gagal memuat parameter strategi:', err); paramsContainer.innerHTML = 'Gagal memuat parameter.
'; } }); // Jalankan backtest saat form disubmit form.addEventListener('submit', async (e) => { e.preventDefault(); loadingSpinner.classList.remove('hidden'); resultsContainer.classList.add('hidden'); runBtn.disabled = true; runBtn.textContent = 'Menjalankan...'; const formData = new FormData(form); // Kumpulkan parameter kustom const params = {}; // Ambil parameter dari form utama (SL/TP) params['sl_pips'] = parseFloat(document.getElementById('sl_atr_multiplier').value); params['tp_pips'] = parseFloat(document.getElementById('tp_atr_multiplier').value); // Kumpulkan parameter strategi kustom paramsContainer.querySelectorAll('input').forEach(input => { const value = parseFloat(input.value); // Pastikan hanya angka valid yang di-parse, selain itu ambil string params[input.name] = isNaN(value) ? input.value : value; }); formData.append('params', JSON.stringify(params)); try { const response = await fetch('/api/backtest/run', { method: 'POST', body: formData, // Kirim sebagai multipart/form-data }); const results = await response.json(); if (response.ok) { displayResults(results); } else { alert(`Error: ${results.error}`); } } catch (err) { console.error("Backtest failed:", err); alert('Gagal terhubung ke server.'); } finally { loadingSpinner.classList.add('hidden'); runBtn.disabled = false; runBtn.textContent = 'Jalankan Backtest'; } }); function displayResults(data) { resultsContainer.classList.remove('hidden'); // PERBAIKAN: Tampilkan 6 metrik utama resultsSummary.innerHTML = `Total Profit
${data.total_profit_usd.toFixed(2)} $
Max Drawdown
${data.max_drawdown_percent.toFixed(2)}%
Win Rate
${data.win_rate_percent.toFixed(2)}%
Total Trades
${data.total_trades}
Wins
${data.wins}
Losses
${data.losses}
Entry: ${trade.entry.toFixed(4)} | Exit: ${trade.exit.toFixed(4)} | Profit: ${trade.profit.toFixed(2)} | Reason: ${trade.reason}
`; }); logHtml += '