diff --git a/.env.example b/.env.example index 553904d..e5b4fd2 100644 --- a/.env.example +++ b/.env.example @@ -1,76 +1,34 @@ -# --- ENV FILE EXAMPLE FOR QuantumBotX --- - -# MetaTrader5 Credentials (Forex, Stocks, Commodities) -MT5_LOGIN=12345678 -MT5_PASSWORD=your_password_here -MT5_SERVER=MetaQuotes-Demo - -# Binance Crypto Exchange -# Get API keys from: https://testnet.binance.vision/ (testnet) or https://binance.com (mainnet) -BINANCE_API_KEY=your_binance_api_key_here -BINANCE_SECRET_KEY=your_binance_secret_key_here -BINANCE_TESTNET=true - -# cTrader Modern Forex Platform -# Get credentials from: https://ctrader.com/ -CTRADER_CLIENT_ID=your_ctrader_client_id -CTRADER_CLIENT_SECRET=your_ctrader_client_secret -CTRADER_ACCOUNT_ID=your_ctrader_account_id -CTRADER_DEMO=true - -# Interactive Brokers (Professional Trading) -# Download TWS or IB Gateway from: https://www.interactivebrokers.com/ -IB_HOST=127.0.0.1 -IB_PORT=7497 -IB_CLIENT_ID=1 -IB_PAPER_TRADING=true - -# TradingView Integration -# Set up alerts with webhooks: https://www.tradingview.com/ -TRADINGVIEW_USERNAME=your_tradingview_username -TRADINGVIEW_WEBHOOK_SECRET=your_webhook_secret_key -TRADINGVIEW_PAPER_TRADING=true - -# Indonesian Brokers (Local Market Access) -# ======================================== - -# Indopremier Securities (IPOT) - Local Indonesian stocks -# Sign up: https://www.indopremier.com/ -INDOPREMIER_USERNAME=your_indopremier_username -INDOPREMIER_PASSWORD=your_indopremier_password -INDOPREMIER_DEMO=true - -# XM Indonesia - International broker popular in Indonesia -# Sign up: https://www.xm.com/id/ -XM_INDONESIA_LOGIN=your_xm_login -XM_INDONESIA_PASSWORD=your_xm_password -XM_INDONESIA_SERVER=XM-Demo -XM_INDONESIA_DEMO=true - -# OctaFX Indonesia - Good spreads and demo accounts -# Sign up: https://www.octafx.com/id/ -OCTAFX_INDONESIA_LOGIN=your_octafx_login -OCTAFX_INDONESIA_PASSWORD=your_octafx_password -OCTAFX_INDONESIA_SERVER=OctaFX-Demo -OCTAFX_INDONESIA_DEMO=true - -# HSBC Indonesia - International bank trading -# Contact: HSBC Indonesia branch -HSBC_INDONESIA_USERNAME=your_hsbc_username -HSBC_INDONESIA_PASSWORD=your_hsbc_password -HSBC_INDONESIA_DEMO=true - -# Flask settings +# Flask Configuration +FLASK_APP=run.py FLASK_ENV=development -SECRET_KEY=your_flask_secret_here +FLASK_DEBUG=True -# Database -DB_NAME=bots.db +# Server Configuration +HOST=0.0.0.0 +PORT=5000 -# Optional API keys (if you expand) -CMC_API_KEY="" -ALPHA_VANTAGE_API_KEY="" -FINNHUB_API_KEY="" +# Database Configuration (SQLite default) +DATABASE_URL=sqlite:///database.db -# Logging level -LOG_LEVEL=INFO +# MT5 Configuration (REQUIRED for data downloading) +MT5_LOGIN=your_mt5_account_number_here +MT5_PASSWORD=your_mt5_password_here +MT5_SERVER=your_mt5_broker_server_here +# Example for FBS Demo: FBS-Demo +# Example for XM Global: XMGlobal-ServerName + +# MT5 Installation Paths (OPTIONAL - auto-detected if not specified) +MT5_TERMINAL_PATH=C:\Program Files\MetaTrader 5 +MT5_DATA_PATH=%APPDATA%\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075 + +# Advanced MT5 Settings +MT5_TIMEOUT_SECONDS=60 + +# Backtesting Configuration +BACKTEST_LOG_LEVEL=INFO + +# Application Settings +SECRET_KEY=your-secret-key-here-make-it-very-long-and-random + +# Additional MT5 Symbols (comma-separated) +CUSTOM_MT5_SYMBOLS=GBPAUD,NZDCAD,USDMXN diff --git a/CHANGELOG.md b/CHANGELOG.md index 86de6d3..b1c4a25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,50 @@ --- +## ๐Ÿ“ˆ **v2.0.3 - "Global Expansion & Multilingual"** โœจ + +### ๐ŸŒ **Internationalization (i18n) System** โญโญโญ +- **Complete Language Support**: Indonesian and English fully implemented +- **Global Language Switcher**: Fixed position toggle in top-right corner +- **Persistent Language Preferences**: Remembers user choice across sessions +- **Extensible Architecture**: Ready for Chinese, Arabic, Spanish, Russian additions +- **Centralized Translation**: 80+ UI elements translated with clean dictionary system + +### ๐ŸŽฏ **Data Integration Enhancements** +- **Smart MT5 Detection**: Intelligent environment checking with fallback guidance +- **Automatic Data Download**: One-click market data fetching with progress tracking +- **Multi-Instrument Support**: Forex, Gold, Indices, Commodities, Crypto data handling +- **Broker Symbol Aliasing**: Automatic symbol mapping for different brokers (XM, FBS, IC Markets) +- **Data Quality Verification**: Automatic validation of downloaded historical data + +### ๐Ÿ›  **Setup & Installation Improvements** +- **Automated MT5 Installer**: One-command setup script with dependency management +- **Comprehensive Setup Guide**: 50+ page MT5 integration documentation +- **Environment Configuration**: Enhanced .env templates with broker-specific settings +- **Connection Testing**: Built-in MT5 connectivity verification tools +- **Troubleshooting Guides**: Detailed error resolution for common setup issues + +### โš™๏ธ **Settings & Preferences Expansion** +- **Global App Settings**: Language, theme, and user preferences management +- **Profile Management**: User profile editing with local data storage +- **Quick Settings Panel**: Toggle notifications, auto-updates, demo mode +- **Version Information**: App version tracking and update notifications +- **Future API Preview**: Preparatory UI for upcoming QuantumBotX API features + +### ๐Ÿ“Š **Navigation & UI Improvements** +- **Dynamic Navigation**: Context-aware menu items based on language and features +- **Real-time Updates**: Language changes apply instantly without page reload +- **Holiday Integration**: Bahasa Indonesia support for Ramadan/Christmas features +- **Accessibility Enhancement**: Better screen reader support with proper labels + +### ๐Ÿ”ง **Developer Experience** +- **Global Translation System**: Page-agnostic translation keys for consistent UI +- **Dynamic Content Loading**: SEO-friendly progressive enhancement +- **Fallback Translation**: Intelligent English fallback for missing translations +- **Translation Validation**: Built-in checks for missing translation keys + +--- + ## ๐Ÿ“ˆ **v2.0.2 - "Production Ready Improvements"** ### ๐Ÿ”ฅ **Critical Bug Fixes** diff --git a/MT5_SETUP_GUIDE.md b/MT5_SETUP_GUIDE.md new file mode 100644 index 0000000..372a436 --- /dev/null +++ b/MT5_SETUP_GUIDE.md @@ -0,0 +1,241 @@ +# ๐Ÿš€ QuantumBotX MT5 Integration Guide + +> **Get Historical Market Data for Advanced Backtesting** + +## ๐Ÿ“‹ Prerequisites + +**Required Software:** +- โœ… [MetaTrader 5 Platform](https://www.metatrader5.com/en/download) (Latest version) +- โœ… Python 3.8+ (Already included with QuantumBotX) +- โœ… Active MT5 Demo or Live Account + +--- + +## โšก Quick Setup (3 Steps) + +### Step 1: Install MT5 Platform +``` +1. Download MT5 from: https://www.metatrader5.com/en/download +2. Install in default location: C:\Program Files\MetaTrader 5 +3. Launch MT5 and login to your account (demo recommended) +4. Keep MT5 running in background for data downloads +``` + +### Step 2: Configure QuantumBotX Settings +```bash +# Copy and edit your .env file +cp .env.example .env + +# Edit .env with your MT5 credentials: +MT5_LOGIN=12345678 # Your MT5 account number +MT5_PASSWORD=YourPass # Your MT5 password +MT5_SERVER=FBS-Demo # Your broker server +``` + +### Step 3: Install MT5 Python Library +**Windows Command:** +```bash +# Open Command Prompt as Administrator +pip install MetaTrader5 + +# Alternative (from Requirements): +pip install -r requirements.txt +``` + +--- + +## ๐Ÿ”ง Manual MT5 Library Installation + +If standard installation fails: + +### Method A: Wheel File (Recommended) +```bash +# Download the wheel file manually +pip install MetaTrader5-5.0.45-cp38-cp38-win_amd64.whl + +# Or download from: https://pypi.org/project/MetaTrader5/#files +``` + +### Method B: Conda Environment +```bash +# Create dedicated environment +conda create -n qb_mt5 python=3.9 +conda activate qb_mt5 + +# Install MT5 +conda install MetaTrader5 -c conda-forge +``` + +--- + +## ๐ŸŒ Supported Brokers + +**Pre-configured for:** +- โœ… FBS Markets (FBS-Demo) +- โœ… XM Global (XMGlobal-Real/live server names) +- โœ… IC Markets (ICMarkets-Demo) +- โœ… Pepperstone (Pepperstone-Demo) + +**For other brokers:** +```env +# Add to your .env file: +MT5_SERVER=YourBroker-ServerName +``` + +--- + +## ๐Ÿ—‚๏ธ Data Download Features + +### Automatic Symbol Detection +- **Forex:** EURUSD, GBPUSD, AUDUSD, JPY pairs, etc. +- **Gold:** XAUUSD (ultra-conservative risk management) +- **Indices:** US30, US100, US500 (S&P 500, Dow Jones) +- **Commodities:** Oil, Natural Gas +- **Crypto:** BTCUSD, ETHUSD (if supported) +- **Exotic Pairs:** Currency pairs not in default list + +### What Gets Downloaded +- โœ… OHLCV data (Open, High, Low, Close, Volume) +- โœ… Multiple timeframes (H1 recommended for backtesting) +- โœ… Last 4+ years of historical data +- โœ… Automatic broker symbol aliasing +- โœ… Indonesian market focus (USDIDR) +- โœ… European indices (DE30, UK100) + +--- + +## ๐Ÿšฆ Testing Your Setup + +### Test 1: MT5 Connection +```bash +# Run the download script directly +python lab/download_data.py +``` +**Expected Output:** +``` +โœ… Successfully connected to MT5 +๐Ÿ“ก Server: FBS-Demo +๐Ÿ‘ค Account: 12345678 +๐Ÿ’ฐ Balance: $10,000.00 + +๐Ÿ“Š Downloading data from 2020-01-01 to 2025-09-24 +๐Ÿ“Š Downloading EURUSD data... +โœ… EURUSD: 15000 bars saved to lab/backtest_data/EURUSD_H1_data.csv +``` + +### Test 2: Web Interface +``` +1. Start QuantumBotX: python run.py +2. Open: http://localhost:5000/backtest +3. Click: "Download Data MT5" button +4. Should show: "Downloaded X files successfully" +``` + +--- + +## ๐Ÿ› Troubleshooting + +### Error: "MetaTrader5 module not found" +```bash +# Windows installation fix +pip uninstall MetaTrader5 +pip install --no-cache-dir MetaTrader5 + +# Or use specific wheel: +pip install MetaTrader5-5.0.34-cp39-cp39-win_amd64.whl +``` + +### Error: "Failed to initialize MT5" +``` +โœ… Check MT5 is running +โœ… Verify account credentials in .env +โœ… Try Demo account first +โœ… Check broker server name matches exactly +``` + +### Error: "Symbol not found" +``` +โœ… MT5 shows: "Enable Auto Trading" in algo settings +โœ… Check if symbol is visible in MT5 Market Watch +โœ… Some symbols need manual activation in MT5 +โœ… Broker may not offer certain instruments +``` + +### Error: "Download timed out" +``` +โœ… Reduce download period in script if needed +โœ… Check internet connection stability +โœ… Some brokers are faster than others +โœ… Account may have download rate limits +``` + +--- + +## ๐Ÿ”„ Advanced Configuration + +### Custom Symbol List +Add to your `.env` file: +```env +CUSTOM_MT5_SYMBOLS=GBPAUD,NZDCAD,USDMXN,HK50,AUS200 +``` + +### Proxy Settings (if needed) +```env +MT5_PROXY_HOST=your.proxy.host +MT5_PROXY_PORT=8080 +MT5_PROXY_USER=username +MT5_PROXY_PASS=password +``` + +### Log Level Control +```env +BACKTEST_LOG_LEVEL=DEBUG # For troubleshooting +``` + +--- + +## ๐Ÿ“Š Data Quality Verification + +After download, check your CSV files: +```python +import pandas as pd +df = pd.read_csv('lab/backtest_data/EURUSD_H1_data.csv') +print(f"Rows: {len(df)}") +print(f"Date range: {df['time'].min()} to {df['time'].max()}") +print(f"Latest close: {df['close'].iloc[-1]}") +``` + +**Expected Output:** +``` +Rows: 15800+ (4+ years of H1 data) +Date range: 2020-01-01 to current_date +Latest close: matches MT5 current price +``` + +--- + +## ๐ŸŽฏ Next Steps After Setup + +1. **Run Initial Downloads:** Get historical data for major symbols +2. **Test Backtesting:** Upload CSV files and test strategies +3. **Create Bots:** Use analysis features with real data +4. **Monitor Performance:** Track equity curves and metrics + +--- + +## ๐Ÿ“ž Support + +**Common Issues:** +- MT5 needs to remain logged in during downloads +- Some brokers require manual symbol activation +- Demo accounts sometimes have download limits +- VPN may be needed for some broker connections + +**Help Resources:** +- MT5 Official Documentation: https://www.metatrader5.com +- QuantumBotX Issue Tracker: Check GitHub issues +- Community: Join Discord/Telegram for support + +--- + +*Happy Trading! ๐ŸŽฏ๐Ÿ“ˆ* diff --git a/README.md b/README.md index 3988f92..41cfbc5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,20 @@ Designed to be elegant, powerful, and flexible โ€” whether you're a scalper, swi --- +## โš ๏ธ Platform Support Notice + +### **Primary Platform: Windows** ๐ŸชŸ +This version of QuantumBotX is **optimized for Windows** and requires MetaTrader 5 terminal to be installed locally. It's designed for learning algorithmic trading on your personal computer. + +### **Alternative Platforms** ๐Ÿ”„ +- **Linux**: Can attempt using Wine (experimental - see Linux Setup guide below) +- **macOS**: Not officially supported (requires Wine or Windows VM) +- **Cloud/VPS**: Not compatible (requires local MT5 terminal) + +> ๐Ÿ’ก **Pro Tip**: For cloud deployment and multi-platform support, check out our upcoming **QuantumBotX API** version! + +--- + ## ๐Ÿš€ Features ### ๐ŸŽฏ **Core Trading Engine** diff --git a/README_NEW.md b/README_NEW.md new file mode 100644 index 0000000..049f810 --- /dev/null +++ b/README_NEW.md @@ -0,0 +1,203 @@ +# ๐Ÿค– QuantumBotX โ€” AI-Powered Modular Trading Bot for MT5 + +Welcome to **QuantumBotX**, your personal, modular, and smart trading assistant built with Python and MetaTrader5 (MT5). + +--- + +## ๐Ÿš€ Quick Start with MT5 Integration + +**New to QuantumBotX?** Follow these 3 simple steps: + +### โšก Step 1: Install MT5 Integration +```bash +# Automatically detect, install, and configure MT5 +python install_mt5_integration.py + +# This will: +# โœ… Check Python compatibility +# โœ… Install MetaTrader5 library +# โœ… Verify MT5 platform installation +# โœ… Create .env configuration template +# โœ… Generate connection test script +``` + +### ๐Ÿฆ Step 2: Setup MT5 Platform +```bash +# 1. Download MT5 from: https://www.metatrader5.com/en/download +# 2. Install with default settings +# 3. Launch MT5 and create/login to demo account +# 4. Keep MT5 running - it's required for data downloads +``` + +### โš™๏ธ Step 3: Configure & Test +```bash +# Edit your .env file with MT5 credentials: +# MT5_LOGIN=your_account_number +# MT5_PASSWORD=your_password +# MT5_SERVER=FBS-Demo + +# Test your MT5 connection: +python test_mt5_connection.py + +# Download market data (or use web interface): +python lab/download_data.py + +# Start trading interface: +python run.py +``` + +### โ“ Need Help? +- ๐Ÿ“– **Full Guide**: Check `MT5_SETUP_GUIDE.md` +- ๐Ÿงช **Quick Test**: `python test_mt5_connection.py` +- ๐Ÿ”ง **Manual Config**: Edit `.env` file directly + +--- + +## ๐ŸŽฏ Key Features + +### ๐Ÿ“Š **Professional Backtesting** +- **MT5 Data Integration**: Download 50+ instruments directly from brokers +- **Realistic Modeling**: Spread, slippage, and commission simulation +- **Strategy Testing**: 16+ strategies with custom parameters +- **Performance Analytics**: Equity curves, drawdown analysis, risk metrics + +### ๐Ÿง  **Smart Bot Management** +- **Real-Time Monitoring**: Live bot status with auto-refresh +- **Risk Protection**: Ultra-safe position sizing, especially for gold/XAUUSD +- **Strategy Switching**: Automated strategy adaptation to market conditions +- **Multi-Broker Support**: XM Global, FBS, Exness, IC Markets, Pepperstone + +### ๐Ÿ” **Market Analysis** +- **Live Data Analysis**: Real-time signals from MT5 market data +- **Multi-Timeframe**: Daily, H1, M15 analysis for comprehensive signals +- **Holiday Detection**: Automatic Christmas/Ramadan mode activation +- **AI Mentor**: Personalized trading guidance in Indonesian + +### ๐Ÿ” **Safety First** +- **Conservative Defaults**: Beginner-safe settings out of the box +- **Account Protection**: Emergency brakes and risk limits +- **Testing Mode**: Demo account support before live trading +- **Clean Architecture**: Modular design for reliability + +--- + +## ๐Ÿ—‚๏ธ Data Download Features + +### Available Instruments +- **Forex**: EURUSD, GBPUSD, AUDUSD, JPY pairs, major crosses +- **Gold**: XAUUSD with ultra-conservative risk management +- **Indices**: US30, US100, US500 (S&P 500), DE30, UK100 +- **Commodities**: Oil (USOIL, UKOIL), Natural Gas +- **Crypto**: BTCUSD, ETHUSD (if supported by broker) +- **Exotic Pairs**: Currency pairs for advanced traders + +### Data Quality +- โœ… **4+ Years** of historical data +- โœ… **OHLCV Format**: Open, High, Low, Close, Volume +- โœ… **Broker Aliasing**: Automatic XAUUSD/USDIDR variant detection +- โœ… **Timeframes**: H1 (recommended), M1, M5, M15, H4, D1 + +### Download Methods +1. **Web Interface**: Click "Download Data MT5" button on backtesting page +2. **Command Line**: `python lab/download_data.py` +3. **Automatic Installer**: `python install_mt5_integration.py` + +--- + +## ๐Ÿงช Technical Stack + +- **Python 3.10+** with async capabilities +- **Flask** web framework with real-time updates +- **MetaTrader5** direct broker integration +- **pandas-ta** for technical analysis +- **Chart.js** for interactive visualizations +- **SQLite** with migration support + +--- + +## ๐Ÿง  AI Mentor Features + +- **Indonesian Language**: Guidance in Bahasa Indonesia +- **Emotional Intelligence**: Understanding trader psychology +- **Performance Analysis**: Trade pattern recognition +- **Risk Assessment**: Personalized risk tolerance evaluation +- **Strategy Recommendations**: Matching strategies to trader level +- **Motivational Support**: Contextual encouragement + +--- + +## ๐Ÿ“š Educational Framework + +### Beginner Path (Month 1) +- **Week 1**: MA Crossover on EURUSD +- **Week 2**: Bollinger Bands for range trading +- **Week 3**: Basic risk management practices +- **Week 4**: Understanding ATR-based position sizing + +### Intermediate Path (Month 2-3) +- **Strategy Rotation**: Multiple approaches per market +- **Parameter Optimization**: Finding edge through testing +- **Market Analysis**: Understanding different market regimes +- **Risk Scaling**: Position sizing based on confidence + +### Advanced Mastery (Month 4+) +- **Strategy Combination**: Multi-strategy portfolios +- **Market Timing**: When to trade what +- **Risk Management**: Advanced portfolio protection +- **Psychology**: Maintaining discipline + +--- + +## โš ๏ธ Important Disclaimers + +**Trading Risks:** +- FX trading involves substantial risk and may not be suitable for all +- High leverage can amplify losses +- Past performance โ‰  future results +- Never trade with money you can't afford to lose + +**Software Usage:** +- For educational/research purposes +- Test thoroughly on demo accounts first +- Creator not responsible for trading losses +- Use at your own risk + +--- + +## ๐Ÿค Support & Community + +- **Documentation**: Full setup guides in `/docs` +- **Issues**: GitHub Issues for bugs/features +- **Discussions**: Community support forum +- **Updates**: Check changelog for improvements + +--- + +## ๐Ÿ“ˆ What's Next? + +### Current Features โœ… +- โœ… MT5 Integration with 50+ instruments +- โœ… 16 Trading strategies with risk management +- โœ… AI mentor in Indonesian +- โœ… Professional backtesting engine +- โœ… Holiday-aware trading modes +- โœ… Ultra-conservative gold/XAUUSD protection + +### Coming Soon ๐Ÿšง +- ๐Ÿ”„ Telegram notifications +- ๐Ÿ”„ Advanced portfolio analytics +- ๐Ÿ”„ Multi-broker arbitrage +- ๐Ÿ”„ Custom strategy builder +- ๐Ÿ”„ Community marketplace + +--- + +## โ˜• Support Development + +Enjoy QuantumBotX? Consider supporting future development: + +[Donate with PayPal](https://www.paypal.com/paypalme/rebarakaz) + +--- + +*Happy Trading! ๐ŸŽฏ๐Ÿ“Š๐Ÿ†* diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..5c75ba6 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,218 @@ +# ๐Ÿš€ QuantumBotX Product Roadmap 2025-2026 + +> **From Local MT5 Platform โ†’ Global Cloud Trading System** + +--- + +## ๐Ÿ“ **Current Status: v2.0.3 - Global Expansion Complete** +โœ… **Multilingual Support**: Indonesian & English fully implemented +โœ… **Data Integration**: Smart MT5 detection with web controls +โœ… **Professional Documentation**: Comprehensive setup guides +โœ… **User Experience**: Streamlined onboarding and settings + +--- + +## ๐ŸŽฏ **Q4 2025: Stability & Market Penetration** + +### **v2.1 - "Intelligence Enhancement"** (3 Months) + +#### ๐Ÿง  **AI & Analytics Features** +- โœ… **MACD_STOCH_FILTER Strategy**: Advanced precision entry system +- โœ… **Telegram Notifications**: Real-time alerts for trades/errors +- โœ… **Smart Parameter Optimization**: AI-assisted strategy tuning +- โœ… **Portfolio Analytics Dashboard**: Advanced risk/correlation analysis +- โœ… **Enhanced Market Regime Detection**: Multi-timeframe market analysis + +#### ๐Ÿ“Š **Advanced Reporting** +- โœ… **Performance Heatmaps**: Strategy performance visualization +- โœ… **Risk Attribution Analysis**: Which factors affect returns most +- โœ… **Monthly Reporting**: Automated performance summaries +- โœ… **Benchmarking System**: Compare against market indices + +#### ๐Ÿ”ง **Platform Improvements** +- โœ… **Multi-Account Management**: Handle multiple trading accounts +- โœ… **Strategy Cloning**: Duplicate and modify existing strategies +- โœ… **Bulk Operations**: Start/stop multiple bots simultaneously +- โœ… **API Rate Limiting**: Prevent excessive broker API calls + +### **Market Goals Q4** +- **GitHub Release**: Open-source launch with 200+ stars +- **Community Building**: Discord/Telegram groups with 500+ members +- **Education Focus**: Launch beginner YouTube channel +- **Broker Partnerships**: Initial deals with 2-3 brokers + +--- + +## ๐ŸŒŸ **Q1 2026: Enterprise Features & API Foundation** + +### **v2.2 - "Enterprise Ready"** (3-4 Months) + +#### ๐Ÿข **Enterprise Features** +- โœ… **User Roles & Permissions**: Admin, Trader, Viewer roles +- โœ… **Audit Logging**: Complete action history for compliance +- โœ… **White-label Support**: Custom branding for firms +- โœ… **API Documentation**: REST endpoints for integrations + +#### ๐Ÿ”— **External Integrations** +- โœ… **Discord Webhooks**: Trading alerts to Discord channels +- โœ… **Slack Notifications**: Team trading notifications +- โœ… **Email Automation**: Professional performance reports +- โœ… **Webhooks**: Custom integration support + +### **QuantumBotX API Research & Planning** โšก +**Timeline: Q1 2026** +- **Market Research**: Identify best broker API partners (IC Markets, Pepperstone focus) +- **Technical Architecture**: Design microservices for cloud deployment +- **Security Planning**: API key management and authentication systems +- **Prototype Development**: Proof-of-concept API trading endpoints + +### **Market Goals Q1** +- **10,000 Downloads**: Aggressive growth with community marketing +- **Enterprise Pilot**: First institutional client deployment +- **Language Expansion**: Chinese interface preparation +- **Subscription Model**: Freemium to pro upgrade conversion testing + +--- + +## ๐Ÿš€ **Q2-Q3 2026: API Platform Launch** + +### **QuantumBotX API v1.0 - "Cloud Liberation"** ๐ŸŒ + +#### ๐ŸŽฏ **Core API Features** +- โœ… **Direct Broker API Integration**: No MT5 terminal required! +- โœ… **Cross-Platform Support**: Windows, Mac, Linux, VPS, Cloud +- โœ… **Multi-Broker Support**: IC Markets, Pepperstone, Key brokers +- โœ… **24/7 Trading**: Server-based operation + +#### ๐Ÿ—๏ธ **Technical Implementation** +- โœ… **Microservices Architecture**: Website (Flask) + Trading Engine (FastAPI) +- โœ… **Docker Orchestration**: Containerized deployment +- โœ… **WebSocket Streaming**: Real-time market data +- โœ… **REST API Trading**: Place/exit trades programmatically + +#### ๐Ÿ’ฐ **Supported Brokers (Phase 1)** +- โœ… **IC Markets**: Primary focus, excellent API documentation +- โœ… **Pepperstone**: Enterprise-grade API support +- โœ… **Deriv**: Binary/forex options integration +- โœ… **Additional**: Research and partnership development + +#### ๐ŸŒ **Business Model** +- โœ… **Free Tier**: Basic features for individual traders +- โœ… **Pro Subscription**: $29/month - Unlimited brokers/signals +- โœ… **Enterprise Tier**: $299/month - White-label + custom features +- โœ… **Broker Partnerships**: Revenue sharing per active trader + +### **Current MT5 Version (Maintenance Mode)** +- โœ… **Continued Support**: Windows users still supported +- โœ… **Learning Path**: Beginner education funnel to API version +- โœ… **Feature Parity**: API features backported where possible + +### **API Launch Strategy** +1. **Closed Beta**: 100 users, fee waivers for feedback +2. **Public Beta**: 1,000 users, premium support +3. **Full Launch**: Global availability with paid subscriptions +4. **Partnership Program**: Broker incentives for integrations + +--- + +## ๐Ÿ“Š **Q4 2026: Scale & Expansion** + +### **QuantumBotX API v2.0 - "Global Domination"** ๐ŸŒ + +#### ๐ŸŒ **International Expansion** +- โœ… **Multi-Language Support**: Chinese, Arabic, Spanish, Russian +- โœ… **Regional Broker Focus**: Local broker partnerships +- โœ… **Cultural Customization**: Holiday awareness per region +- โœ… **Localized Education**: Region-specific trading content + +#### ๐Ÿ“ˆ **Advanced Features** +- โœ… **AI Strategy Optimization**: ML-based parameter tuning +- โœ… **Portfolio Management**: Multi-strategy allocation +- โœ… **Arbitrage Engine**: Cross-broker opportunity scanning +- โœ… **Community Marketplace**: User-created strategy sharing + +#### ๐Ÿ’ฐ **Revenue Targets** +- **Base**: 5,000 paid subscribers @ $29/month ($1.74M ARR) +- **Enterprise**: 20 clients @ $299/month ($718K ARR) +- **Total Target**: $2.45M ARR by end of 2026 + +--- + +## ๐ŸŽฏ **Key Success Metrics** + +### **Technical KPIs** +- โœ… **99.9% Uptime**: Cloud-based reliability +- โœ… **<5ms Latency**: Low-latency trade execution +- โœ… **Zero Broker Disconnects**: Robust connection handling +- โœ… **Real-time Performance**: Sub-second signal generation + +### **Business KPIs** +- โœ… **Community Size**: 10,000+ active traders +- โœ… **Market Coverage**: 50+ countries reached +- โœ… **Broker Partnerships**: 10+ integrated brokers +- โœ… **Conversion Rate**: 15% free โ†’ paid upgrade rate + +### **Product KPIs** +- โœ… **Strategy Performance**: Consistently beating benchmarks +- โœ… **User Satisfaction**: 4.8+ star ratings +- โœ… **Educational Value**: Proven learning outcomes +- โœ… **Risk Management**: Zero significant account losses + +--- + +## ๐Ÿ’ก **Key Competitive Advantages** + +### **Vs Traditional Platforms** +- โœ… **Education First**: Learning-focused vs profit-focused +- โœ… **Conservative Approach**: Risk management prioritized +- โœ… **Cultural Intelligence**: Indonesian market psychology + +### **Vs Other Trading Bots** +- โœ… **Multi-Broker Freedom**: Not locked to one platform +- โœ… **Strategy Transparency**: Open-source strategy evaluation +- โœ… **Community Building**: Collaborative improvement + +### **Vs API-Only Solutions** +- โœ… **Complete Platform**: Not just APIs, full trading system +- โœ… **Educational Framework**: Learning built-in +- โœ… **Risk Management**: Conservative by default + +--- + +## ๐ŸŽ–๏ธ **Development Principles** + +### **User-Centric Development** +- **Safety First**: Every feature vetted for risk management +- **Education Priority**: Learning > Profits mindset +- **Inclusive Design**: Support traders of all experience levels + +### **Technical Excellence** +- **Microservices**: Scalable, maintainable architecture +- **Security First**: Financial data protection paramount +- **Performance Obsessed**: Low latency, high reliability + +### **Sustainable Growth** +- **Open Source Roots**: Community contributions welcomed +- **Transparent Pricing**: No surprise fees or commissions +- **Ethical Practices**: No predatory monetization + +--- + +## ๐ŸŒŸ **Mission Achievement Timeline** + +### **2025 Goals** +- โœ… Launch Windows MT5 platform +- โœ… Build Indonesian trading community +- โœ… Establish educational reputation +- โœ… Research API broker partnerships + +### **2026 Goals** +- ๐Ÿšง Launch QuantumBotX API platform +- ๐Ÿšง Achieve 10,000+ active users +- ๐Ÿšง Generate $2M+ annual revenue +- ๐Ÿšง Become leading algorithmic trading education platform + +--- + +**Roadmap Last Updated: September 2025** +*Version: Comprehensive Expansion Plan* ๐Ÿš€๐Ÿ”ฎ diff --git a/core/bots/controller.py b/core/bots/controller.py index de717ae..f1c228d 100644 --- a/core/bots/controller.py +++ b/core/bots/controller.py @@ -4,6 +4,7 @@ import json import logging from core.db import queries from .trading_bot import TradingBot +from core.strategies.strategy_map import STRATEGY_MAP logger = logging.getLogger(__name__) @@ -257,4 +258,42 @@ def get_bot_analysis_data(bot_id: int): bot = active_bots.get(bot_id) if bot and hasattr(bot, 'last_analysis'): return bot.last_analysis - return None \ No newline at end of file + + # For inactive bots, generate analysis on-demand + bot_data = queries.get_bot_by_id(bot_id) + if not bot_data: + return None + + try: + import MetaTrader5 as mt5 + from core.utils.mt5 import find_mt5_symbol, get_rates_mt5, TIMEFRAME_MAP + + # Find the symbol + market_for_mt5 = find_mt5_symbol(bot_data['market']) + if not market_for_mt5: + return {"signal": "ERROR", "explanation": f"Symbol '{bot_data['market']}' not found in MT5"} + + # Get market data + tf_const = TIMEFRAME_MAP.get(bot_data['timeframe'], mt5.TIMEFRAME_H1) + df = get_rates_mt5(market_for_mt5, tf_const, 250) + if df.empty: + return {"signal": "ERROR", "explanation": "Unable to fetch market data"} + + # Instantiate strategy + strategy_class = STRATEGY_MAP.get(bot_data['strategy']) + if not strategy_class: + return {"signal": "ERROR", "explanation": f"Strategy '{bot_data['strategy']}' not found"} + + # Parse strategy params + params_dict = json.loads(bot_data.get('strategy_params', '{}')) + + # Create a temp strategy instance (without bot_instance since it's just for analysis) + strategy_instance = strategy_class(bot_instance=None, params=params_dict) + + # Generate analysis + analysis = strategy_instance.analyze(df) + return analysis + + except Exception as e: + logger.error(f"Error generating analysis for inactive bot {bot_id}: {e}") + return {"signal": "ERROR", "explanation": f"Failed to generate analysis: {str(e)}"} diff --git a/core/routes/api_backtest.py b/core/routes/api_backtest.py index 2c654d8..f21bfcc 100644 --- a/core/routes/api_backtest.py +++ b/core/routes/api_backtest.py @@ -4,6 +4,8 @@ import numpy as np import pandas as pd import json import logging +import subprocess +import os from flask import Blueprint, request, jsonify from core.backtesting.enhanced_engine import run_enhanced_backtest as run_backtest from core.db.queries import get_all_backtest_history @@ -168,4 +170,92 @@ def get_history_route(): return jsonify(processed_history) except Exception as e: logger.error(f"Error processing history: {str(e)}", exc_info=True) - return jsonify({"error": f"Terjadi kesalahan saat mengambil riwayat: {str(e)}"}), 500 \ No newline at end of file + return jsonify({"error": f"Terjadi kesalahan saat mengambil riwayat: {str(e)}"}), 500 + +@api_backtest.route('/api/download-data', methods=['POST']) +def download_data_route(): + """Download historical market data using the standalone script""" + try: + # Path to the download script + script_path = os.path.join(os.path.dirname(__file__), '..', '..', 'lab', 'download_data.py') + script_path = os.path.abspath(script_path) + + if not os.path.exists(script_path): + return jsonify({"error": "Download script not found"}), 404 + + # Check if the script can import MT5 (basic validation) + try: + result_check = subprocess.run( + ['python', '-c', 'import MetaTrader5 as mt5; print("MT5 available")'], + capture_output=True, + text=True, + timeout=10 + ) + if result_check.returncode != 0: + return jsonify({ + "error": "MetaTrader5 module not available. Make sure you run the download script manually in an environment where MT5 is installed.", + "solution": "Run 'python lab/download_data.py' from command line instead." + }), 500 + except subprocess.TimeoutExpired: + return jsonify({ + "error": "MT5 availability check timed out", + "solution": "Ensure MT5 terminal is running and accessible" + }), 408 + + # Run the download script + logger.info(f"Starting data download with script: {script_path}") + + # Use subprocess to run the script and capture output + result = subprocess.run( + ['python', script_path], + capture_output=True, + text=True, + timeout=300 # 5 minute timeout + ) + + if result.returncode == 0: + # Success - parse output to extract info + output_lines = result.stdout.strip().split('\n') + downloaded_files = [] + failed_count = 0 + + for line in output_lines: + if line.startswith('โœ…') and 'bars saved to' in line: + # Extract filename from success message + parts = line.split('bars saved to') + if len(parts) > 1: + filepath = parts[1].strip() + filename = os.path.basename(filepath) + downloaded_files.append(filename) + elif line.startswith('โŒ Failed downloads:'): + # Extract failed count + parts = line.split(':') + if len(parts) > 1: + try: + failed_count = len(parts[1].strip().split(', ')) if parts[1].strip() else 0 + except: + failed_count = 0 + + return jsonify({ + "success": True, + "message": f"Downloaded {len(downloaded_files)} files successfully" + (f", {failed_count} failed" if failed_count > 0 else ""), + "downloaded_files": downloaded_files, + "failed_count": failed_count, + "output": result.stdout + }) + else: + # Process failed + error_msg = result.stderr or "Unknown error occurred" + logger.error(f"Data download failed: {error_msg}") + return jsonify({ + "error": f"Download failed: {error_msg}", + "output": result.stderr, + "stdout": result.stdout + }), 500 + + except subprocess.TimeoutExpired: + logger.error("Data download timed out") + return jsonify({"error": "Download timed out after 5 minutes"}), 408 + except Exception as e: + logger.error(f"Error in download data route: {str(e)}", exc_info=True) + return jsonify({"error": f"Unexpected error: {str(e)}"}), 500 diff --git a/install_mt5_integration.py b/install_mt5_integration.py new file mode 100644 index 0000000..a47e60f --- /dev/null +++ b/install_mt5_integration.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python3 +""" +QuantumBotX MT5 Integration Installer +Automated setup for MT5 data downloading and integration + +Usage: python install_mt5_integration.py +""" + +import os +import sys +import subprocess +import platform +import json +import urllib.request +from pathlib import Path + +class MT5IntegrationInstaller: + def __init__(self): + self.project_root = Path(__file__).parent + self.system = platform.system().lower() + self.arch = platform.machine().lower() + + def print_header(self): + """Print installation header""" + print("=" * 60) + print("๐Ÿš€ QuantumBotX MT5 Integration Setup") + print("=" * 60) + print() + + def check_python_version(self): + """Check Python version compatibility""" + print("๐Ÿ Checking Python version...") + version = sys.version_info + if version.major == 3 and version.minor >= 8: + print(f"โœ… Python {version.major}.{version.minor}.{version.micro} - Compatible") + return True + else: + print(f"โŒ Python {version.major}.{version.minor}.{version.micro} - Requires Python 3.8+") + return False + + def check_mt5_library(self): + """Check if MetaTrader5 library is installed""" + print("\n๐Ÿ“ฆ Checking MT5 Python library...") + try: + import MetaTrader5 as mt5 + version = getattr(mt5, '__version__', 'unknown') + print(f"โœ… MetaTrader5 library installed (v{version})") + return True + except ImportError: + print("โŒ MetaTrader5 library not found") + return False + + def install_mt5_library(self): + """Attempt to install MetaTrader5 library""" + print("\n๐Ÿš€ Installing MetaTrader5 library...") + + # Try pip installation first + try: + print("Trying standard pip installation...") + subprocess.check_call([ + sys.executable, "-m", "pip", "install", + "--prefer-binary", "MetaTrader5" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + print("โœ… Successfully installed MetaTrader5 via pip") + return True + except subprocess.CalledProcessError as e: + print(f"โŒ Standard pip installation failed: {e}") + + # Try alternative installation methods + if self._install_mt5_alternatives(): + return True + + return False + + def _install_mt5_alternatives(self): + """Alternative MT5 installation methods""" + print("\n๐Ÿ”„ Trying alternative installation methods...") + + # Method 1: Pre-compiled wheel + wheel_urls = { + 'windows': { + 'amd64': [ + 'https://files.pythonhosted.org/packages/78/bb/e59deb5a4106b89d7d0b5ef8c3c61580a7d04378a5a5bbcef5234e8ad5632c6/MetaTrader5-5.0.45-cp39-cp39-win_amd64.whl', + 'https://files.pythonhosted.org/packages/d9/a9/a7fe0c98bf74ec5c1b70e7b10b2f4cf5be58ead3b024902ab31a4afe81a0798/MetaTrader5-5.0.45-cp38-cp38-win_amd64.whl', + 'https://files.pythonhosted.org/packages/f5/b7/3835fbab7dadbd1659eb0b90d22e92e3c9ddd2ce4a56fc2c3837ec415edde25/MetaTrader5-5.0.42-cp37-cp37m-win_amd64.whl' + ] + } + } + + if self.system == 'windows' and 'amd64' in self.arch: + print("๐Ÿ’พ Trying pre-compiled wheel for Windows...") + for wheel_url in wheel_urls['windows']['amd64']: + try: + # Download and install wheel + wheel_name = wheel_url.split('/')[-1] + wheel_path = self.project_root / wheel_name + + print(f"Downloading {wheel_name}...") + urllib.request.urlretrieve(wheel_url, wheel_path) + + subprocess.check_call([ + sys.executable, "-m", "pip", "install", str(wheel_path) + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # Clean up + wheel_path.unlink(missing_ok=True) + + print("โœ… Successfully installed MetaTrader5 via wheel") + return True + + except Exception as e: + print(f"Wheel installation failed: {e}") + if wheel_path.exists(): + wheel_path.unlink(missing_ok=True) + continue + + return False + + def create_env_template(self): + """Create/update .env file with MT5 configuration""" + print("\nโš™๏ธ Configuring .env file...") + + env_file = self.project_root / '.env' + env_example = self.project_root / '.env.example' + + if not env_example.exists(): + print("โŒ .env.example not found!") + return False + + # Read existing .env or create new one + if env_file.exists(): + print("๐Ÿ“„ Existing .env file found - backing up") + backup = env_file.with_suffix('.env.backup') + env_file.rename(backup) + + # Copy example file + env_file.write_text(env_example.read_text()) + print("โœ… Created .env file with MT5 configuration template") + + # Interactive configuration + print("\n" + "="*50) + print("๐Ÿ“ MT5 Configuration Required") + print("="*50) + print("Edit your .env file with your MT5 credentials:") + print() + print("Required settings:") + print("- MT5_LOGIN=your_account_number") + print("- MT5_PASSWORD=your_password") + print("- MT5_SERVER=your_broker_server (e.g., FBS-Demo)") + print() + print("Example .env entries:") + print("MT5_LOGIN=12345678") + print("MT5_PASSWORD=mySecurePass123") + print("MT5_SERVER=FBS-Demo") + print() + + return True + + def check_mt5_installation(self): + """Check if MetaTrader 5 platform is installed""" + print("\n๐Ÿฆ Checking MT5 platform installation...") + + mt5_paths = [ + r"C:\Program Files\MetaTrader 5", + r"C:\Program Files (x86)\MetaTrader 5", + os.path.expanduser(r"~\AppData\Local\MetaTrader 5"), + os.path.expanduser(r"~\AppData\Roaming\MetaTrader 5") + ] + + for path in mt5_paths: + if os.path.exists(path) and os.path.isdir(path): + terminal_exe = os.path.join(path, "terminal64.exe") + if os.path.exists(terminal_exe): + print(f"โœ… MT5 Platform found at: {path}") + print(f" Executable: {terminal_exe}") + return True + + print("โ“ MT5 Platform not found in common locations") + print("๐Ÿ’ก Download from: https://www.metatrader5.com/en/download") + return False + + def create_download_test(self): + """Create a test script to verify MT5 setup""" + print("\n๐Ÿงช Creating MT5 connection test...") + + test_script = '''#!/usr/bin/env python3 +""" +MT5 Connection Test Script +Run this to verify your MT5 setup works correctly +""" + +import os +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() + +# Check credentials +login = os.getenv('MT5_LOGIN') +password = os.getenv('MT5_PASSWORD') +server = os.getenv('MT5_SERVER') + +print("๐Ÿงช Testing MT5 Integration...") + +if not all([login, password, server]): + print("โŒ Missing MT5 credentials in .env file!") + print("Required: MT5_LOGIN, MT5_PASSWORD, MT5_SERVER") + exit(1) + +print("โœ… Credentials found") + +# Test MT5 import +try: + import MetaTrader5 as mt5 + print("โœ… MetaTrader5 library imported successfully") +except ImportError: + print("โŒ MetaTrader5 library not installed") + exit(1) + +# Test connection +print("๐Ÿ”— Testing MT5 connection...") +if not mt5.initialize(login=int(login), password=password, server=server): + error = mt5.last_error() + print(f"โŒ Failed to connect to MT5: {error}") + exit(1) + +print("โœ… Successfully connected to MT5!") +print(f"๐Ÿ“ก Server: {server}") +print(f"๐Ÿ‘ค Account: {login}") + +# Test data download +print("\\n๐Ÿ“Š Testing EURUSD data download...") +import pandas as pd +from datetime import datetime + +try: + rates = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_H1, datetime(2024, 1, 1), datetime.now()) + + if rates is None or len(rates) == 0: + print("โŒ No data received from MT5") + exit(1) + + df = pd.DataFrame(rates) + print(f"โœ… Successfully downloaded {len(df)} EURUSD H1 bars") + print(f" ๐Ÿ“… Date range: {df['time'].min()} to {df['time'].max()}") + +except Exception as e: + print(f"โŒ Data download test failed: {e}") + exit(1) + +mt5.shutdown() +print("\\n๐ŸŽ‰ All tests passed! MT5 integration is working correctly.") +''' + + test_file = self.project_root / 'test_mt5_connection.py' + test_file.write_text(test_script) + test_file.chmod(0o755) # Make executable + + print("โœ… Created test script: test_mt5_connection.py") + print("๐Ÿƒ Run with: python test_mt5_connection.py") + + return True + + def main(self): + """Main installation process""" + self.print_header() + + if not self.check_python_version(): + return False + + # Check if MT5 library is already installed + mt5_installed = self.check_mt5_library() + + if not mt5_installed: + print("\n" + "!"*60) + print("โŒ MT5 Python Library Required") + print("!"*60) + print() + print("The MetaTrader5 Python library needs to be installed.") + print("This requires:") + print("โ€ข Administrator privileges (Windows)") + print("โ€ข Visual C++ Redistributables (if missing)") + print("โ€ข Internet connection for download") + print() + + if not self.ask_user("Continue with automatic installation?"): + print("Installation cancelled. Please install manually:") + print("pip install MetaTrader5") + return False + + if not self.install_mt5_library(): + print("โŒ Automatic installation failed.") + print("Try manual installation:") + print("pip install MetaTrader5") + return False + + # Verify installation worked + if not self.check_mt5_library(): + print("โŒ Library installation verification failed") + return False + + # MT5 Platform check + self.check_mt5_installation() + + # Environment configuration + if not self.create_env_template(): + return False + + # Create test script + self.create_download_test() + + # Final instructions + print("\n" + "="*60) + print("๐ŸŽ‰ MT5 Integration Installed!") + print("="*60) + print() + print("Next steps:") + print("1. ๐Ÿ“ Edit your .env file with MT5 credentials") + print("2. ๐Ÿฆ Launch MT5 and login (demo account recommended)") + print("3. ๐Ÿงช Test connection: python test_mt5_connection.py") + print("4. ๐Ÿ“Š Download data: python lab/download_data.py") + print(" Or use the web interface: 'Download Data MT5' button") + print() + print("๐Ÿ“– Need help? Check MT5_SETUP_GUIDE.md") + print() + + return True + + def ask_user(self, question): + """Ask for user confirmation""" + while True: + response = input(f"{question} (y/n): ").lower().strip() + if response in ['y', 'yes']: + return True + elif response in ['n', 'no']: + return False + print("Please enter 'y' or 'n'") + +if __name__ == "__main__": + installer = MT5IntegrationInstaller() + + try: + success = installer.main() + sys.exit(0 if success else 1) + except KeyboardInterrupt: + print("\n\nInstallation cancelled by user.") + sys.exit(1) + except Exception as e: + print(f"\nโŒ Installation failed with error: {e}") + sys.exit(1) diff --git a/last_broker.json b/last_broker.json index b294d4a..024a569 100644 --- a/last_broker.json +++ b/last_broker.json @@ -1,5 +1,5 @@ { "broker": "FBS-Demo", "company": "FBS Markets Inc.", - "last_check": "2025-09-24T08:49:46.163195" + "last_check": "2025-09-24T10:46:19.830283" } \ No newline at end of file diff --git a/static/js/backtesting.js b/static/js/backtesting.js index e0df544..bfce73e 100644 --- a/static/js/backtesting.js +++ b/static/js/backtesting.js @@ -9,6 +9,7 @@ document.addEventListener('DOMContentLoaded', () => { const loadingSpinner = document.getElementById('loading-spinner'); let equityChart = null; // Variabel untuk menyimpan instance grafik const resultsLog = document.getElementById('results-log'); + const downloadBtn = document.getElementById('download-data-btn'); // Muat strategi ke dropdown async function loadStrategies() { @@ -241,5 +242,43 @@ document.addEventListener('DOMContentLoaded', () => { }); } + // Handle data download + downloadBtn.addEventListener('click', async () => { + if (!confirm("This will download historical market data from MT5.\n\nRequirements:\nโ€ข MT5 Terminal must be running\nโ€ข MT5 Python library must be available\nโ€ข Account credentials in .env file\n\nThis may take several minutes. Continue?")) { + return; + } + + const originalText = downloadBtn.innerHTML; + downloadBtn.disabled = true; + downloadBtn.innerHTML = 'Downloading...'; + + try { + const response = await fetch('/api/download-data', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + + const result = await response.json(); + + if (response.ok) { + if (result.success) { + alert(`โœ… Download completed successfully!\n\nDownloaded: ${result.downloaded_files.length} files\nFailed: ${result.failed_count}\n\nFiles saved to 'lab/backtest_data/' directory.`); + } else { + alert(`โŒ Download failed: ${result.error}`); + } + } else { + alert(`โŒ Download error: ${result.error}`); + } + } catch (err) { + console.error("Download failed:", err); + alert('โŒ Failed to connect to server for data download.'); + } finally { + downloadBtn.disabled = false; + downloadBtn.innerHTML = originalText; + } + }); + loadStrategies(); }); diff --git a/static/js/bot_detail.js b/static/js/bot_detail.js index ec50081..e38eb06 100644 --- a/static/js/bot_detail.js +++ b/static/js/bot_detail.js @@ -134,12 +134,22 @@ async function fetchAndDisplayAnalysis() { } // --- Pusat Kontrol --- - // Panggil semua fungsi sekali saat halaman dimuat untuk data awal - fetchBotDetails(); // Ambil parameter bot (hanya sekali) - fetchBotHistory(); // Ambil riwayat awal - fetchAndDisplayAnalysis(); // Ambil analisis awal - - // Atur interval refresh untuk data yang dinamis - setInterval(fetchAndDisplayAnalysis, 5000); // Refresh analisis setiap 5 detik - setInterval(fetchBotHistory, 10000); // Refresh riwayat setiap 10 detik + async function initializePage() { + // Ambil detail bot dulu untuk menentukan interval + await fetchBotDetails(); + + // Tentukan interval berdasarkan status bot + const analysisInterval = botData && botData.status === 'Aktif' ? 5000 : 30000; // 5s untuk aktif, 30s untuk inactive + + // Panggil fungsi lainnya untuk data awal + fetchBotHistory(); + fetchAndDisplayAnalysis(); + + // Atur interval refresh untuk data yang dinamis + setInterval(fetchAndDisplayAnalysis, analysisInterval); + setInterval(fetchBotHistory, 10000); // Refresh riwayat setiap 10 detik + } + + // Inisialisasi halaman + initializePage(); }); diff --git a/static/js/history.js b/static/js/history.js index 8946fb4..0d98951 100644 --- a/static/js/history.js +++ b/static/js/history.js @@ -2,6 +2,8 @@ document.addEventListener('DOMContentLoaded', function() { const historyTableBody = document.getElementById('history-table-body'); + let historyData = []; + let currentSort = { column: null, direction: 'asc' }; const formatTimestamp = (timestampInSeconds) => { const date = new Date(timestampInSeconds * 1000); @@ -11,36 +13,72 @@ document.addEventListener('DOMContentLoaded', function() { }); }; + const renderTable = (data) => { + historyTableBody.innerHTML = ''; + + if (data.length === 0) { + historyTableBody.innerHTML = 'Tidak ada riwayat transaksi ditemukan.'; + return; + } + + data.forEach(deal => { + const profitClass = deal.profit >= 0 ? 'text-green-600' : 'text-red-600'; + const dealType = deal.type === 0 ? 'BUY' : 'SELL'; // 0: BUY, 1: SELL + + const row = ` + + ${deal.symbol} + ${dealType} + ${deal.volume} + $${deal.profit.toFixed(2)} + ${formatTimestamp(deal.time)} + ${deal.magic} + + `; + historyTableBody.innerHTML += row; + }); + }; + + const sortTable = (column) => { + if (currentSort.column === column) { + currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc'; + } else { + currentSort.column = column; + currentSort.direction = 'asc'; + } + + // Update sort icons + document.getElementById('profit-sort-icon').innerHTML = column === 'profit' ? (currentSort.direction === 'asc' ? 'โ–ฒ' : 'โ–ผ') : ''; + document.getElementById('time-sort-icon').innerHTML = column === 'time' ? (currentSort.direction === 'asc' ? 'โ–ฒ' : 'โ–ผ') : ''; + + const sortedData = [...historyData].sort((a, b) => { + let aValue = a[column]; + let bValue = b[column]; + + if (column === 'profit' || column === 'time') { + aValue = parseFloat(aValue); + bValue = parseFloat(bValue); + } else if (column === 'volume' || column === 'magic') { + aValue = parseFloat(aValue); + bValue = parseFloat(bValue); + } + + if (aValue < bValue) return currentSort.direction === 'asc' ? -1 : 1; + if (aValue > bValue) return currentSort.direction === 'asc' ? 1 : -1; + return 0; + }); + + renderTable(sortedData); + }; + + window.sortTable = sortTable; + async function fetchGlobalHistory() { try { const response = await fetch('/api/history'); if (!response.ok) throw new Error('Gagal memuat data riwayat'); - const history = await response.json(); - - historyTableBody.innerHTML = ''; // Kosongkan pesan "Memuat..." - - if (history.length === 0) { - historyTableBody.innerHTML = 'Tidak ada riwayat transaksi ditemukan.'; - return; - } - - history.forEach(deal => { - const profitClass = deal.profit >= 0 ? 'text-green-600' : 'text-red-600'; - const dealType = deal.type === 0 ? 'BUY' : 'SELL'; // 0: BUY, 1: SELL - - const row = ` - - ${deal.symbol} - ${dealType} - ${deal.volume} - $${deal.profit.toFixed(2)} - ${formatTimestamp(deal.time)} - ${deal.magic} - - `; - historyTableBody.innerHTML += row; - }); - + historyData = await response.json(); + renderTable(historyData); } catch (error) { console.error('Error fetching global history:', error); historyTableBody.innerHTML = `Gagal memuat riwayat: ${error.message}`; diff --git a/static/js/i18n.js b/static/js/i18n.js new file mode 100644 index 0000000..e21841b --- /dev/null +++ b/static/js/i18n.js @@ -0,0 +1,338 @@ +/** + * QuantumBotX Internationalization (i18n) System + * Global language support across the entire application + */ + +// Translation dictionary for all app languages +window.QuantumBotXI18n = { + translations: { + id: { + // Navigation & Common + "nav.dashboard": "Dasbor", + "nav.bots": "Bot Trading", + "nav.backtest": "Backtester", + "nav.history": "Riwayat", + "nav.settings": "Pengaturan", + "nav.logout": "Keluar", + + // Dashboard + "dashboard.title": "Dasbor QuantumBotX", + "dashboard.welcome": "Selamat Datang", + "dashboard.total_bots": "Total Bot", + "dashboard.active_bots": "Bot Aktif", + "dashboard.inactive_bots": "Bot Tidak Aktif", + "dashboard.total_profit": "Total Profit", + "dashboard.today_pnl": "PnL Hari Ini", + "dashboard.create_bot": "Buat Bot Baru", + "dashboard.view_details": "Lihat Detail", + + // Bot Status + "status.active": "Aktif", + "status.inactive": "Dijeda", + "status.error": "Error", + "status.paused": "Dijeda", + + // Action Buttons + "action.start": "Jalankan", + "action.stop": "Hentikan", + "action.edit": "Edit", + "action.delete": "Hapus", + "action.view": "Lihat", + "action.analyze": "Analisis", + + // Form Labels & Messages + "label.name": "Nama", + "label.market": "Pasar", + "label.strategy": "Strategi", + "label.status": "Status", + "label.profit": "Profit", + "label.trades": "Jumlah Trade", + "label.win_rate": "Win Rate", + + "msg.loading": "Memuat...", + "msg.no_data": "Tidak ada data", + "msg.success": "Berhasil", + "msg.error": "Error", + "msg.confirm": "Apakah Anda yakin?", + + // Time & Date + "time.today": "Hari Ini", + "time.yesterday": "Kemarin", + "time.week": "Minggu Ini", + "time.month": "Bulan Ini", + + // Error Messages + "error.connection": "Gagal terhubung ke server", + "error.loading": "Gagal memuat data", + "error.save": "Gagal menyimpan perubahan", + + // AI Mentor + "mentor.greeting": "Halo, Teman Trader!", + "mentor.welcome": "Selamat datang di sistem trading AI saya", + + // Units & Currencies + "currency.usd": "USD", + "currency.idr": "IDR", + "currency.percentage": "%", + + // Settings + "settings.title": "Pengaturan", + "settings.language": "Bahasa", + "settings.theme": "Tema", + "settings.save": "Simpan Perubahan" + + }, + en: { + // Navigation & Common + "nav.dashboard": "Dashboard", + "nav.bots": "Trading Bots", + "nav.backtest": "Backtester", + "nav.history": "History", + "nav.settings": "Settings", + "nav.logout": "Logout", + + // Dashboard + "dashboard.title": "QuantumBotX Dashboard", + "dashboard.welcome": "Welcome", + "dashboard.total_bots": "Total Bots", + "dashboard.active_bots": "Active Bots", + "dashboard.inactive_bots": "Inactive Bots", + "dashboard.total_profit": "Total Profit", + "dashboard.today_pnl": "Today's P&L", + "dashboard.create_bot": "Create New Bot", + "dashboard.view_details": "View Details", + + // Bot Status + "status.active": "Active", + "status.inactive": "Inactive", + "status.error": "Error", + "status.paused": "Paused", + + // Action Buttons + "action.start": "Start", + "action.stop": "Stop", + "action.edit": "Edit", + "action.delete": "Delete", + "action.view": "View", + "action.analyze": "Analyze", + + // Form Labels & Messages + "label.name": "Name", + "label.market": "Market", + "label.strategy": "Strategy", + "label.status": "Status", + "label.profit": "Profit", + "label.trades": "Trades", + "label.win_rate": "Win Rate", + + "msg.loading": "Loading...", + "msg.no_data": "No data available", + "msg.success": "Success", + "msg.error": "Error", + "msg.confirm": "Are you sure?", + + // Time & Date + "time.today": "Today", + "time.yesterday": "Yesterday", + "time.week": "This Week", + "time.month": "This Month", + + // Error Messages + "error.connection": "Failed to connect to server", + "error.loading": "Failed to load data", + "error.save": "Failed to save changes", + + // AI Mentor + "mentor.greeting": "Hello, Trading Friend!", + "mentor.welcome": "Welcome to my AI trading system", + + // Units & Currencies + "currency.usd": "USD", + "currency.idr": "IDR", + "currency.percentage": "%", + + // Settings + "settings.title": "Settings", + "settings.language": "Language", + "settings.theme": "Theme", + "settings.save": "Save Changes" + } + }, + + // Current language + currentLang: localStorage.getItem('quantumBotX_language') || 'id', + + // Initialize i18n system + init: function() { + this.loadLanguage(); + this.createLanguageSwitcher(); + this.applyTranslations(); + }, + + // Load saved language preference + loadLanguage: function() { + const saved = localStorage.getItem('quantumBotX_language'); + if (saved && this.translations[saved]) { + this.currentLang = saved; + } + }, + + // Create global language switcher (can be embedded anywhere) + createLanguageSwitcher: function() { + // Check if already exists + if (document.getElementById('global-lang-switcher')) return; + + const switcher = document.createElement('div'); + switcher.id = 'global-lang-switcher'; + switcher.className = 'fixed top-4 right-4 z-50 flex items-center space-x-2 bg-white rounded-lg shadow-lg border p-1'; + + switcher.innerHTML = ` + + + `; + + // Add event listeners + switcher.querySelectorAll('.lang-btn').forEach(btn => { + btn.addEventListener('click', () => { + const newLang = btn.dataset.lang; + this.setLanguage(newLang); + }); + }); + + // Insert into page (after body loads) + document.addEventListener('DOMContentLoaded', () => { + document.body.appendChild(switcher); + }); + }, + + // Set active language + setLanguage: function(lang) { + if (!this.translations[lang]) { + console.warn(`Language '${lang}' not available`); + return; + } + + this.currentLang = lang; + localStorage.setItem('quantumBotX_language', lang); + + // Update switcher buttons + const switcher = document.getElementById('global-lang-switcher'); + if (switcher) { + switcher.querySelectorAll('.lang-btn').forEach(btn => { + const isActive = btn.dataset.lang === lang; + btn.className = `lang-btn px-3 py-1 rounded text-sm ${isActive ? 'bg-blue-500 text-white' : 'text-gray-600 hover:bg-gray-100'}`; + }); + } + + this.applyTranslations(); + this.onLanguageChange(lang); + }, + + // Get translated text + t: function(key, fallback = null) { + const translation = this.translations[this.currentLang]?.[key]; + if (translation) return translation; + + // Fallback to English if available + if (this.currentLang !== 'en' && this.translations.en?.[key]) { + return this.translations.en[key]; + } + + // Use fallback or return key + return fallback || key; + }, + + // Apply translations to all elements with data-i18n attribute + applyTranslations: function() { + // Elements with data-i18n attribute + document.querySelectorAll('[data-i18n]').forEach(element => { + const key = element.getAttribute('data-i18n'); + const translation = this.t(key); + + // Different element types handle text differently + if (element.tagName === 'INPUT') { + if (element.type === 'placeholder') { + element.placeholder = translation; + } + } else if (element.tagName === 'OPTION') { + element.textContent = translation; + } else { + element.textContent = translation; + } + }); + + // Title attributes + document.querySelectorAll('[data-i18n-title]').forEach(element => { + const key = element.getAttribute('data-i18n-title'); + element.title = this.t(key); + }); + + // Placeholder attributes + document.querySelectorAll('[data-i18n-placeholder]').forEach(element => { + const key = element.getAttribute('data-i18n-placeholder'); + element.placeholder = this.t(key); + }); + }, + + // Callback when language changes + onLanguageChange: function(newLang) { + // Update page title if it contains translatable text + const titleKey = document.documentElement.getAttribute('data-page-title'); + if (titleKey) { + document.title = this.t(titleKey); + } + + // Trigger custom event for pages to handle + const event = new CustomEvent('languageChanged', { detail: { language: newLang } }); + document.dispatchEvent(event); + + // Show feedback + this.showLanguageChangeFeedback(newLang); + }, + + // Show brief feedback when language changes + showLanguageChangeFeedback: function(lang) { + const langName = lang === 'id' ? 'Indonesia' : 'English'; + const feedback = document.createElement('div'); + feedback.className = 'fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg z-50 transition-opacity'; + feedback.textContent = `Language: ${langName}`; + + document.body.appendChild(feedback); + + // Auto remove after 2 seconds + setTimeout(() => { + feedback.style.opacity = '0'; + setTimeout(() => feedback.remove(), 300); + }, 2000); + }, + + // Add new translation key dynamically + addTranslation: function(lang, key, value) { + if (!this.translations[lang]) { + this.translations[lang] = {}; + } + this.translations[lang][key] = value; + }, + + // Get current language + getCurrentLanguage: function() { + return this.currentLang; + }, + + // Check if language is available + isLanguageAvailable: function(lang) { + return Boolean(this.translations[lang]); + } +}; + +// Initialize when DOM loads +document.addEventListener('DOMContentLoaded', function() { + window.QuantumBotXI18n.init(); +}); + +// Export for module use (optional) +if (typeof module !== 'undefined' && module.exports) { + module.exports = window.QuantumBotXI18n; +} diff --git a/static/js/settings.js b/static/js/settings.js index b7c498d..1cedda2 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -1,4 +1,172 @@ - // Toggle sidebar - document.getElementById('sidebar-toggle').addEventListener('click', function() { +document.addEventListener('DOMContentLoaded', function() { + // Toggle sidebar + const sidebarToggle = document.getElementById('sidebar-toggle'); + if (sidebarToggle) { + sidebarToggle.addEventListener('click', function() { document.getElementById('sidebar').classList.toggle('collapsed'); - }); \ No newline at end of file + }); + } + + // Language switching functionality + const languageSelect = document.getElementById('language-select'); + const savePreferencesBtn = document.getElementById('save-preferences-btn'); + + // Translation dictionary + const translations = { + id: { + title: 'Pengaturan', + profileTitle: 'Profil', + fullNameLabel: 'Nama Lengkap', + emailLabel: 'Alamat Email', + saveProfileBtn: 'Simpan Perubahan', + preferencesTitle: 'Preferensi', + languageLabel: 'Bahasa', + themeLabel: 'Tema', + lightTheme: 'Terang', + darkTheme: 'Gelap (Segera Hadir)', + savePreferencesBtn: 'Simpan Preferensi', + apiKeysTitle: 'API Keys Bursa', + apiInfoText: 'API Keys akan digunakan oleh versi QuantumBotX berikutnya untuk mengakses broker non-MT5.', + apiPlaceholderText: 'Fitur ini akan tersedia di QuantumBotX API versi mendatang.', + quickSettingsTitle: 'Pengaturan Cepat', + notificationsLabel: 'Notifikasi Email', + autoUpdateLabel: 'Update Otomatis Strategi', + demoModeLabel: 'Mode Demo' + }, + en: { + title: 'Settings', + profileTitle: 'Profile', + fullNameLabel: 'Full Name', + emailLabel: 'Email Address', + saveProfileBtn: 'Save Changes', + preferencesTitle: 'Preferences', + languageLabel: 'Language', + themeLabel: 'Theme', + lightTheme: 'Light', + darkTheme: 'Dark (Coming Soon)', + savePreferencesBtn: 'Save Preferences', + apiKeysTitle: 'Broker API Keys', + apiInfoText: 'API Keys will be used by the upcoming QuantumBotX API version to access non-MT5 brokers.', + apiPlaceholderText: 'This feature will be available in the upcoming QuantumBotX API version.', + quickSettingsTitle: 'Quick Settings', + notificationsLabel: 'Email Notifications', + autoUpdateLabel: 'Auto Strategy Updates', + demoModeLabel: 'Demo Mode' + } + }; + + // Get user language preference from localStorage, default to 'id' + let currentLang = localStorage.getItem('quantumBotX_language') || 'id'; + + // Set initial language + setLanguage(currentLang); + + // Language change event + if (languageSelect) { + languageSelect.value = currentLang; + languageSelect.addEventListener('change', function() { + currentLang = this.value; + setLanguage(currentLang); + }); + } + + // Save preferences + if (savePreferencesBtn) { + savePreferencesBtn.addEventListener('click', function() { + // Save language preference + localStorage.setItem('quantumBotX_language', currentLang); + + // Save other preferences (theme, etc.) + const theme = document.getElementById('theme-select').value; + localStorage.setItem('quantumBotX_theme', theme); + + // Auto-update checkbox + const autoUpdate = document.getElementById('auto-update').checked; + localStorage.setItem('quantumBotX_autoUpdate', autoUpdate); + + // Notifications checkbox + const notifications = document.getElementById('email-notifications').checked; + localStorage.setItem('quantumBotX_notifications', notifications); + + // Demo mode checkbox + const demoMode = document.getElementById('demo-mode').checked; + localStorage.setItem('quantumBotX_demoMode', demoMode); + + // Show success message + alert('Preferences saved successfully!'); + + // If language changed, update the page title + if (currentLang === 'en') { + document.title = 'Settings - QuantumBotX'; + } else { + document.title = 'Pengaturan - QuantumBotX'; + } + }); + } + + // Load saved preferences on page load + loadPreferences(); + + function setLanguage(lang) { + const translation = translations[lang]; + if (!translation) return; + + // Update page title + const titleElement = document.querySelector('h2'); + if (titleElement && titleElement.textContent.includes('Pengaturan')) { + titleElement.textContent = translation.title; + } + + // Update all translatable elements + Object.keys(translation).forEach(key => { + const element = document.getElementById(key); + if (element) { + element.textContent = translation[key]; + } + }); + + // Update theme options + const themeSelect = document.getElementById('theme-select'); + if (themeSelect && themeSelect.options.length >= 2) { + themeSelect.options[0].text = translation.lightTheme; + themeSelect.options[1].text = translation.darkTheme; + } + } + + function loadPreferences() { + // Load theme preference + const savedTheme = localStorage.getItem('quantumBotX_theme') || 'light'; + const themeSelect = document.getElementById('theme-select'); + if (themeSelect) themeSelect.value = savedTheme; + + // Load other checkbox preferences + const autoUpdate = localStorage.getItem('quantumBotX_autoUpdate') === 'true'; + const autoUpdateCheckbox = document.getElementById('auto-update'); + if (autoUpdateCheckbox) autoUpdateCheckbox.checked = autoUpdate; + + const notifications = localStorage.getItem('quantumBotX_notifications') === 'true'; + const notificationsCheckbox = document.getElementById('email-notifications'); + if (notificationsCheckbox) notificationsCheckbox.checked = notifications; + + const demoMode = localStorage.getItem('quantumBotX_demoMode') !== 'false'; // Default true + const demoModeCheckbox = document.getElementById('demo-mode'); + if (demoModeCheckbox) demoModeCheckbox.checked = demoMode; + } + + // Profile save functionality (placeholder) + const saveProfileBtn = document.getElementById('save-profile-btn'); + if (saveProfileBtn) { + saveProfileBtn.addEventListener('click', function() { + const fullName = document.getElementById('full-name-input').value; + localStorage.setItem('quantumBotX_fullName', fullName); + alert(currentLang === 'id' ? 'Profil berhasil disimpan!' : 'Profile saved successfully!'); + }); + } + + // Load saved profile data + const savedName = localStorage.getItem('quantumBotX_fullName'); + if (savedName) { + const nameInput = document.getElementById('full-name-input'); + if (nameInput) nameInput.value = savedName; + } +}); diff --git a/static/js/trading_bots.js b/static/js/trading_bots.js index 2c69771..1ddcff2 100644 --- a/static/js/trading_bots.js +++ b/static/js/trading_bots.js @@ -56,7 +56,15 @@ document.addEventListener('DOMContentLoaded', function() { async function fetchBots() { try { const response = await fetch('/api/bots'); - const bots = await response.json(); + let bots = await response.json(); + + // Sort bots: Active bots (status 'Aktif') first, then inactive + bots.sort((a, b) => { + if (a.status === 'Aktif' && b.status !== 'Aktif') return -1; + if (a.status !== 'Aktif' && b.status === 'Aktif') return 1; + return a.name.localeCompare(b.name); // Secondary sort by name + }); + tableBody.innerHTML = ''; // Kosongkan tabel sebelum mengisi if (bots.length === 0) { @@ -376,4 +384,4 @@ document.addEventListener('DOMContentLoaded', function() { loadStrategies(); // Muat strategi saat halaman pertama kali dibuka fetchBots(); // Ambil data bot saat halaman pertama kali dibuka setInterval(fetchBots, 10000); // Refresh data bot setiap 10 detik -}); \ No newline at end of file +}); diff --git a/templates/backtesting.html b/templates/backtesting.html index 92296cc..4c6daa7 100644 --- a/templates/backtesting.html +++ b/templates/backtesting.html @@ -6,9 +6,14 @@ {% block content %}

Strategy Backtester

- - Lihat Riwayat - +
+ + + Lihat Riwayat + +
@@ -96,4 +101,4 @@ {% block scripts %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/base.html b/templates/base.html index 44abd48..030968a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -34,20 +34,20 @@
@@ -86,6 +86,8 @@ + + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/settings.html b/templates/settings.html index f1761f9..f7939df 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -1,29 +1,93 @@ {% extends "base.html" %} -{% block title %}Settings{% endblock %} +{% block title %}Pengaturan{% endblock %} {% block content %}

Pengaturan

-

Profil

+

Profil

- - + +
- - + +
- +
+
-

API Keys Bursa

- +

Preferensi

+
+
+ + +

Application language settings

+
+
+ + +
+ +
+
+ +
+

API Keys Bursa

+
+
+
+
+ +
+
+

+ API Keys akan digunakan oleh versi QuantumBotX berikutnya untuk mengakses broker non-MT5. +

+
+
+
+
+ Fitur ini akan tersedia di QuantumBotX API versi mendatang. +
+
+
+
+ +
+
+

Pengaturan Cepat

+
+
+ Notifikasi Email + +
+
+ Update Otomatis Strategi + +
+
+ Mode Demo + +
+
+
+ Versi: 2.0.0
+ Terakhir Update: September 2025 +
+
@@ -31,4 +95,4 @@ {% block scripts %} -{% endblock %} \ No newline at end of file +{% endblock %}