mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-28 11:17:44 +00:00
a7b99ec1cf
🔧 Core System Improvements: - Enhanced backtesting engine with realistic spread modeling and ATR-based risk management - Improved bot controller with better error handling and status tracking - Optimized MT5 integration with symbol verification and market watch integration - Strengthened database queries with better performance and reliability 🎯 New Strategy Features: - Added index strategies (Index Momentum, Index Breakout Pro) for stock market trading - Implemented market condition detector for dynamic strategy adaptation - Created performance scorer for strategy evaluation and ranking - Added strategy switcher system for automatic strategy optimization 📚 Educational Framework: - New beginner guide documentation for newcomer onboarding - Enhanced FAQ section with common trading questions - Quick start guide for rapid setup and deployment - Improved AI mentor integration with personalized guidance 🌍 Multi-Asset Expansion: - Extended data collection for 20+ trading instruments (Forex, Crypto, Indices) - Enhanced broker compatibility with FBS and other platforms - Improved symbol migration system for seamless broker switching - Added holiday integration for culturally-aware trading automation 🧪 Testing & Validation: - Added comprehensive index strategy testing suite - Enhanced holiday integration validation - Dynamic strategy signal testing for improved reliability - EURUSD optimization testing with London session focus ⚡ Performance & UI: - Frontend JavaScript optimizations for better trading bot management - Enhanced templates with improved user experience - Database migration system for smooth version upgrades - Optimized data download scripts for better efficiency 📊 Analytics & Monitoring: - Strengthened Flask application architecture with better routing - Improved logging system for production deployment - Enhanced error handling across all components - Better API response handling and status reporting
115 lines
5.3 KiB
JavaScript
115 lines
5.3 KiB
JavaScript
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
fetchForexData();
|
|
// Refresh data setiap 10 detik untuk konsistensi dengan halaman Saham
|
|
setInterval(fetchForexData, 10000);
|
|
});
|
|
|
|
async function fetchForexData() {
|
|
const tableBody = document.getElementById('forex-table-body');
|
|
|
|
// Tampilkan pesan loading jika tabel masih kosong
|
|
if (!tableBody.querySelector('tr')) {
|
|
tableBody.innerHTML = '<tr><td colspan="5" class="p-4 text-center text-gray-500">Memuat data forex...</td></tr>';
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/api/forex-data');
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
const forexPairs = await response.json(); // API sekarang mengembalikan array
|
|
|
|
if (!forexPairs || forexPairs.length === 0) {
|
|
tableBody.innerHTML = '<tr><td colspan="5" class="p-4 text-center text-gray-500">Tidak ada data forex dari MT5.</td></tr>';
|
|
return;
|
|
}
|
|
|
|
const rowsHtml = forexPairs.map(pair => {
|
|
// Spread dihitung berdasarkan poin, bukan pips. Untuk konversi ke pips:
|
|
// Jika digits 5 (misal EURUSD 1.23456), 1 pip = 10 poin.
|
|
// Jika digits 3 (misal USDJPY 123.456), 1 pip = 10 poin.
|
|
// Jika digits 2 atau 4, 1 pip = 1 poin.
|
|
// Karena data spread sudah dalam poin, dan 1 pip umumnya 10 poin untuk 5/3 digit,
|
|
// atau 1 poin untuk 2/4 digit, kita bisa langsung bagi dengan 10 untuk konversi umum.
|
|
// Ini adalah penyederhanaan karena kita tidak memiliki akses ke mt5.symbol_info di frontend.
|
|
return `
|
|
<tr class="hover:bg-gray-50">
|
|
<td class="px-6 py-4 whitespace-nowrap"><div class="font-medium text-gray-900">${pair.name}</div></td>
|
|
<td class="px-6 py-4 whitespace-nowrap font-medium">${pair.bid.toFixed(pair.digits)}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap font-medium">${pair.ask.toFixed(pair.digits)}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${(pair.spread / 10).toFixed(1)} pips</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-right">
|
|
<button class="bg-blue-600 text-white py-1 px-3 rounded-md text-sm font-medium hover:bg-blue-700">Trade</button>
|
|
<button class="bg-gray-600 text-white py-1 px-3 rounded-md text-sm font-medium hover:bg-gray-700 details-btn" data-symbol="${pair.name}">Details</button>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}).join('');
|
|
|
|
tableBody.innerHTML = rowsHtml;
|
|
} catch (error) {
|
|
console.error('Error fetching forex data:', error);
|
|
if (tableBody) {
|
|
tableBody.innerHTML = '<tr><td colspan="5" class="p-4 text-center text-red-500">Gagal memuat data.</td></tr>';
|
|
}
|
|
}
|
|
}
|
|
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.classList.contains('details-btn')) {
|
|
const symbol = e.target.dataset.symbol;
|
|
fetchSymbolProfile(symbol);
|
|
}
|
|
|
|
// Add handler for Trade buttons
|
|
if (e.target.classList.contains('bg-blue-600') && e.target.textContent === 'Trade') {
|
|
const row = e.target.closest('tr');
|
|
const symbol = row.querySelector('.details-btn').dataset.symbol;
|
|
// Redirect to trading_bots.html with symbol parameter
|
|
window.location.href = `/trading-bots?symbol=${encodeURIComponent(symbol)}`;
|
|
}
|
|
});
|
|
|
|
document.getElementById('close-modal').addEventListener('click', function() {
|
|
document.getElementById('forex-modal').classList.add('hidden'); // Fixed: was referencing 'stock-modal'
|
|
});
|
|
|
|
async function fetchSymbolProfile(symbol) {
|
|
const modal = document.getElementById('forex-modal'); // Fixed: was referencing 'stock-modal'
|
|
const modalTitle = document.getElementById('modal-title');
|
|
const modalContent = document.getElementById('modal-content');
|
|
|
|
modalTitle.textContent = 'Loading...';
|
|
modalContent.textContent = '';
|
|
modal.classList.remove('hidden');
|
|
|
|
try {
|
|
const response = await fetch(`/api/forex/${symbol}/profile`);
|
|
if (!response.ok) {
|
|
const errData = await response.json();
|
|
throw new Error(errData.error || 'Failed to fetch symbol profile.');
|
|
}
|
|
const profile = await response.json();
|
|
|
|
modalTitle.textContent = profile.name;
|
|
modalContent.innerHTML = `
|
|
<div class="space-y-2 text-left">
|
|
<p><strong>Symbol:</strong> ${profile.symbol}</p>
|
|
<p><strong>Base Currency:</strong> ${profile.currency_base}</p>
|
|
<p><strong>Profit Currency:</strong> ${profile.currency_profit}</p>
|
|
<p><strong>Digits:</strong> ${profile.digits}</p>
|
|
<p><strong>Spread:</strong> ${profile.spread} points</p>
|
|
<p><strong>Contract Size:</strong> ${profile.trade_contract_size}</p>
|
|
<p><strong>Min Volume:</strong> ${profile.volume_min}</p>
|
|
<p><strong>Max Volume:</strong> ${profile.volume_max}</p>
|
|
<p><strong>Volume Step:</strong> ${profile.volume_step}</p>
|
|
</div>
|
|
`;
|
|
|
|
} catch (error) {
|
|
modalTitle.textContent = 'Error';
|
|
modalContent.textContent = error.message;
|
|
}
|
|
}
|