mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-28 11:17:44 +00:00
348acc6f43
This major commit introduces a new advanced trading strategy, resolves critical trading logic errors, and significantly enhances system stability and UI data accuracy.
Key Changes:
- **New Features & Strategies**:
- **Quantum Velocity Strategy**: Added 'quantum_velocity.py', a new hybrid strategy combining a long-term trend filter (EMA 200) with a volatility-based entry trigger (Bollinger Squeeze).
- **Hybrid Pro Backtester**: Added 'lab/backtester_hybrid_pro.py' to facilitate advanced, offline testing and optimization of the QuantumBotX Hybrid strategy.
- **Critical Trading Logic Fixes**:
- Resolved 'Invalid Stops' and 'Unsupported filling mode' errors by refactoring 'core/mt5/trade.py' to use dynamic point calculation and the FOK fill policy.
- Fixed a recurring 'KeyError' in 'BollingerSqueezeStrategy' by ensuring consistent naming for Bollinger Bands columns.
- **System Stability & Robustness**:
- Hardened the graceful shutdown handler in 'app.py' to prevent crashes from repeated Ctrl+C signals, ensuring a clean shutdown process.
- Enhanced the notification system by adding an 'is_notification' flag to logs, allowing for a clear distinction between critical alerts and general activity.
- **Dashboard & UI Enhancements**:
- Fixed the 'Total Bots' card on the dashboard by correcting the backend API ('api_dashboard.py') to send the complete stats payload.
- Replaced static '0' values on dashboard cards with loading spinners for a more professional user experience.
- The 'Create/Edit Bot' modal button now dynamically changes its text to 'Ubah Bot' when in edit mode.
63 lines
2.9 KiB
JavaScript
63 lines
2.9 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function() {
|
|
const container = document.getElementById('notifications-container');
|
|
|
|
const formatTimestamp = (isoString) => {
|
|
const date = new Date(isoString);
|
|
return date.toLocaleString('id-ID', {
|
|
day: '2-digit', month: 'short', year: 'numeric',
|
|
hour: '2-digit', minute: '2-digit'
|
|
});
|
|
};
|
|
|
|
const getNotificationAppearance = (action) => {
|
|
const lowerAction = action.toLowerCase();
|
|
if (lowerAction.includes('buy')) return { icon: 'fa-arrow-up', color: 'green' };
|
|
if (lowerAction.includes('sell')) return { icon: 'fa-arrow-down', color: 'red' };
|
|
if (lowerAction.includes('start')) return { icon: 'fa-play-circle', color: 'blue' };
|
|
if (lowerAction.includes('stop')) return { icon: 'fa-pause-circle', color: 'yellow' };
|
|
if (lowerAction.includes('error')) return { icon: 'fa-exclamation-triangle', color: 'red' };
|
|
return { icon: 'fa-info-circle', color: 'gray' };
|
|
};
|
|
|
|
async function fetchNotifications() {
|
|
try {
|
|
const response = await fetch('/api/notifications');
|
|
if (!response.ok) throw new Error('Gagal memuat notifikasi');
|
|
const notifications = await response.json();
|
|
|
|
if (notifications.length === 0) {
|
|
container.innerHTML = '<p class="p-6 text-center text-gray-500">Tidak ada notifikasi.</p>';
|
|
return;
|
|
}
|
|
|
|
const notificationsHtml = notifications.map(notif => {
|
|
const appearance = getNotificationAppearance(notif.action);
|
|
const message = `<strong>[${notif.bot_name}]</strong> ${notif.details}`;
|
|
return `
|
|
<div class="p-4 flex items-start hover:bg-gray-50 cursor-pointer">
|
|
<div class="w-10 h-10 rounded-full bg-${appearance.color}-100 flex items-center justify-center text-${appearance.color}-600 mr-4 flex-shrink-0"><i class="fas ${appearance.icon}"></i></div>
|
|
<div>
|
|
<p class="text-sm text-gray-800">${message}</p>
|
|
<p class="text-xs text-gray-500 mt-1">${formatTimestamp(notif.timestamp)}</p>
|
|
</div>
|
|
</div>`;
|
|
}).join('');
|
|
|
|
container.innerHTML = notificationsHtml;
|
|
|
|
} catch (error) {
|
|
console.error("Error fetching notifications:", error);
|
|
container.innerHTML = `<p class="p-6 text-center text-red-500">Gagal memuat notifikasi: ${error.message}</p>`;
|
|
}
|
|
}
|
|
|
|
fetchNotifications();
|
|
|
|
// Setelah memuat notifikasi, tandai semua sebagai sudah dibaca
|
|
fetch('/api/notifications/mark-as-read', {
|
|
method: 'POST'
|
|
}).then(response => response.json())
|
|
.then(data => console.log(data.message))
|
|
.catch(error => console.error('Gagal menandai notifikasi:', error));
|
|
|
|
}); |