mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-27 18:57:47 +00:00
feat: add i18n support and prepare for Vercel deployment
- Streamlined .env.example to include only essential Flask and MT5 configs for production environments - Added .vercel directory to .gitignore for clean Vercel deployments - Enabled internationalization by adding data-i18n attributes to strategy switcher UI elements - Updated MT5 setup guide and roadmap documentation for clarity and current focus This change simplifies configuration for server deployment while enhancing UI accessibility across languages.
This commit is contained in:
+9
-31
@@ -1,34 +1,12 @@
|
||||
# Flask Configuration
|
||||
FLASK_APP=run.py
|
||||
FLASK_ENV=development
|
||||
FLASK_DEBUG=True
|
||||
FLASK_DEBUG=False
|
||||
FLASK_HOST=127.0.0.1
|
||||
FLASK_PORT=5000
|
||||
|
||||
# Server Configuration
|
||||
HOST=0.0.0.0
|
||||
PORT=5000
|
||||
# MT5 Configuration (required for local development)
|
||||
MT5_LOGIN=your_mt5_account_number
|
||||
MT5_PASSWORD=your_mt5_password
|
||||
MT5_SERVER=your_mt5_server
|
||||
|
||||
# Database Configuration (SQLite default)
|
||||
DATABASE_URL=sqlite:///database.db
|
||||
|
||||
# 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
|
||||
# Skip MT5 initialization in deployment environments (Vercel, etc.)
|
||||
SKIP_MT5_INIT=0
|
||||
|
||||
@@ -90,3 +90,5 @@ DESKTOP_DEPLOYMENT.md
|
||||
INVESTMENT_RETURN.md
|
||||
PAYMENT_SETUP.md
|
||||
STRATEGY_IDEAS.md
|
||||
|
||||
.vercel
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** eslint-disable markdown/fenced-code-language */
|
||||
# 🚀 QuantumBotX MT5 Integration Guide
|
||||
|
||||
> **Get Historical Market Data for Advanced Backtesting**
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
# QuantumBotX Windows Packaging Guide
|
||||
|
||||
This guide explains how to package your QuantumBotX trading application into a Windows installer for distribution to non-technical users.
|
||||
|
||||
## 🎯 What This Packaging Solution Provides
|
||||
|
||||
✅ **Single EXE Installer** - Professional Windows installer
|
||||
✅ **One-Click Installation** - Simple for end users
|
||||
✅ **Desktop Shortcuts** - Easy application access
|
||||
✅ **Uninstaller** - Clean removal capability
|
||||
✅ **Setup Wizard** - Automated first-time setup
|
||||
✅ **User-Friendly Scripts** - Simple startup process
|
||||
✅ **Comprehensive Documentation** - Clear instructions for users
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
### For Building the Package
|
||||
1. **Python 3.8+** (already installed)
|
||||
2. **PyInstaller** (already installed via this guide)
|
||||
3. **NSIS (Optional)** - For creating the installer EXE
|
||||
- Download from: https://nsis.sourceforge.io/Download
|
||||
- Install and ensure `makensis` is in your PATH
|
||||
|
||||
### For End Users
|
||||
1. **Windows 7+** (64-bit recommended)
|
||||
2. **MetaTrader 5** - Must be installed separately
|
||||
3. **Internet Connection** - For initial setup
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Option 1: Build Everything (Recommended)
|
||||
```bash
|
||||
python build_installer.py
|
||||
```
|
||||
|
||||
### Option 2: Manual Build Process
|
||||
```bash
|
||||
# 1. Build with PyInstaller
|
||||
pyinstaller --clean quantumbotx.spec
|
||||
|
||||
# 2. Create portable version (optional)
|
||||
python -c "import zipfile; zipf=zipfile.ZipFile('QuantumBotX-Portable.zip','w',8); [zipf.write(f,f) for d in ['dist/QuantumBotX','.'] for f in [os.path.join(r,d) for r,_,fs in os.walk(d) for f in fs]]"
|
||||
|
||||
# 3. Create installer (requires NSIS)
|
||||
makensis installer.nsi
|
||||
```
|
||||
|
||||
## 📁 Generated Files
|
||||
|
||||
After successful build, you'll have:
|
||||
|
||||
```txt
|
||||
QuantumBotX-Installer.exe # Main Windows installer
|
||||
QuantumBotX-Portable.zip # Portable version (alternative)
|
||||
dist/QuantumBotX/ # PyInstaller output (for troubleshooting)
|
||||
```
|
||||
|
||||
## 🎮 For End Users
|
||||
|
||||
### Installation Process
|
||||
1. **Download** `QuantumBotX-Installer.exe`
|
||||
2. **Run** the installer (requires admin privileges)
|
||||
3. **Follow** the setup wizard
|
||||
4. **Launch** from desktop shortcut or start menu
|
||||
|
||||
### Daily Usage
|
||||
1. **Start MetaTrader 5** first
|
||||
2. **Launch QuantumBotX** via desktop shortcut or start menu
|
||||
3. **Open browser** to http://127.0.0.1:5000
|
||||
4. **Configure settings** if needed
|
||||
|
||||
## 🔧 Configuration Files
|
||||
|
||||
The installer includes these configuration files:
|
||||
|
||||
- **`.env.example`** - Template for environment variables
|
||||
- **`start.bat`** - Windows startup script
|
||||
- **`setup_quantumbotx.py`** - Setup wizard for first run
|
||||
- **`QUICK_START_GUIDE.md`** - User instructions
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### Build Issues
|
||||
|
||||
**PyInstaller fails:**
|
||||
```bash
|
||||
# Clean and rebuild
|
||||
pyinstaller --clean quantumbotx.spec
|
||||
```
|
||||
|
||||
**NSIS not found:**
|
||||
- Install NSIS from https://nsis.sourceforge.io/
|
||||
- Or use the portable version instead
|
||||
|
||||
**Missing dependencies:**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Runtime Issues
|
||||
|
||||
**Application won't start:**
|
||||
- Check if MetaTrader 5 is running
|
||||
- Verify `.env` file has correct credentials
|
||||
- Check Windows Event Viewer for errors
|
||||
|
||||
**Port already in use:**
|
||||
- Close other applications using port 5000
|
||||
- Or modify `FLASK_PORT` in `.env` file
|
||||
|
||||
**MetaTrader 5 connection fails:**
|
||||
- Verify MT5 credentials in `.env`
|
||||
- Ensure MT5 is running and logged in
|
||||
- Check MT5 terminal for connection status
|
||||
|
||||
## 📦 Distribution
|
||||
|
||||
### For Technical Users
|
||||
- Share `QuantumBotX-Installer.exe` for full installation
|
||||
- Or share `QuantumBotX-Portable.zip` for manual installation
|
||||
|
||||
### For Non-Technical Users
|
||||
1. **Share the installer** `QuantumBotX-Installer.exe`
|
||||
2. **Provide simple instructions:**
|
||||
- Double-click to install
|
||||
- Follow the setup wizard
|
||||
- Use desktop shortcut to launch
|
||||
- Ensure MetaTrader 5 is running
|
||||
|
||||
### System Requirements for End Users
|
||||
- **OS:** Windows 7 SP1+ (64-bit recommended)
|
||||
- **RAM:** 4GB minimum, 8GB recommended
|
||||
- **Storage:** 500MB free space
|
||||
- **Network:** Internet connection for initial setup
|
||||
- **Software:** MetaTrader 5 (installed separately)
|
||||
|
||||
## 🔄 Updates and Maintenance
|
||||
|
||||
### Creating Updates
|
||||
1. **Increment version** in `installer.nsi`
|
||||
2. **Rebuild** using `python build_installer.py`
|
||||
3. **Test** on clean system
|
||||
4. **Distribute** new installer
|
||||
|
||||
### Uninstallation
|
||||
- Use Windows Add/Remove Programs
|
||||
- Or run `Uninstall.exe` from installation directory
|
||||
- Or use the uninstall shortcut in Start Menu
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
### Common User Questions
|
||||
|
||||
**"How do I configure my MT5 credentials?"**
|
||||
- Copy `.env.example` to `.env`
|
||||
- Edit `.env` with your MT5 account details
|
||||
- Restart the application
|
||||
|
||||
**"The application says MT5 is not connected"**
|
||||
- Ensure MetaTrader 5 is running
|
||||
- Check MT5 login credentials
|
||||
- Verify MT5 server settings
|
||||
|
||||
**"I can't access the web interface"**
|
||||
- Check if the application is running
|
||||
- Verify the URL: http://127.0.0.1:5000
|
||||
- Check firewall settings
|
||||
|
||||
## 🎯 Advanced Configuration
|
||||
|
||||
### Customizing the Installer
|
||||
Edit `installer.nsi` to:
|
||||
- Change installation directory
|
||||
- Modify shortcuts
|
||||
- Add custom messages
|
||||
- Include additional files
|
||||
|
||||
### Customizing PyInstaller
|
||||
Edit `quantumbotx.spec` to:
|
||||
- Add/remove files
|
||||
- Change executable properties
|
||||
- Modify hidden imports
|
||||
- Customize build options
|
||||
|
||||
## 📞 Getting Help
|
||||
|
||||
1. **Check the logs** in the `logs/` directory
|
||||
2. **Review** `QUICK_START_GUIDE.md`
|
||||
3. **Consult** `README.md` for technical details
|
||||
4. **Check** MetaTrader 5 documentation for connection issues
|
||||
|
||||
---
|
||||
|
||||
**🎉 Your application is now ready for distribution to non-technical users!**
|
||||
@@ -0,0 +1,47 @@
|
||||
# QuantumBotX - Quick Start Guide
|
||||
|
||||
## First Time Setup
|
||||
|
||||
1. **Install MetaTrader 5** (Required)
|
||||
- Download from: https://www.metatrader5.com/
|
||||
- Install and create a demo account
|
||||
- Keep MT5 running in the background
|
||||
- ⚠️ **IMPORTANT:** MetaTrader 5 must be running for QuantumBotX to work
|
||||
|
||||
2. **Configure Your Settings**
|
||||
- Copy `.env.example` to `.env`
|
||||
- Edit `.env` with your MT5 credentials:
|
||||
```ini
|
||||
MT5_LOGIN=your_account_number
|
||||
MT5_PASSWORD=your_password
|
||||
MT5_SERVER=your_server_name
|
||||
```
|
||||
|
||||
3. **Start the Application**
|
||||
- Double-click `start.bat` (Windows)
|
||||
- Open http://127.0.0.1:5000 in your browser
|
||||
|
||||
## ✅ System Requirements
|
||||
|
||||
- **Windows 7 SP1 or later** (64-bit recommended)
|
||||
- **MetaTrader 5** (must be installed separately)
|
||||
- **4GB RAM minimum** (8GB recommended)
|
||||
- **500MB free disk space**
|
||||
- **Internet connection** for initial setup
|
||||
- **❌ Python NOT required** (already bundled in the installer)
|
||||
|
||||
## Daily Use
|
||||
|
||||
1. Start MetaTrader 5 first
|
||||
2. Run `start.bat`
|
||||
3. Open your web browser to http://127.0.0.1:5000
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Make sure MetaTrader 5 is running
|
||||
- Check your .env file has correct credentials
|
||||
- If the app won't start, try running `python run.py` directly
|
||||
|
||||
## Support
|
||||
|
||||
If you need help, check the README.md file or contact support.
|
||||
+40
-206
@@ -1,218 +1,52 @@
|
||||
# 🚀 QuantumBotX Product Roadmap 2025-2026
|
||||
# 📋 QuantumBotX Development Roadmap
|
||||
|
||||
> **From Local MT5 Platform → Global Cloud Trading System**
|
||||
**👀 Stay Tuned for Exciting Updates!**
|
||||
|
||||
## 🎯 **What's Coming Next**
|
||||
|
||||
### **Q4 2025: Intelligence Enhancement**
|
||||
- **Advanced AI Features**: Enhanced strategy analysis with machine learning
|
||||
- **Real-time Notifications**: Telegram integration for trade alerts
|
||||
- **Portfolio Analytics**: Advanced performance dashboards
|
||||
- **Enterprise Features**: Multi-account management and compliance logging
|
||||
|
||||
### **Exciting New Project** 🚀
|
||||
We're developing **QuantumBotX API** - a revolutionary cloud-based trading platform that will give users unprecedented freedom:
|
||||
|
||||
> **"Trade anywhere, anytime, with any broker - no local installations required!"**
|
||||
|
||||
**QuantumBotX API will feature:**
|
||||
- 🌐 **Cloud-native architecture** - Run on any device, anywhere
|
||||
- 🔄 **Direct broker integration** - No intermediaries, pure API trading
|
||||
- 🌏 **Cross-broker support** - IC Markets, Pepperstone, and beyond
|
||||
- ⚡ **Real-time execution** - Ultra-low latency trade processing
|
||||
- 🎓 **Advanced education** - Built-in learning with community support
|
||||
|
||||
### **Timeline**
|
||||
- **Q4 2025**: Closed beta testing with select users
|
||||
- **Q1 2026**: Public beta launch with premium support
|
||||
- **Q2 2026**: Full global launch with subscription tiers
|
||||
|
||||
---
|
||||
|
||||
## 📍 **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
|
||||
## 🤝 **Community & Support**
|
||||
|
||||
**We're building more than software - we're building a trading community!**
|
||||
|
||||
- **Discord Community**: Join our growing trader community
|
||||
- **Educational Content**: Free trading courses and tutorials
|
||||
- **Open Source**: Contribute to the project and shape its future
|
||||
- **Mentorship Program**: One-on-one guidance for serious traders
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **Q4 2025: Stability & Market Penetration**
|
||||
## 🗺️ **Our Mission**
|
||||
|
||||
### **v2.1 - "Intelligence Enhancement"** (3 Months)
|
||||
**Empowering traders worldwide with safe, educational, and profitable algorithmic trading solutions.**
|
||||
|
||||
#### 🧠 **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
|
||||
*From local learning platform → Global trading ecosystem!* 🚀💫
|
||||
|
||||
---
|
||||
|
||||
## 🌟 **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* 🚀🔮
|
||||
**Roadmap Updated: September 2025**
|
||||
</content>
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import os
|
||||
from core import create_app
|
||||
|
||||
# Set environment to skip MT5 initialization on Vercel
|
||||
os.environ['SKIP_MT5_INIT'] = '1'
|
||||
|
||||
app = create_app()
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
QuantumBotX Windows Installer Builder
|
||||
Builds the complete installer package for distribution
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
def run_command(command, shell=True, cwd=None):
|
||||
"""Run a command and return the result."""
|
||||
try:
|
||||
print(f"Running: {command}")
|
||||
result = subprocess.run(command, shell=shell, cwd=cwd, capture_output=True, text=True)
|
||||
if result.stdout:
|
||||
print(result.stdout)
|
||||
if result.stderr:
|
||||
print(result.stderr, file=sys.stderr)
|
||||
return result.returncode == 0, result.stdout, result.stderr
|
||||
except Exception as e:
|
||||
return False, "", str(e)
|
||||
|
||||
def check_requirements():
|
||||
"""Check if all required tools are installed."""
|
||||
print("Checking requirements...")
|
||||
|
||||
# Check PyInstaller
|
||||
success, _, _ = run_command("pyinstaller --version")
|
||||
if not success:
|
||||
print("❌ PyInstaller not found. Installing...")
|
||||
run_command("pip install pyinstaller")
|
||||
|
||||
# Check NSIS (we'll assume it's installed or provide instructions)
|
||||
print("✓ PyInstaller found")
|
||||
|
||||
# Check if favicon exists for installer icon
|
||||
if not os.path.exists("static/favicon.ico"):
|
||||
print("⚠️ Warning: static/favicon.ico not found. Installer will use default icon.")
|
||||
|
||||
return True
|
||||
|
||||
def clean_previous_builds():
|
||||
"""Clean previous build artifacts."""
|
||||
print("Cleaning previous builds...")
|
||||
|
||||
directories_to_clean = [
|
||||
"build",
|
||||
"dist",
|
||||
"__pycache__",
|
||||
"*.spec~"
|
||||
]
|
||||
|
||||
for path in directories_to_clean:
|
||||
if os.path.exists(path):
|
||||
if os.path.isfile(path):
|
||||
os.remove(path)
|
||||
else:
|
||||
shutil.rmtree(path)
|
||||
print(f" Cleaned: {path}")
|
||||
|
||||
# Clean Python cache
|
||||
for root, dirs, files in os.walk("."):
|
||||
for dir_name in dirs:
|
||||
if dir_name == "__pycache__":
|
||||
pycache_path = os.path.join(root, dir_name)
|
||||
shutil.rmtree(pycache_path)
|
||||
print(f" Cleaned: {pycache_path}")
|
||||
|
||||
def build_with_pyinstaller():
|
||||
"""Build the application using PyInstaller."""
|
||||
print("Building with PyInstaller...")
|
||||
|
||||
# Build the executable
|
||||
success, stdout, stderr = run_command("pyinstaller --clean quantumbotx.spec")
|
||||
|
||||
if not success:
|
||||
print(f"❌ PyInstaller build failed: {stderr}")
|
||||
return False
|
||||
|
||||
print("✓ PyInstaller build completed successfully")
|
||||
return True
|
||||
|
||||
def create_installer():
|
||||
"""Create the Windows installer using NSIS."""
|
||||
print("Creating Windows installer...")
|
||||
|
||||
# Check if NSIS is installed
|
||||
success, _, _ = run_command("makensis /VERSION")
|
||||
if not success:
|
||||
print("❌ NSIS not found!")
|
||||
print("Please install NSIS from: https://nsis.sourceforge.io/Download")
|
||||
print("Or download from: https://nsis.sourceforge.io/Download")
|
||||
print()
|
||||
print("Alternative: You can manually install the application by:")
|
||||
print("1. Running the PyInstaller build")
|
||||
print("2. Copying the dist/QuantumBotX folder to the target computer")
|
||||
print("3. Running setup_quantumbotx.py on the target computer")
|
||||
return False
|
||||
|
||||
# Create the installer
|
||||
success, stdout, stderr = run_command("makensis installer.nsi")
|
||||
|
||||
if not success:
|
||||
print(f"❌ NSIS build failed: {stderr}")
|
||||
return False
|
||||
|
||||
print("✓ Windows installer created successfully")
|
||||
return True
|
||||
|
||||
def create_portable_package():
|
||||
"""Create a portable ZIP package as alternative."""
|
||||
print("Creating portable ZIP package...")
|
||||
|
||||
try:
|
||||
import zipfile
|
||||
|
||||
# Create portable package
|
||||
portable_name = "QuantumBotX-Portable.zip"
|
||||
|
||||
with zipfile.ZipFile(portable_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
# Add the main executable and supporting files
|
||||
dist_path = Path("dist/QuantumBotX")
|
||||
if dist_path.exists():
|
||||
for file_path in dist_path.rglob("*"):
|
||||
if file_path.is_file():
|
||||
arcname = file_path.relative_to("dist")
|
||||
zipf.write(file_path, arcname)
|
||||
|
||||
# Add additional files
|
||||
additional_files = [
|
||||
"start.bat",
|
||||
"start.sh",
|
||||
"setup_quantumbotx.py",
|
||||
"requirements.txt",
|
||||
".env.example",
|
||||
"README.md",
|
||||
"QUICK_START_GUIDE.md",
|
||||
"MT5_SETUP_GUIDE.md"
|
||||
]
|
||||
|
||||
for file_name in additional_files:
|
||||
if os.path.exists(file_name):
|
||||
zipf.write(file_name, file_name)
|
||||
|
||||
print(f"✓ Portable package created: {portable_name}")
|
||||
return True
|
||||
|
||||
except ImportError:
|
||||
print("⚠️ zipfile not available, skipping portable package")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Error creating portable package: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main build function."""
|
||||
print("QuantumBotX Windows Installer Builder")
|
||||
print("====================================")
|
||||
print()
|
||||
|
||||
# Check requirements
|
||||
if not check_requirements():
|
||||
print("❌ Requirements check failed")
|
||||
input("Press Enter to exit...")
|
||||
return
|
||||
|
||||
# Clean previous builds
|
||||
clean_previous_builds()
|
||||
|
||||
# Build with PyInstaller
|
||||
if not build_with_pyinstaller():
|
||||
print("❌ PyInstaller build failed")
|
||||
input("Press Enter to exit...")
|
||||
return
|
||||
|
||||
# Create installer
|
||||
installer_created = create_installer()
|
||||
|
||||
# Create portable package as backup
|
||||
create_portable_package()
|
||||
|
||||
print()
|
||||
if installer_created:
|
||||
print("🎉 Build Complete!")
|
||||
print("==================")
|
||||
print("✓ Windows installer: QuantumBotX-Installer.exe")
|
||||
print("✓ Portable package: QuantumBotX-Portable.zip")
|
||||
print()
|
||||
print("Distribution files are ready in the current directory.")
|
||||
print()
|
||||
print("To test the installer:")
|
||||
print("1. Copy QuantumBotX-Installer.exe to a test computer")
|
||||
print("2. Run the installer")
|
||||
print("3. Follow the setup wizard")
|
||||
print()
|
||||
else:
|
||||
print("⚠️ Build Complete (Installer not available)")
|
||||
print("=============================================")
|
||||
print("✓ Application executable: dist/QuantumBotX/")
|
||||
print("✓ Portable package: QuantumBotX-Portable.zip")
|
||||
print()
|
||||
print("Since NSIS is not installed, you have these options:")
|
||||
print("1. Install NSIS and run this script again")
|
||||
print("2. Use the portable version (dist/QuantumBotX/)")
|
||||
print("3. Manually copy files to target computer")
|
||||
print()
|
||||
|
||||
print("Next steps for end users:")
|
||||
print("1. Install MetaTrader 5")
|
||||
print("2. Configure .env file with MT5 credentials")
|
||||
print("3. Run start.bat to launch the application")
|
||||
print()
|
||||
|
||||
input("Press Enter to exit...")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+164
-4
@@ -1,10 +1,13 @@
|
||||
# core/__init__.py
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import sqlite3
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from flask import Flask, render_template, send_from_directory
|
||||
from dotenv import load_dotenv
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
class RequestLogFilter(logging.Filter):
|
||||
"""Filter untuk menghilangkan noise dari terminal log."""
|
||||
@@ -58,6 +61,155 @@ class RequestLogFilter(logging.Filter):
|
||||
# Tampilkan semua request lainnya (termasuk GET yang error)
|
||||
return True
|
||||
|
||||
def init_database():
|
||||
"""Initialize database and create tables if they don't exist."""
|
||||
try:
|
||||
# Get the directory where the executable is located
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Running as PyInstaller bundle
|
||||
base_dir = os.path.dirname(sys.executable)
|
||||
db_path = os.path.join(base_dir, 'bots.db')
|
||||
else:
|
||||
# Running as script
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
db_path = os.path.join(base_dir, '..', '..', 'bots.db')
|
||||
|
||||
# Create connection
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Create users table
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
join_date DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
# Create bots table
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS bots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
market TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'Dijeda',
|
||||
lot_size REAL NOT NULL DEFAULT 0.01,
|
||||
sl_pips INTEGER NOT NULL DEFAULT 100,
|
||||
tp_pips INTEGER NOT NULL DEFAULT 200,
|
||||
timeframe TEXT NOT NULL DEFAULT 'H1',
|
||||
check_interval_seconds INTEGER NOT NULL DEFAULT 60,
|
||||
strategy TEXT NOT NULL,
|
||||
strategy_params TEXT,
|
||||
enable_strategy_switching INTEGER NOT NULL DEFAULT 0
|
||||
)
|
||||
''')
|
||||
|
||||
# Create trade_history table
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS trade_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
bot_id INTEGER NOT NULL,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
action TEXT NOT NULL,
|
||||
details TEXT,
|
||||
is_notification INTEGER NOT NULL DEFAULT 0,
|
||||
is_read INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (bot_id) REFERENCES bots (id) ON DELETE CASCADE
|
||||
)
|
||||
''')
|
||||
|
||||
# Create backtest_results table
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS backtest_results (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
strategy_name TEXT NOT NULL,
|
||||
data_filename TEXT NOT NULL,
|
||||
total_profit_usd REAL NOT NULL,
|
||||
total_trades INTEGER NOT NULL,
|
||||
win_rate_percent REAL NOT NULL,
|
||||
max_drawdown_percent REAL NOT NULL,
|
||||
wins INTEGER NOT NULL,
|
||||
losses INTEGER NOT NULL,
|
||||
equity_curve TEXT,
|
||||
trade_log TEXT,
|
||||
parameters TEXT
|
||||
)
|
||||
''')
|
||||
|
||||
# Create trading_sessions table (AI Mentor)
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS trading_sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_date DATE NOT NULL,
|
||||
user_id INTEGER DEFAULT 1,
|
||||
total_trades INTEGER NOT NULL DEFAULT 0,
|
||||
total_profit_loss REAL NOT NULL DEFAULT 0.0,
|
||||
emotions TEXT NOT NULL DEFAULT 'netral',
|
||||
market_conditions TEXT NOT NULL DEFAULT 'normal',
|
||||
personal_notes TEXT,
|
||||
risk_score INTEGER DEFAULT 5,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
)
|
||||
''')
|
||||
|
||||
# Create ai_mentor_reports table
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS ai_mentor_reports (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id INTEGER NOT NULL,
|
||||
trading_patterns_analysis TEXT,
|
||||
emotional_analysis TEXT,
|
||||
risk_management_score INTEGER,
|
||||
recommendations TEXT,
|
||||
motivation_message TEXT,
|
||||
language TEXT DEFAULT 'bahasa_indonesia',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (session_id) REFERENCES trading_sessions (id) ON DELETE CASCADE
|
||||
)
|
||||
''')
|
||||
|
||||
# Create daily_trading_data table
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS daily_trading_data (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id INTEGER NOT NULL,
|
||||
bot_id INTEGER NOT NULL,
|
||||
symbol TEXT NOT NULL,
|
||||
entry_time DATETIME,
|
||||
exit_time DATETIME,
|
||||
profit_loss REAL NOT NULL,
|
||||
lot_size REAL NOT NULL,
|
||||
stop_loss_used BOOLEAN DEFAULT 0,
|
||||
take_profit_used BOOLEAN DEFAULT 0,
|
||||
risk_percent REAL,
|
||||
strategy_used TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (session_id) REFERENCES trading_sessions (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (bot_id) REFERENCES bots (id) ON DELETE CASCADE
|
||||
)
|
||||
''')
|
||||
|
||||
# Check if default user exists
|
||||
cursor.execute('SELECT COUNT(*) FROM users')
|
||||
if cursor.fetchone()[0] == 0:
|
||||
# Insert default user
|
||||
default_password_hash = generate_password_hash('admin')
|
||||
cursor.execute(
|
||||
'INSERT INTO users (name, email, password_hash) VALUES (?, ?, ?)',
|
||||
('Admin User', 'admin@quantumbotx.com', default_password_hash)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"Database initialization failed: {e}")
|
||||
|
||||
# ============================
|
||||
# APPLICATION FACTORY FUNCTION
|
||||
# ============================
|
||||
@@ -66,13 +218,21 @@ def create_app():
|
||||
Membuat dan mengkonfigurasi instance aplikasi Flask.
|
||||
"""
|
||||
load_dotenv()
|
||||
|
||||
|
||||
app = Flask(
|
||||
__name__,
|
||||
__name__,
|
||||
instance_relative_config=True,
|
||||
template_folder='../templates',
|
||||
static_folder='../static'
|
||||
)
|
||||
)
|
||||
|
||||
# Initialize database on startup
|
||||
try:
|
||||
init_database()
|
||||
app.logger.info("Database initialized successfully")
|
||||
except Exception as e:
|
||||
app.logger.error(f"Failed to initialize database: {e}")
|
||||
# Don't crash the app, but log the error
|
||||
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key-here')
|
||||
|
||||
# Konfigurasi logging yang lebih bersih
|
||||
@@ -203,4 +363,4 @@ def create_app():
|
||||
return send_from_directory(os.path.join(app.root_path, 'static'),
|
||||
'favicon.ico', mimetype='image/vnd.microsoft.icon')
|
||||
|
||||
return app
|
||||
return app
|
||||
|
||||
+13
-4
@@ -1,15 +1,24 @@
|
||||
# core/db/connection.py
|
||||
import sqlite3
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Tentukan nama file database di satu tempat.
|
||||
DATABASE_FILENAME = 'bots.db'
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
DATABASE_PATH = os.path.join(BASE_DIR, '..', '..', DATABASE_FILENAME)
|
||||
|
||||
def get_db_connection():
|
||||
"""Membuat dan mengembalikan koneksi ke database SQLite."""
|
||||
conn = sqlite3.connect(DATABASE_PATH)
|
||||
# Get the directory where the executable is located
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Running as PyInstaller bundle
|
||||
base_dir = os.path.dirname(sys.executable)
|
||||
db_path = os.path.join(base_dir, DATABASE_FILENAME)
|
||||
else:
|
||||
# Running as script
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
db_path = os.path.join(BASE_DIR, '..', '..', DATABASE_FILENAME)
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
# Mengatur agar hasil query bisa diakses seperti dictionary
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
return conn
|
||||
|
||||
@@ -10,7 +10,6 @@ import os
|
||||
import sys
|
||||
import subprocess
|
||||
import platform
|
||||
import json
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
; QuantumBotX Windows Installer
|
||||
; This script creates a Windows installer for the QuantumBotX trading application
|
||||
|
||||
!include "MUI2.nsh"
|
||||
!include "FileFunc.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
|
||||
; General
|
||||
Name "QuantumBotX Trading Bot"
|
||||
OutFile "QuantumBotX-Installer.exe"
|
||||
Unicode True
|
||||
InstallDir "C:\QuantumBotX"
|
||||
InstallDirRegKey HKCU "Software\QuantumBotX" ""
|
||||
RequestExecutionLevel admin
|
||||
|
||||
; Modern UI Configuration
|
||||
!define MUI_ABORTWARNING
|
||||
!define MUI_ICON "static\favicon.ico"
|
||||
!define MUI_UNICON "static\favicon.ico"
|
||||
|
||||
; Pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_LICENSE "LICENSE.md"
|
||||
|
||||
; Custom prerequisites page
|
||||
Page custom PrerequisitesPage PrerequisitesPageLeave
|
||||
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_WELCOME
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
; Languages
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "Indonesian"
|
||||
|
||||
; Version Information
|
||||
VIProductVersion "2.0.0.0"
|
||||
VIAddVersionKey "ProductName" "QuantumBotX Trading Bot"
|
||||
VIAddVersionKey "CompanyName" "Chrisnov IT Solutions"
|
||||
VIAddVersionKey "FileVersion" "2.0.0.0"
|
||||
VIAddVersionKey "ProductVersion" "2.0.0.0"
|
||||
VIAddVersionKey "FileDescription" "Professional Trading Bot Application"
|
||||
VIAddVersionKey "LegalCopyright" "Copyright (c) 2025 Reynov Christian - Chrisnov IT Solutions"
|
||||
VIAddVersionKey "Contact" "contact@chrisnov.com"
|
||||
|
||||
Section "Install"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
; Stop any running instances
|
||||
DetailPrint "Stopping any running instances..."
|
||||
nsExec::Exec 'taskkill /f /im "QuantumBotX.exe"'
|
||||
|
||||
; Create installation directory
|
||||
CreateDirectory "$INSTDIR"
|
||||
|
||||
; Copy main files
|
||||
File "dist\QuantumBotX\QuantumBotX.exe"
|
||||
File /r "dist\QuantumBotX\_internal"
|
||||
File "start.bat"
|
||||
File "start.sh"
|
||||
File "setup_quantumbotx.py"
|
||||
File "requirements.txt"
|
||||
File ".env.example"
|
||||
File "README.md"
|
||||
File "QUICK_START_GUIDE.md"
|
||||
File "MT5_SETUP_GUIDE.md"
|
||||
File /r "templates"
|
||||
File /r "static"
|
||||
File /r "core"
|
||||
|
||||
; Create data directories
|
||||
CreateDirectory "$INSTDIR\logs"
|
||||
CreateDirectory "$INSTDIR\lab"
|
||||
CreateDirectory "$INSTDIR\testing"
|
||||
CreateDirectory "$INSTDIR\docs"
|
||||
|
||||
; Copy optional directories if they exist
|
||||
IfFileExists "docs\*.*" 0 +2
|
||||
File /r "docs"
|
||||
|
||||
IfFileExists "lab\*.*" 0 +2
|
||||
File /r "lab"
|
||||
|
||||
IfFileExists "testing\*.*" 0 +2
|
||||
File /r "testing"
|
||||
|
||||
; Create desktop shortcut
|
||||
CreateShortCut "$DESKTOP\QuantumBotX.lnk" "$INSTDIR\start.bat" "" "$INSTDIR\start.bat" 0
|
||||
|
||||
; Create start menu entries
|
||||
CreateDirectory "$SMPROGRAMS\QuantumBotX"
|
||||
CreateShortCut "$SMPROGRAMS\QuantumBotX\QuantumBotX.lnk" "$INSTDIR\start.bat" "" "$INSTDIR\start.bat" 0
|
||||
CreateShortCut "$SMPROGRAMS\QuantumBotX\Uninstall.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
|
||||
|
||||
; Store installation folder
|
||||
WriteRegStr HKCU "Software\QuantumBotX" "" $INSTDIR
|
||||
|
||||
; Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
; Write registry for Add/Remove Programs
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX" "DisplayName" "QuantumBotX Trading Bot"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX" "DisplayVersion" "2.0.0"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX" "Publisher" "Chrisnov IT Solutions"
|
||||
WriteRegDWord HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX" "NoModify" 1
|
||||
WriteRegDWord HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX" "NoRepair" 1
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
; Remove files and directories
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
Delete "$INSTDIR\QuantumBotX.exe"
|
||||
RMDir /r "$INSTDIR\_internal"
|
||||
RMDir /r "$INSTDIR\templates"
|
||||
RMDir /r "$INSTDIR\static"
|
||||
RMDir /r "$INSTDIR\core"
|
||||
RMDir /r "$INSTDIR\docs"
|
||||
RMDir /r "$INSTDIR\lab"
|
||||
RMDir /r "$INSTDIR\testing"
|
||||
RMDir /r "$INSTDIR\logs"
|
||||
Delete "$INSTDIR\*.*"
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove shortcuts
|
||||
Delete "$DESKTOP\QuantumBotX.lnk"
|
||||
RMDir /r "$SMPROGRAMS\QuantumBotX"
|
||||
|
||||
; Remove registry entries
|
||||
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QuantumBotX"
|
||||
DeleteRegKey /ifempty HKCU "Software\QuantumBotX"
|
||||
|
||||
; Stop running instances before uninstall
|
||||
nsExec::Exec 'taskkill /f /im "QuantumBotX.exe"'
|
||||
nsExec::Exec 'taskkill /f /im "python.exe"'
|
||||
|
||||
SectionEnd
|
||||
|
||||
Function .onInit
|
||||
; Check if already installed
|
||||
ReadRegStr $R0 HKCU "Software\QuantumBotX" ""
|
||||
${If} $R0 != ""
|
||||
MessageBox MB_YESNO "QuantumBotX is already installed. Do you want to reinstall?" IDYES continue
|
||||
Abort
|
||||
continue:
|
||||
${EndIf}
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function PrerequisitesPage
|
||||
!insertmacro MUI_HEADER_TEXT "Prerequisites" "Important setup information"
|
||||
|
||||
nsDialogs::Create 1018
|
||||
Pop $0
|
||||
|
||||
${NSD_CreateLabel} 0 0 100% 24u "Before using QuantumBotX, you need to:"
|
||||
Pop $0
|
||||
|
||||
${NSD_CreateLabel} 0 30u 100% 60u "1. Install MetaTrader 5 from https://www.metatrader5.com/$\n2. Create a demo or live trading account$\n3. Keep MT5 running in background when using QuantumBotX$\n$\n⚠️ Python is NOT required - it's already bundled in this installer!"
|
||||
Pop $0
|
||||
|
||||
${NSD_CreateLabel} 0 100u 100% 24u "System Requirements:"
|
||||
Pop $0
|
||||
|
||||
${NSD_CreateLabel} 0 130u 100% 40u "• Windows 7 SP1 or later (64-bit recommended)$\n• 4GB RAM minimum (8GB recommended)$\n• 500MB free disk space$\n• Internet connection for initial setup"
|
||||
Pop $0
|
||||
|
||||
nsDialogs::Show
|
||||
FunctionEnd
|
||||
|
||||
Function PrerequisitesPageLeave
|
||||
# This function is called when leaving the prerequisites page
|
||||
# We could add validation here if needed
|
||||
FunctionEnd
|
||||
|
||||
Function .onInstSuccess
|
||||
MessageBox MB_YESNO "Installation completed successfully! $\n$\nDo you want to run the setup wizard now?" IDNO end
|
||||
Exec '"$INSTDIR\setup_quantumbotx.py"'
|
||||
end:
|
||||
FunctionEnd
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"broker": "FBS-Demo",
|
||||
"company": "FBS Markets Inc.",
|
||||
"last_check": "2025-09-24T10:46:19.830283"
|
||||
"last_check": "2025-10-09T12:17:45.370404"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
cd /d "%~dp0"
|
||||
start.bat
|
||||
@@ -0,0 +1,99 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
a = Analysis(
|
||||
['run.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('templates', 'templates'),
|
||||
('static', 'static'),
|
||||
('core', 'core'),
|
||||
('.env.example', '.env.example'),
|
||||
('README.md', 'README.md'),
|
||||
('MT5_SETUP_GUIDE.md', 'MT5_SETUP_GUIDE.md'),
|
||||
],
|
||||
hiddenimports=[
|
||||
'MetaTrader5',
|
||||
'flask',
|
||||
'werkzeug',
|
||||
'jinja2',
|
||||
'numpy',
|
||||
'pandas',
|
||||
'pandas_ta',
|
||||
'core',
|
||||
'core.bots',
|
||||
'core.brokers',
|
||||
'core.data',
|
||||
'core.db',
|
||||
'core.routes',
|
||||
'core.strategies',
|
||||
'core.utils',
|
||||
'core.ai',
|
||||
'core.backtesting',
|
||||
'core.education',
|
||||
'core.interfaces',
|
||||
'core.services',
|
||||
'core.seasonal',
|
||||
'core.helpers',
|
||||
'core.bots.controller',
|
||||
'core.bots.trading_bot',
|
||||
'core.brokers.base_broker',
|
||||
'core.brokers.binance_broker',
|
||||
'core.brokers.broker_factory',
|
||||
'core.brokers.ctrader_broker',
|
||||
'core.brokers.indonesian_brokers',
|
||||
'core.brokers.interactive_brokers',
|
||||
'core.brokers.tradingview_broker',
|
||||
'core.data.chart_data',
|
||||
'core.db.connection',
|
||||
'core.db.models',
|
||||
'core.db.queries',
|
||||
'core.ai.ollama_client',
|
||||
'core.ai.trading_mentor_ai',
|
||||
'core.backtesting.engine',
|
||||
'core.backtesting.enhanced_engine',
|
||||
'core.education.atr_education',
|
||||
'core.utils.mt5',
|
||||
],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='QuantumBotX',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
icon=None,
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='QuantumBotX',
|
||||
)
|
||||
@@ -4,6 +4,7 @@ charset-normalizer==3.4.2
|
||||
click==8.2.1
|
||||
colorama==0.4.6
|
||||
Flask==3.1.1
|
||||
gunicorn
|
||||
idna==3.10
|
||||
itsdangerous==2.2.0
|
||||
Jinja2==3.1.6
|
||||
|
||||
@@ -29,9 +29,21 @@ app = create_app()
|
||||
@app.route('/api/health')
|
||||
def health_check():
|
||||
"""Endpoint untuk memastikan server berjalan."""
|
||||
return jsonify({"status": "ok", "message": "Server is running"})
|
||||
mt5_status = "MT5 connected" if mt5.isinitialize() else "MT5 not connected" # pyright: ignore[reportAttributeAccessIssue]
|
||||
return jsonify({"status": "ok", "message": "Server is running", "mt5": mt5_status})
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Skip MT5 initialization if SKIP_MT5_INIT is set (for Vercel deployment)
|
||||
if os.getenv('SKIP_MT5_INIT') == '1':
|
||||
logging.info("Skipping MT5 initialization (deployment mode).")
|
||||
app.run(
|
||||
debug=os.getenv('FLASK_DEBUG', 'False').lower() == 'true',
|
||||
host=os.getenv('FLASK_HOST', '127.0.0.1'),
|
||||
port=int(os.getenv('FLASK_PORT', 5000)),
|
||||
use_reloader=False
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
# --- Inisialisasi MT5 Terpusat ---
|
||||
# Dilakukan di sini untuk memastikan hanya berjalan sekali.
|
||||
try:
|
||||
@@ -72,4 +84,4 @@ if __name__ == '__main__':
|
||||
host=os.getenv('FLASK_HOST', '127.0.0.1'),
|
||||
port=int(os.getenv('FLASK_PORT', 5000)),
|
||||
use_reloader=False
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
QuantumBotX Setup Script
|
||||
Automated setup for non-technical users
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
def run_command(command, shell=True):
|
||||
"""Run a command and return the result."""
|
||||
try:
|
||||
result = subprocess.run(command, shell=shell, capture_output=True, text=True)
|
||||
return result.returncode == 0, result.stdout, result.stderr
|
||||
except Exception as e:
|
||||
return False, "", str(e)
|
||||
|
||||
def check_python():
|
||||
"""Check if Python is installed."""
|
||||
success, _, _ = run_command("python --version")
|
||||
return success
|
||||
|
||||
def install_requirements():
|
||||
"""Install Python requirements."""
|
||||
print("Installing Python dependencies...")
|
||||
success, stdout, stderr = run_command("pip install -r requirements.txt")
|
||||
if not success:
|
||||
print(f"Error installing requirements: {stderr}")
|
||||
return False
|
||||
print("✓ Python dependencies installed successfully")
|
||||
return True
|
||||
|
||||
def create_startup_scripts():
|
||||
"""Create user-friendly startup scripts."""
|
||||
print("Creating startup scripts...")
|
||||
|
||||
# Create start.bat
|
||||
start_bat = '''@echo off
|
||||
echo Starting QuantumBotX Trading Application...
|
||||
echo =========================================
|
||||
echo.
|
||||
echo Make sure MetaTrader 5 is running before continuing!
|
||||
echo.
|
||||
pause
|
||||
echo.
|
||||
python run.py
|
||||
pause
|
||||
'''
|
||||
|
||||
with open('start.bat', 'w') as f:
|
||||
f.write(start_bat)
|
||||
|
||||
# Create start.sh for Unix-like systems (if needed)
|
||||
start_sh = '''#!/bin/bash
|
||||
echo "Starting QuantumBotX Trading Application..."
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "Make sure MetaTrader 5 is running before continuing!"
|
||||
echo ""
|
||||
read -p "Press Enter to continue..."
|
||||
echo ""
|
||||
python3 run.py
|
||||
'''
|
||||
|
||||
with open('start.sh', 'w') as f:
|
||||
f.write(start_sh)
|
||||
|
||||
# Make start.sh executable on Unix systems
|
||||
try:
|
||||
os.chmod('start.sh', 0o755)
|
||||
except:
|
||||
pass # Windows doesn't need this
|
||||
|
||||
print("✓ Startup scripts created")
|
||||
return True
|
||||
|
||||
def create_desktop_shortcut():
|
||||
"""Create desktop shortcut (Windows only)."""
|
||||
print("Creating desktop shortcut...")
|
||||
|
||||
try:
|
||||
# Get user's desktop path
|
||||
desktop = Path.home() / "Desktop"
|
||||
shortcut_path = desktop / "QuantumBotX.lnk"
|
||||
|
||||
# Create a simple batch file that will be the shortcut target
|
||||
shortcut_bat = '''@echo off
|
||||
cd /d "%~dp0"
|
||||
start.bat
|
||||
'''
|
||||
|
||||
with open('quantum_botx_shortcut.bat', 'w') as f:
|
||||
f.write(shortcut_bat)
|
||||
|
||||
print("✓ Desktop shortcut script created")
|
||||
print(f" You can manually create a shortcut to: {os.path.abspath('quantum_botx_shortcut.bat')}")
|
||||
print(" And place it on your desktop")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Note: Could not create desktop shortcut automatically: {e}")
|
||||
print(" You can manually create a shortcut to start.bat on your desktop")
|
||||
return True
|
||||
|
||||
def create_user_instructions():
|
||||
"""Create user-friendly instructions."""
|
||||
print("Creating user instructions...")
|
||||
|
||||
instructions = '''# QuantumBotX - Quick Start Guide
|
||||
|
||||
## First Time Setup
|
||||
|
||||
1. **Install MetaTrader 5**
|
||||
- Download from: https://www.metatrader5.com/
|
||||
- Install and create a demo account
|
||||
- Keep MT5 running in the background
|
||||
|
||||
2. **Configure Your Settings**
|
||||
- Copy `.env.example` to `.env`
|
||||
- Edit `.env` with your MT5 credentials:
|
||||
```
|
||||
MT5_LOGIN=your_account_number
|
||||
MT5_PASSWORD=your_password
|
||||
MT5_SERVER=your_server_name
|
||||
```
|
||||
|
||||
3. **Start the Application**
|
||||
- Double-click `start.bat` (Windows)
|
||||
- Open http://127.0.0.1:5000 in your browser
|
||||
|
||||
## Daily Use
|
||||
|
||||
1. Start MetaTrader 5 first
|
||||
2. Run `start.bat`
|
||||
3. Open your web browser to http://127.0.0.1:5000
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Make sure MetaTrader 5 is running
|
||||
- Check your .env file has correct credentials
|
||||
- If the app won't start, try running `python run.py` directly
|
||||
|
||||
## Support
|
||||
|
||||
If you need help, check the README.md file or contact support.
|
||||
'''
|
||||
|
||||
with open('QUICK_START_GUIDE.md', 'w') as f:
|
||||
f.write(instructions)
|
||||
|
||||
print("✓ User instructions created")
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Main setup function."""
|
||||
print("QuantumBotX Setup Wizard")
|
||||
print("========================")
|
||||
print()
|
||||
|
||||
# Check Python
|
||||
if not check_python():
|
||||
print("❌ Python is not installed or not in PATH")
|
||||
print("Please install Python 3.8 or higher from https://python.org")
|
||||
input("Press Enter to exit...")
|
||||
return
|
||||
|
||||
print("✓ Python found")
|
||||
|
||||
# Install requirements
|
||||
if not install_requirements():
|
||||
print("❌ Failed to install requirements")
|
||||
input("Press Enter to exit...")
|
||||
return
|
||||
|
||||
# Create startup scripts
|
||||
if not create_startup_scripts():
|
||||
print("❌ Failed to create startup scripts")
|
||||
input("Press Enter to exit...")
|
||||
return
|
||||
|
||||
# Create desktop shortcut
|
||||
create_desktop_shortcut()
|
||||
|
||||
# Create user instructions
|
||||
if not create_user_instructions():
|
||||
print("❌ Failed to create user instructions")
|
||||
input("Press Enter to exit...")
|
||||
return
|
||||
|
||||
print()
|
||||
print("🎉 Setup Complete!")
|
||||
print("==================")
|
||||
print()
|
||||
print("Next steps:")
|
||||
print("1. Install and configure MetaTrader 5")
|
||||
print("2. Copy .env.example to .env and configure your credentials")
|
||||
print("3. Run start.bat to launch the application")
|
||||
print("4. Open http://127.0.0.1:5000 in your browser")
|
||||
print()
|
||||
print("See QUICK_START_GUIDE.md for detailed instructions")
|
||||
print()
|
||||
input("Press Enter to exit...")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,10 @@
|
||||
@echo off
|
||||
echo Starting QuantumBotX Trading Application...
|
||||
echo =========================================
|
||||
echo.
|
||||
echo Make sure MetaTrader 5 is running before continuing!
|
||||
echo.
|
||||
pause
|
||||
echo.
|
||||
QuantumBotX.exe
|
||||
pause
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
echo "Starting QuantumBotX Trading Application..."
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "Make sure MetaTrader 5 is running before continuing!"
|
||||
echo ""
|
||||
read -p "Press Enter to continue..."
|
||||
echo ""
|
||||
python3 run.py
|
||||
@@ -9,7 +9,6 @@ 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() {
|
||||
@@ -242,43 +241,5 @@ 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 = '<i class="fas fa-spinner fa-spin mr-2"></i>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();
|
||||
});
|
||||
|
||||
+15
-7
@@ -47,18 +47,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
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' ? '▲' : '▼') : '';
|
||||
// Reset all icons
|
||||
['symbol', 'type', 'volume', 'profit', 'time', 'magic'].forEach(col => {
|
||||
const iconEl = document.getElementById(`${col}-sort-icon`);
|
||||
if (iconEl) {
|
||||
iconEl.innerHTML = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Set active icon
|
||||
const activeIconEl = document.getElementById(`${column}-sort-icon`);
|
||||
if (activeIconEl) {
|
||||
activeIconEl.innerHTML = 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') {
|
||||
// For numeric columns, parse as float
|
||||
if (['profit', 'time', 'volume', 'magic', 'type'].includes(column)) {
|
||||
aValue = parseFloat(aValue);
|
||||
bValue = parseFloat(bValue);
|
||||
}
|
||||
|
||||
+1100
-48
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -84,7 +84,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
portfolioTableBody.innerHTML = ''; // Kosongkan tabel sebelum diisi
|
||||
|
||||
if (positions.length === 0) {
|
||||
portfolioTableBody.innerHTML = '<tr><td colspan="6" class="p-4 text-center text-gray-500">Tidak ada posisi terbuka.</td></tr>';
|
||||
portfolioTableBody.innerHTML = `<tr><td colspan="6" class="p-4 text-center text-gray-500">${window.QuantumBotXI18n.t('portfolio.no_open_positions')}</td></tr>`;
|
||||
} else {
|
||||
positions.forEach(pos => {
|
||||
totalProfit += pos.profit;
|
||||
@@ -112,7 +112,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
else if (totalProfit < previousTotalProfit) trendIcon = '<i class="fas fa-arrow-down text-red-500"></i>';
|
||||
|
||||
portfolioSummary.innerHTML = `
|
||||
<p class="text-sm text-gray-500">Total P/L Terbuka</p>
|
||||
<p class="text-sm text-gray-500">${window.QuantumBotXI18n.t('portfolio.open_pnl_total')}</p>
|
||||
<p class="text-2xl font-bold ${totalProfitClass}">${formatCurrency(totalProfit)} <span class="ml-2 text-lg">${trendIcon}</span></p>`;
|
||||
previousTotalProfit = totalProfit;
|
||||
|
||||
|
||||
+13
-5
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Halaman Tidak Ditemukan - QuantumBotX</title>
|
||||
<title><span data-i18n="error.404_title">Halaman Tidak Ditemukan - QuantumBotX</span></title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
@@ -11,13 +11,21 @@
|
||||
<body class="bg-gray-100 font-sans flex items-center justify-center h-screen">
|
||||
<div class="text-center">
|
||||
<h1 class="text-9xl font-bold text-blue-500">404</h1>
|
||||
<h2 class="text-3xl font-semibold text-gray-800 mt-4">Halaman Tidak Ditemukan</h2>
|
||||
<p class="text-gray-600 mt-2">Maaf, halaman yang Anda cari tidak ada atau telah dipindahkan.</p>
|
||||
<h2 class="text-3xl font-semibold text-gray-800 mt-4" data-i18n="error.404_heading">Halaman Tidak Ditemukan</h2>
|
||||
<p class="text-gray-600 mt-2" data-i18n="error.404_message">Maaf, halaman yang Anda cari tidak ada atau telah dipindahkan.</p>
|
||||
<div class="mt-8">
|
||||
<a href="{{ url_for('dashboard') }}" class="bg-blue-500 text-white px-6 py-3 rounded-lg shadow hover:bg-blue-600 transition">
|
||||
<i class="fas fa-home mr-2"></i>Kembali ke Dashboard
|
||||
<i class="fas fa-home mr-2"></i><span data-i18n="error.back_to_dashboard">Kembali ke Dashboard</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/i18n.js') }}"></script>
|
||||
<script>
|
||||
// Initialize i18n for this page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.QuantumBotXI18n.init();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
+12
-4
@@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Terjadi Kesalahan Internal - QuantumBotX</title>
|
||||
<title><span data-i18n="error.500_title">Terjadi Kesalahan Internal - QuantumBotX</span></title>
|
||||
<!-- Menggunakan versi Tailwind yang lebih modern jika memungkinkan, tapi kita samakan dengan 404.html -->
|
||||
<link href="https://cdn.tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||
@@ -13,15 +13,23 @@
|
||||
<body class="bg-gray-100 font-sans flex items-center justify-center h-screen">
|
||||
<div class="text-center">
|
||||
<h1 class="text-9xl font-bold text-red-500">500</h1>
|
||||
<h2 class="text-3xl font-semibold text-gray-800 mt-4">Terjadi Kesalahan Internal</h2>
|
||||
<p class="text-gray-600 mt-2">
|
||||
<h2 class="text-3xl font-semibold text-gray-800 mt-4" data-i18n="error.500_heading">Terjadi Kesalahan Internal</h2>
|
||||
<p class="text-gray-600 mt-2" data-i18n="error.500_message">
|
||||
Maaf, terjadi masalah pada server kami. Tim kami telah diberitahu dan sedang menanganinya.
|
||||
</p>
|
||||
<div class="mt-8">
|
||||
<a href="{{ url_for('dashboard') }}" class="bg-blue-500 text-white px-6 py-3 rounded-lg shadow hover:bg-blue-600 transition">
|
||||
<i class="fas fa-home mr-2"></i>Kembali ke Dashboard
|
||||
<i class="fas fa-home mr-2"></i><span data-i18n="error.back_to_dashboard">Kembali ke Dashboard</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/i18n.js') }}"></script>
|
||||
<script>
|
||||
// Initialize i18n for this page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.QuantumBotXI18n.init();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +1,8 @@
|
||||
<!-- templates/ai_mentor/daily_report.html -->
|
||||
{% extends \"base.html\" %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}📊 Laporan AI Mentor - {{ session_data.session_date if session_data else 'Hari Ini' }} - QuantumBotX{% endblock %}
|
||||
{% block title_key %}ai_mentor.report_page_title{% endblock %}
|
||||
{% block title %}📊 AI Mentor Report{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
@@ -71,179 +72,179 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class=\"container mx-auto px-4 py-8\">
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Header -->
|
||||
<div class=\"ai-report-card\">
|
||||
<div class=\"flex justify-between items-start\">
|
||||
<div class="ai-report-card">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<h1 class=\"text-3xl font-bold mb-2\">📊 Laporan AI Mentor</h1>
|
||||
<p class=\"text-blue-100 text-lg\">Analisis personal untuk {{ session_data.session_date if session_data else 'Hari Ini' }}</p>
|
||||
<div class=\"mt-4 flex items-center space-x-4\">
|
||||
<span class=\"text-blue-200\">🤖 Dibuat oleh AI</span>
|
||||
<span class=\"text-blue-200\">• 🇮🇩 Bahasa Indonesia</span>
|
||||
<span class=\"text-blue-200\">• 📈 Data Real</span>
|
||||
<h1 class="text-3xl font-bold mb-2" data-i18n="ai_mentor.report_title">📊 Laporan AI Mentor</h1>
|
||||
<p class="text-blue-100 text-lg" data-i18n="ai_mentor.report_subtitle">Analisis personal untuk {{ session_data.session_date if session_data else 'Hari Ini' }}</p>
|
||||
<div class="mt-4 flex items-center space-x-4">
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.created_by_ai">🤖 Dibuat oleh AI</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.language_indonesian">• 🇮🇩 Bahasa Indonesia</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.real_data">• 📈 Data Real</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class=\"text-right\">
|
||||
<div class="text-right">
|
||||
{% if session_data %}
|
||||
<div class=\"text-3xl font-bold {{ 'text-green-300' if session_data.total_profit_loss > 0 else 'text-red-300' if session_data.total_profit_loss < 0 else 'text-gray-300' }}\">
|
||||
${{ \"%.2f\"|format(session_data.total_profit_loss) }}
|
||||
<div class="text-3xl font-bold {{ 'text-green-300' if session_data.total_profit_loss > 0 else 'text-red-300' if session_data.total_profit_loss < 0 else 'text-gray-300' }}">
|
||||
${{ "%.2f"|format(session_data.total_profit_loss) }}
|
||||
</div>
|
||||
<div class=\"text-blue-200\">{{ session_data.total_trades }} trades</div>
|
||||
<div class="text-blue-200">{{ session_data.total_trades }} <span data-i18n="ai_mentor.trades">trades</span></div>
|
||||
{% else %}
|
||||
<div class=\"text-gray-300\">No data</div>
|
||||
<div class="text-gray-300" data-i18n="ai_mentor.no_data">No data</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation -->
|
||||
<div class=\"mb-6\">
|
||||
<nav class=\"flex space-x-4\">
|
||||
<a href=\"{{ url_for('ai_mentor.dashboard') }}\" class=\"text-blue-600 hover:text-blue-800\">← Kembali ke Dashboard</a>
|
||||
<a href=\"{{ url_for('ai_mentor.history') }}\" class=\"text-gray-600 hover:text-gray-800\">📚 Riwayat Laporan</a>
|
||||
<div class="mb-6">
|
||||
<nav class="flex space-x-4">
|
||||
<a href="{{ url_for('ai_mentor.dashboard') }}" class="text-blue-600 hover:text-blue-800">← <span data-i18n="ai_mentor.back_to_dashboard">Kembali ke Dashboard</span></a>
|
||||
<a href="{{ url_for('ai_mentor.history') }}" class="text-gray-600 hover:text-gray-800">📚 <span data-i18n="ai_mentor.report_history">Riwayat Laporan</span></a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{% if session_data and analysis %}
|
||||
<!-- Trading Summary -->
|
||||
<div class=\"analysis-section\">
|
||||
<h2 class=\"text-xl font-bold mb-4 flex items-center text-gray-800\">
|
||||
<span class=\"mr-2\">📊</span>
|
||||
Ringkasan Trading
|
||||
<div class="analysis-section">
|
||||
<h2 class="text-xl font-bold mb-4 flex items-center text-gray-800">
|
||||
<span class="mr-2">📊</span>
|
||||
<span data-i18n="ai_mentor.trading_summary">Ringkasan Trading</span>
|
||||
</h2>
|
||||
<div class=\"grid grid-cols-1 md:grid-cols-4 gap-4\">
|
||||
<div class=\"text-center\">
|
||||
<div class=\"text-2xl font-bold text-blue-600\">{{ session_data.total_trades }}</div>
|
||||
<div class=\"text-sm text-gray-600\">Total Trades</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-blue-600">{{ session_data.total_trades }}</div>
|
||||
<div class="text-sm text-gray-600" data-i18n="ai_mentor.total_trades">Total Trades</div>
|
||||
</div>
|
||||
<div class=\"text-center\">
|
||||
<div class=\"text-2xl font-bold {{ 'profit-positive' if session_data.total_profit_loss > 0 else 'profit-negative' if session_data.total_profit_loss < 0 else 'text-gray-600' }}\">
|
||||
${{ \"%.2f\"|format(session_data.total_profit_loss) }}
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold {{ 'profit-positive' if session_data.total_profit_loss > 0 else 'profit-negative' if session_data.total_profit_loss < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(session_data.total_profit_loss) }}
|
||||
</div>
|
||||
<div class=\"text-sm text-gray-600\">Profit/Loss</div>
|
||||
<div class="text-sm text-gray-600" data-i18n="ai_mentor.profit_loss">Profit/Loss</div>
|
||||
</div>
|
||||
<div class=\"text-center\">
|
||||
<span class=\"emotion-badge emotion-{{ session_data.emotions }}\">{{ session_data.emotions.title() }}</span>
|
||||
<div class=\"text-sm text-gray-600 mt-1\">Kondisi Emosi</div>
|
||||
<div class="text-center">
|
||||
<span class="emotion-badge emotion-{{ session_data.emotions }}">{{ session_data.emotions.title() }}</span>
|
||||
<div class="text-sm text-gray-600 mt-1" data-i18n="ai_mentor.emotional_condition">Kondisi Emosi</div>
|
||||
</div>
|
||||
<div class=\"text-center\">
|
||||
<div class=\"text-lg font-semibold text-gray-700\">{{ session_data.market_conditions.title() }}</div>
|
||||
<div class=\"text-sm text-gray-600\">Kondisi Market</div>
|
||||
<div class="text-center">
|
||||
<div class="text-lg font-semibold text-gray-700">{{ session_data.market_conditions.title() }}</div>
|
||||
<div class="text-sm text-gray-600" data-i18n="ai_mentor.market_conditions">Kondisi Market</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI Analysis Sections -->
|
||||
<div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<!-- Trading Patterns -->
|
||||
<div class=\"analysis-section\">
|
||||
<h3 class=\"text-lg font-bold mb-3 text-gray-800\">🔍 Analisis Pola Trading</h3>
|
||||
<div class=\"space-y-3\">
|
||||
<div class="analysis-section">
|
||||
<h3 class="text-lg font-bold mb-3 text-gray-800">🔍 <span data-i18n="ai_mentor.trading_patterns">Analisis Pola Trading</span></h3>
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<span class=\"font-semibold text-gray-700\">Pola Utama:</span>
|
||||
<span class=\"text-blue-600\">{{ analysis.pola_trading.pola_utama }}</span>
|
||||
<span class="font-semibold text-gray-700" data-i18n="ai_mentor.main_pattern">Pola Utama:</span>
|
||||
<span class="text-blue-600">{{ analysis.pola_trading.pola_utama }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class=\"text-gray-700\">{{ analysis.pola_trading.analisis }}</p>
|
||||
<p class="text-gray-700">{{ analysis.pola_trading.analisis }}</p>
|
||||
</div>
|
||||
<div class=\"bg-green-50 p-3 rounded-lg\">
|
||||
<strong class=\"text-green-700\">💪 Kekuatan:</strong>
|
||||
<p class=\"text-green-600\">{{ analysis.pola_trading.kekuatan }}</p>
|
||||
<div class="bg-green-50 p-3 rounded-lg">
|
||||
<strong class="text-green-700">💪 <span data-i18n="ai_mentor.strength">Kekuatan:</span></strong>
|
||||
<p class="text-green-600">{{ analysis.pola_trading.kekuatan }}</p>
|
||||
</div>
|
||||
<div class=\"bg-blue-50 p-3 rounded-lg\">
|
||||
<strong class=\"text-blue-700\">🎯 Area Perbaikan:</strong>
|
||||
<p class=\"text-blue-600\">{{ analysis.pola_trading.area_perbaikan }}</p>
|
||||
<div class="bg-blue-50 p-3 rounded-lg">
|
||||
<strong class="text-blue-700">🎯 <span data-i18n="ai_mentor.improvement_areas">Area Perbaikan:</span></strong>
|
||||
<p class="text-blue-600">{{ analysis.pola_trading.area_perbaikan }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Emotional Analysis -->
|
||||
<div class=\"analysis-section\">
|
||||
<h3 class=\"text-lg font-bold mb-3 text-gray-800\">🧠 Analisis Emosi vs Performa</h3>
|
||||
<div class=\"space-y-3\">
|
||||
<div class=\"bg-purple-50 p-3 rounded-lg\">
|
||||
<strong class=\"text-purple-700\">💭 Feedback Emosi:</strong>
|
||||
<p class=\"text-purple-600\">{{ analysis.emosi_vs_performa.feedback }}</p>
|
||||
<div class="analysis-section">
|
||||
<h3 class="text-lg font-bold mb-3 text-gray-800">🧠 <span data-i18n="ai_mentor.emotional_analysis">Analisis Emosi vs Performa</span></h3>
|
||||
<div class="space-y-3">
|
||||
<div class="bg-purple-50 p-3 rounded-lg">
|
||||
<strong class="text-purple-700">💭 <span data-i18n="ai_mentor.emotional_feedback">Feedback Emosi:</span></strong>
|
||||
<p class="text-purple-600">{{ analysis.emosi_vs_performa.feedback }}</p>
|
||||
</div>
|
||||
<div class=\"bg-yellow-50 p-3 rounded-lg\">
|
||||
<strong class=\"text-yellow-700\">💡 Tip:</strong>
|
||||
<p class=\"text-yellow-600\">{{ analysis.emosi_vs_performa.tip }}</p>
|
||||
<div class="bg-yellow-50 p-3 rounded-lg">
|
||||
<strong class="text-yellow-700">💡 <span data-i18n="ai_mentor.tip">Tip:</span></strong>
|
||||
<p class="text-yellow-600">{{ analysis.emosi_vs_performa.tip }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Risk Management -->
|
||||
<div class=\"analysis-section\">
|
||||
<h3 class=\"text-lg font-bold mb-3 text-gray-800\">🛡️ Evaluasi Manajemen Risiko</h3>
|
||||
<div class=\"flex items-center space-x-4 mb-4\">
|
||||
<span class=\"risk-score risk-{{ 'excellent' if '10' in analysis.manajemen_risiko.nilai else 'good' if any(x in analysis.manajemen_risiko.nilai for x in ['8', '9']) else 'warning' if any(x in analysis.manajemen_risiko.nilai for x in ['6', '7']) else 'danger' }}\">
|
||||
<div class="analysis-section">
|
||||
<h3 class="text-lg font-bold mb-3 text-gray-800">🛡️ <span data-i18n="ai_mentor.risk_management">Evaluasi Manajemen Risiko</span></h3>
|
||||
<div class="flex items-center space-x-4 mb-4">
|
||||
<span class="risk-score risk-{{ 'excellent' if '10' in analysis.manajemen_risiko.nilai else 'good' if any(x in analysis.manajemen_risiko.nilai for x in ['8', '9']) else 'warning' if any(x in analysis.manajemen_risiko.nilai for x in ['6', '7']) else 'danger' }}">
|
||||
{{ analysis.manajemen_risiko.nilai }}
|
||||
</span>
|
||||
<span class=\"text-gray-700\">{{ analysis.manajemen_risiko.feedback }}</span>
|
||||
<span class="text-gray-700">{{ analysis.manajemen_risiko.feedback }}</span>
|
||||
</div>
|
||||
|
||||
{% if analysis.manajemen_risiko.detail %}
|
||||
<div class=\"bg-gray-50 p-3 rounded-lg mb-3\">
|
||||
<p class=\"text-gray-700\">{{ analysis.manajemen_risiko.detail }}</p>
|
||||
<div class="bg-gray-50 p-3 rounded-lg mb-3">
|
||||
<p class="text-gray-700">{{ analysis.manajemen_risiko.detail }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if analysis.manajemen_risiko.apresiasi %}
|
||||
<div class=\"bg-green-50 p-3 rounded-lg\">
|
||||
<p class=\"text-green-700\">{{ analysis.manajemen_risiko.apresiasi }}</p>
|
||||
<div class="bg-green-50 p-3 rounded-lg">
|
||||
<p class="text-green-700">{{ analysis.manajemen_risiko.apresiasi }}</p>
|
||||
</div>
|
||||
{% elif analysis.manajemen_risiko.saran %}
|
||||
<div class=\"bg-orange-50 p-3 rounded-lg\">
|
||||
<p class=\"text-orange-700\">{{ analysis.manajemen_risiko.saran }}</p>
|
||||
<div class="bg-orange-50 p-3 rounded-lg">
|
||||
<p class="text-orange-700">{{ analysis.manajemen_risiko.saran }}</p>
|
||||
</div>
|
||||
{% elif analysis.manajemen_risiko.peringatan %}
|
||||
<div class=\"bg-red-50 p-3 rounded-lg\">
|
||||
<p class=\"text-red-700\">{{ analysis.manajemen_risiko.peringatan }}</p>
|
||||
<div class="bg-red-50 p-3 rounded-lg">
|
||||
<p class="text-red-700">{{ analysis.manajemen_risiko.peringatan }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Recommendations -->
|
||||
<div class=\"analysis-section\">
|
||||
<h3 class=\"text-lg font-bold mb-3 text-gray-800\">💡 Rekomendasi AI Mentor</h3>
|
||||
<div class=\"space-y-2\">
|
||||
<div class="analysis-section">
|
||||
<h3 class="text-lg font-bold mb-3 text-gray-800">💡 <span data-i18n="ai_mentor.recommendations">Rekomendasi AI Mentor</span></h3>
|
||||
<div class="space-y-2">
|
||||
{% for rekomendasi in analysis.rekomendasi %}
|
||||
<div class=\"recommendation-item\">
|
||||
<p class=\"text-gray-700\">{{ rekomendasi }}</p>
|
||||
<div class="recommendation-item">
|
||||
<p class="text-gray-700">{{ rekomendasi }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Motivation Message -->
|
||||
<div class=\"bg-gradient-to-r from-green-400 to-blue-500 text-white rounded-lg p-6\">
|
||||
<h3 class=\"text-xl font-bold mb-3\">💪 Pesan Motivasi</h3>
|
||||
<p class=\"text-lg leading-relaxed\">{{ analysis.motivasi }}</p>
|
||||
<div class="bg-gradient-to-r from-green-400 to-blue-500 text-white rounded-lg p-6">
|
||||
<h3 class="text-xl font-bold mb-3">💪 <span data-i18n="ai_mentor.motivational_message">Pesan Motivasi</span></h3>
|
||||
<p class="text-lg leading-relaxed">{{ analysis.motivasi }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Trade Details -->
|
||||
{% if session_data.trades %}
|
||||
<div class=\"analysis-section\">
|
||||
<h3 class=\"text-lg font-bold mb-3 text-gray-800\">📈 Detail Trades Hari Ini</h3>
|
||||
<div class=\"space-y-2\">
|
||||
<div class="analysis-section">
|
||||
<h3 class="text-lg font-bold mb-3 text-gray-800">📈 <span data-i18n="ai_mentor.trade_details">Detail Trades Hari Ini</span></h3>
|
||||
<div class="space-y-2">
|
||||
{% for trade in session_data.trades %}
|
||||
<div class=\"trade-item\">
|
||||
<div class=\"flex-1\">
|
||||
<span class=\"font-semibold\">{{ trade.symbol }}</span>
|
||||
<span class=\"text-sm text-gray-500 ml-2\">Lot: {{ trade.lot_size }}</span>
|
||||
<div class="trade-item">
|
||||
<div class="flex-1">
|
||||
<span class="font-semibold">{{ trade.symbol }}</span>
|
||||
<span class="text-sm text-gray-500 ml-2" data-i18n="ai_mentor.lot_size">Lot: {{ trade.lot_size }}</span>
|
||||
{% if trade.strategy %}
|
||||
<span class=\"text-xs bg-gray-200 px-2 py-1 rounded ml-2\">{{ trade.strategy }}</span>
|
||||
<span class="text-xs bg-gray-200 px-2 py-1 rounded ml-2">{{ trade.strategy }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class=\"text-right\">
|
||||
<div class=\"{{ 'profit-positive' if trade.profit > 0 else 'profit-negative' if trade.profit < 0 else 'text-gray-600' }}\">
|
||||
${{ \"%.2f\"|format(trade.profit) }}
|
||||
<div class="text-right">
|
||||
<div class="{{ 'profit-positive' if trade.profit > 0 else 'profit-negative' if trade.profit < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(trade.profit) }}
|
||||
</div>
|
||||
<div class=\"text-xs text-gray-500\">
|
||||
SL: {{ '✅' if trade.stop_loss_used else '❌' }} |
|
||||
TP: {{ '✅' if trade.take_profit_used else '❌' }}
|
||||
<div class="text-xs text-gray-500">
|
||||
<span data-i18n="ai_mentor.sl">SL: {{ '✅' if trade.stop_loss_used else '❌' }}</span> |
|
||||
<span data-i18n="ai_mentor.tp">TP: {{ '✅' if trade.take_profit_used else '❌' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -254,22 +255,22 @@
|
||||
|
||||
<!-- Personal Notes -->
|
||||
{% if session_data.personal_notes %}
|
||||
<div class=\"analysis-section\">
|
||||
<h3 class=\"text-lg font-bold mb-3 text-gray-800\">📝 Catatan Pribadi Anda</h3>
|
||||
<div class=\"bg-blue-50 p-4 rounded-lg border-l-4 border-blue-500\">
|
||||
<p class=\"text-gray-700 italic\">\"{{ session_data.personal_notes }}\"</p>
|
||||
<div class="analysis-section">
|
||||
<h3 class="text-lg font-bold mb-3 text-gray-800">📝 <span data-i18n="ai_mentor.personal_notes">Catatan Pribadi Anda</span></h3>
|
||||
<div class="bg-blue-50 p-4 rounded-lg border-l-4 border-blue-500">
|
||||
<p class="text-gray-700 italic">"{{ session_data.personal_notes }}"</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<!-- No Data State -->
|
||||
<div class=\"text-center py-12\">
|
||||
<div class=\"text-6xl mb-4\">📊</div>
|
||||
<h2 class=\"text-2xl font-bold text-gray-600 mb-4\">Belum Ada Data Trading</h2>
|
||||
<p class=\"text-gray-500 mb-6\">Mulai trading untuk mendapatkan analisis personal dari AI mentor Anda!</p>
|
||||
<a href=\"{{ url_for('ai_mentor.dashboard') }}\" class=\"bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors\">
|
||||
Kembali ke Dashboard
|
||||
<div class="text-center py-12">
|
||||
<div class="text-6xl mb-4">📊</div>
|
||||
<h2 class="text-2xl font-bold text-gray-600 mb-4" data-i18n="ai_mentor.no_trading_data">Belum Ada Data Trading</h2>
|
||||
<p class="text-gray-500 mb-6" data-i18n="ai_mentor.start_trading_for_analysis">Mulai trading untuk mendapatkan analisis personal dari AI mentor Anda!</p>
|
||||
<a href="{{ url_for('ai_mentor.dashboard') }}" class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
<span data-i18n="ai_mentor.back_to_dashboard_button">Kembali ke Dashboard</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -277,23 +278,23 @@
|
||||
|
||||
{% if ai_report %}
|
||||
<!-- Full AI Report Modal (Optional) -->
|
||||
<div id=\"fullReportModal\" class=\"fixed inset-0 bg-black bg-opacity-50 hidden z-50\">
|
||||
<div class=\"flex items-center justify-center min-h-screen p-4\">
|
||||
<div class=\"bg-white rounded-lg max-w-4xl w-full max-h-96 overflow-y-auto p-6\">
|
||||
<div class=\"flex justify-between items-center mb-4\">
|
||||
<h3 class=\"text-lg font-bold\">📝 Laporan AI Lengkap</h3>
|
||||
<button onclick=\"closeFullReport()\" class=\"text-gray-500 hover:text-gray-700\">
|
||||
<div id="fullReportModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
|
||||
<div class="flex items-center justify-center min-h-screen p-4">
|
||||
<div class="bg-white rounded-lg max-w-4xl w-full max-h-96 overflow-y-auto p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="text-lg font-bold">📝 <span data-i18n="ai_mentor.full_report">Laporan AI Lengkap</span></h3>
|
||||
<button onclick="closeFullReport()" class="text-gray-500 hover:text-gray-700">
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<pre class=\"whitespace-pre-wrap text-sm bg-gray-50 p-4 rounded-lg\">{{ ai_report }}</pre>
|
||||
<pre class="whitespace-pre-wrap text-sm bg-gray-50 p-4 rounded-lg">{{ ai_report }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class=\"fixed bottom-4 right-4\">
|
||||
<button onclick=\"showFullReport()\" class=\"bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition-colors\">
|
||||
📝 Lihat Laporan Lengkap
|
||||
<div class="fixed bottom-4 right-4">
|
||||
<button onclick="showFullReport()" class="bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition-colors">
|
||||
📝 <span data-i18n="ai_mentor.view_full_report">Lihat Laporan Lengkap</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<!-- templates/ai_mentor/dashboard.html -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}🧠 AI Mentor Trading - QuantumBotX{% endblock %}
|
||||
{% block title_key %}ai_mentor.page_title{% endblock %}
|
||||
{% block title %}🧠 AI Mentor Trading{% endblock %}
|
||||
|
||||
{% block head_extra %}
|
||||
<style>
|
||||
@@ -20,11 +21,11 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.emotion-tenang { background-color: #10b981; color: white; }
|
||||
.emotion-serakah { background-color: #f59e0b; color: white; }
|
||||
.emotion-takut { background-color: #8b5cf6; color: white; }
|
||||
.emotion-frustasi { background-color: #ef4444; color: white; }
|
||||
.emotion-netral { background-color: #6b7280; color: white; }
|
||||
.emotion-calm { background-color: #10b981; color: white; }
|
||||
.emotion-greedy { background-color: #f59e0b; color: white; }
|
||||
.emotion-fear { background-color: #8b5cf6; color: white; }
|
||||
.emotion-frustrated { background-color: #ef4444; color: white; }
|
||||
.emotion-neutral { background-color: #6b7280; color: white; }
|
||||
|
||||
.profit-positive { color: #10b981; font-weight: bold; }
|
||||
.profit-negative { color: #ef4444; font-weight: bold; }
|
||||
@@ -149,8 +150,8 @@
|
||||
<h2 class="text-xl font-bold mb-2">{{ holiday_config.active_holiday }} 🎆</h2>
|
||||
<p class="text-lg">{{ holiday_greeting }}</p>
|
||||
{% if holiday_config.adjustments.risk_reduction %}
|
||||
<p class="text-sm mt-2 opacity-90">
|
||||
⚠️ Risk otomatis dikurangi {{ (100 - holiday_config.adjustments.risk_reduction * 100)|int }}% untuk periode liburan
|
||||
<p class="text-sm mt-2 opacity-90" data-i18n="ai_mentor.holiday_risk_reduction">
|
||||
⚠️ Risk automatically reduced by {{ (100 - holiday_config.adjustments.risk_reduction * 100)|int }}% during holiday period
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -158,14 +159,14 @@
|
||||
|
||||
<!-- Header -->
|
||||
<div class="mentor-card">
|
||||
<h1 class="text-3xl font-bold mb-2">🧠 AI Mentor Trading Indonesia</h1>
|
||||
<p class="text-blue-100 text-lg">Mentor digital Anda untuk sukses trading jangka panjang</p>
|
||||
<h1 class="text-3xl font-bold mb-2" data-i18n="ai_mentor.header">🧠 AI Mentor Trading</h1>
|
||||
<p class="text-blue-100 text-lg" data-i18n="ai_mentor.subtitle">Your digital mentor for long-term trading success</p>
|
||||
<div class="mt-4 flex items-center space-x-4">
|
||||
<span class="text-blue-200">🇮🇩 Bahasa Indonesia</span>
|
||||
<span class="text-blue-200">• 📊 Analisis Real-time</span>
|
||||
<span class="text-blue-200">• 🎯 Personal</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.language_indonesian">🇺🇸 English Language</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.realtime">• 📊 Real-time Analysis</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.personal">• 🎯 Personal</span>
|
||||
{% if holiday_config.active_holiday %}
|
||||
<span class="text-blue-200">• {{ holiday_config.active_holiday.split()[0] }} 🎄</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.holiday">• {{ holiday_config.active_holiday.split()[0] }} 🎄</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -173,35 +174,35 @@
|
||||
<!-- Quick Stats -->
|
||||
<div class="quick-stats">
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Total Sesi</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.total_sessions">Total Sessions</h3>
|
||||
<div class="text-3xl font-bold text-blue-600">{{ total_sessions or 0 }}</div>
|
||||
<p class="text-sm text-gray-500 mt-1">sesi trading</p>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.sessions">trading sessions</p>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Win Rate</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.win_rate">Win Rate</h3>
|
||||
<div class="text-3xl font-bold {{ 'text-green-600' if (win_rate or 0) >= 60 else 'text-red-600' if (win_rate or 0) < 40 else 'text-yellow-600' }}">{{ "%.1f"|format(win_rate or 0) }}%</div>
|
||||
<p class="text-sm text-gray-500 mt-1">sesi profit</p>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.profit_sessions">profit sessions</p>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Hari Ini</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.today">Today</h3>
|
||||
{% if today_session %}
|
||||
{% set profit_loss = today_session.get('profit_loss', today_session.get('total_profit_loss', 0)) %}
|
||||
<div class="text-2xl font-bold {{ 'profit-positive' if profit_loss > 0 else 'profit-negative' if profit_loss < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(profit_loss) }}
|
||||
</div>
|
||||
<span class="emotion-badge emotion-{{ today_session.get('emotions', 'netral') }}">{{ (today_session.get('emotions', 'netral')|title) }}</span>
|
||||
<span class="emotion-badge emotion-{{ today_session.get('emotions', 'neutral') }}">{{ (today_session.get('emotions', 'neutral')|title) }}</span>
|
||||
{% else %}
|
||||
<div class="text-2xl font-bold text-gray-400">-</div>
|
||||
<p class="text-sm text-gray-500 mt-1">belum trading</p>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.not_traded">not traded yet</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Status AI</h3>
|
||||
<div class="text-2xl font-bold text-green-600">🤖 Aktif</div>
|
||||
<p class="text-sm text-gray-500 mt-1">siap menganalisis</p>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.ai_status">AI Status</h3>
|
||||
<div class="text-2xl font-bold text-green-600" data-i18n="ai_mentor.ai_active">🤖 Active</div>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.ai_ready">ready to analyze</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -211,7 +212,7 @@
|
||||
<div class="bg-white rounded-lg shadow-md p-6">
|
||||
<h2 class="text-xl font-bold mb-4 flex items-center">
|
||||
<span class="mr-2">📊</span>
|
||||
Trading Hari Ini
|
||||
<span data-i18n="ai_mentor.today_trading">Today's Trading</span>
|
||||
</h2>
|
||||
|
||||
{% if today_session %}
|
||||
@@ -219,43 +220,43 @@
|
||||
{% set total_trades = today_session.get('total_trades', today_session.get('trades_count', 0)) %}
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-600">Total Trades:</span>
|
||||
<span class="text-gray-600" data-i18n="ai_mentor.total_trades">Total Trades:</span>
|
||||
<span class="font-semibold">{{ total_trades }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-600">P&L:</span>
|
||||
<span class="text-gray-600" data-i18n="ai_mentor.pnl">P&L:</span>
|
||||
<span class="font-semibold {{ 'profit-positive' if profit_loss > 0 else 'profit-negative' if profit_loss < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(profit_loss) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-gray-600">Emosi:</span>
|
||||
<span class="emotion-badge emotion-{{ today_session.get('emotions', 'netral') }}">{{ (today_session.get('emotions', 'netral')|title) }}</span>
|
||||
<span class="text-gray-600" data-i18n="ai_mentor.emotion">Emotion:</span>
|
||||
<span class="emotion-badge emotion-{{ today_session.get('emotions', 'neutral') }}">{{ (today_session.get('emotions', 'neutral')|title) }}</span>
|
||||
</div>
|
||||
|
||||
{% if today_session.get('personal_notes') %}
|
||||
<div class="ai-insight">
|
||||
<p class="text-sm"><strong>Catatan Anda:</strong></p>
|
||||
<p class="text-sm"><strong data-i18n="ai_mentor.your_notes">Your Notes:</strong></p>
|
||||
<p class="text-gray-700 italic">"{{ today_session.get('personal_notes') }}"</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mt-4 space-y-2">
|
||||
<a href="{{ url_for('ai_mentor.today_report') }}" class="block w-full bg-blue-600 text-white text-center py-2 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
🧠 Lihat Analisis AI Lengkap
|
||||
<span data-i18n="ai_mentor.view_full_analysis">🧠 View Full AI Analysis</span>
|
||||
</a>
|
||||
<button onclick="openQuickFeedback()" class="block w-full bg-green-600 text-white text-center py-2 rounded-lg hover:bg-green-700 transition-colors">
|
||||
✏️ Update Emosi & Catatan
|
||||
<span data-i18n="ai_mentor.update_emotion">✏️ Update Emotion & Notes</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-8">
|
||||
<div class="text-6xl mb-4">📈</div>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Belum Ada Trading Hari Ini</h3>
|
||||
<p class="text-gray-500 mb-4">Mulai trading untuk mendapatkan analisis AI yang personal!</p>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.not_traded_today">No Trading Today Yet</h3>
|
||||
<p class="text-gray-500 mb-4" data-i18n="ai_mentor.start_trading">Start trading to get personalized AI analysis!</p>
|
||||
<button onclick="openQuickFeedback()" class="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
📝 Catat Emosi Trading
|
||||
<span data-i18n="ai_mentor.record_emotion">📝 Record Trading Emotion</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -265,7 +266,7 @@
|
||||
<div class="bg-white rounded-lg shadow-md p-6">
|
||||
<h2 class="text-xl font-bold mb-4 flex items-center">
|
||||
<span class="mr-2">🤖</span>
|
||||
AI Insights Terbaru
|
||||
<span data-i18n="ai_mentor.ai_insights">Latest AI Insights</span>
|
||||
</h2>
|
||||
|
||||
{% if recent_reports %}
|
||||
@@ -280,21 +281,21 @@
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">{{ (report.get('motivation', 'No insights available'))[:100] }}{% if (report.get('motivation', '')|length) > 100 %}...{% endif %}</p>
|
||||
<span class="emotion-badge emotion-{{ report.get('emotions', 'netral') }} text-xs mt-1 inline-block">{{ (report.get('emotions', 'netral')|title) }}</span>
|
||||
<span class="emotion-badge emotion-{{ report.get('emotions', 'neutral') }} text-xs mt-1 inline-block">{{ (report.get('emotions', 'neutral')|title) }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<a href="{{ url_for('ai_mentor.history') }}" class="block w-full bg-gray-600 text-white text-center py-2 rounded-lg hover:bg-gray-700 transition-colors">
|
||||
📚 Lihat Semua Riwayat
|
||||
<span data-i18n="ai_mentor.view_history">📚 View All History</span>
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-8">
|
||||
<div class="text-6xl mb-4">🤖</div>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">AI Siap Membantu!</h3>
|
||||
<p class="text-gray-500">Mulai trading untuk mendapatkan insight personal dari AI mentor Anda.</p>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.no_insights">AI is Ready to Help!</h3>
|
||||
<p class="text-gray-500" data-i18n="ai_mentor.start_trading_insights">Start trading to get personalized insights from your AI mentor.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -304,46 +305,46 @@
|
||||
<div class="bg-gradient-to-r from-green-400 to-blue-500 rounded-lg shadow-md p-6 text-white">
|
||||
<h2 class="text-xl font-bold mb-4 flex items-center">
|
||||
<span class="mr-2">💡</span>
|
||||
Tips Harian dari AI Mentor
|
||||
<span data-i18n="ai_mentor.daily_tips">Daily Tips from AI Mentor</span>
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-4">
|
||||
<h4 class="font-semibold mb-2">🎯 Konsistensi</h4>
|
||||
<p class="text-sm">"Profit kecil tapi konsisten lebih baik daripada profit besar sekali terus loss."</p>
|
||||
<h4 class="font-semibold mb-2" data-i18n="ai_mentor.consistency">🎯 Consistency</h4>
|
||||
<p class="text-sm" data-i18n="ai_mentor.consistency_tip">"Small but consistent profits are better than one big profit followed by losses."</p>
|
||||
</div>
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-4">
|
||||
<h4 class="font-semibold mb-2">🛡️ Risk Management</h4>
|
||||
<p class="text-sm">"Jangan pernah risiko lebih dari 2% modal per trade. Modal adalah nyawa trader!"</p>
|
||||
<h4 class="font-semibold mb-2" data-i18n="ai_mentor.risk_management">🛡️ Risk Management</h4>
|
||||
<p class="text-sm" data-i18n="ai_mentor.risk_tip">"Never risk more than 2% of your capital per trade. Capital is a trader's life!"</p>
|
||||
</div>
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-4">
|
||||
<h4 class="font-semibold mb-2">🧠 Emosi</h4>
|
||||
<p class="text-sm">"Trading dengan emosi tenang adalah kunci trader profesional. Istirahat jika frustasi."</p>
|
||||
<h4 class="font-semibold mb-2" data-i18n="ai_mentor.emotions">🧠 Emotions</h4>
|
||||
<p class="text-sm" data-i18n="ai_mentor.emotion_tip">"Trading with a calm emotion is the key to professional trading. Take a break if frustrated."</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Floating Chat Button -->
|
||||
<button class="floating-chat-btn" onclick="openQuickFeedback()" title="Chat dengan AI Mentor">
|
||||
<button class="floating-chat-btn" onclick="openQuickFeedback()" title="Chat with AI Mentor">
|
||||
💬
|
||||
</button>
|
||||
|
||||
<!-- Quick Feedback Modal (akan dimuat dengan AJAX) -->
|
||||
<!-- Quick Feedback Modal (will be loaded with AJAX) -->
|
||||
<div id="quickFeedbackModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
|
||||
<div class="flex items-center justify-center min-h-screen p-4">
|
||||
<div class="bg-white rounded-lg max-w-md w-full p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="text-lg font-bold">💬 Chat dengan AI Mentor</h3>
|
||||
<h3 class="text-lg font-bold" data-i18n="ai_mentor.chat_with_mentor">💬 Chat with AI Mentor</h3>
|
||||
<button onclick="closeQuickFeedback()" class="text-gray-500 hover:text-gray-700">
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<div id="quickFeedbackContent">
|
||||
<!-- Content akan dimuat dengan AJAX -->
|
||||
<!-- Content will be loaded with AJAX -->
|
||||
<div class="text-center py-4">
|
||||
<div class="text-4xl mb-2">🤖</div>
|
||||
<p class="text-gray-600">Fitur sedang dikembangkan...</p>
|
||||
<p class="text-sm text-gray-500 mt-2">Sementara ini, gunakan dashboard untuk melihat analisis AI.</p>
|
||||
<p class="text-gray-600" data-i18n="ai_mentor.developing">Feature under development...</p>
|
||||
<p class="text-sm text-gray-500 mt-2" data-i18n="ai_mentor.use_dashboard">For now, use the dashboard to view AI analysis.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}📊 Riwayat AI Mentor - QuantumBotX{% endblock %}
|
||||
{% block title_key %}ai_mentor.history_page_title{% endblock %}
|
||||
{% block title %}📊 AI Mentor History{% endblock %}
|
||||
|
||||
{% block head_extra %}
|
||||
<style>
|
||||
@@ -35,11 +36,11 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.emotion-tenang { background-color: #10b981; color: white; }
|
||||
.emotion-serakah { background-color: #f59e0b; color: white; }
|
||||
.emotion-takut { background-color: #8b5cf6; color: white; }
|
||||
.emotion-frustasi { background-color: #ef4444; color: white; }
|
||||
.emotion-netral { background-color: #6b7280; color: white; }
|
||||
.emotion-calm { background-color: #10b981; color: white; }
|
||||
.emotion-greedy { background-color: #f59e0b; color: white; }
|
||||
.emotion-fear { background-color: #8b5cf6; color: white; }
|
||||
.emotion-frustrated { background-color: #ef4444; color: white; }
|
||||
.emotion-neutral { background-color: #6b7280; color: white; }
|
||||
|
||||
.profit-positive { color: #10b981; font-weight: bold; }
|
||||
.profit-negative { color: #ef4444; font-weight: bold; }
|
||||
@@ -143,58 +144,58 @@
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Header -->
|
||||
<div class="mentor-card">
|
||||
<h1 class="text-3xl font-bold mb-2">📊 Riwayat AI Mentor Trading</h1>
|
||||
<p class="text-blue-100 text-lg">Analisis lengkap perjalanan trading Anda dengan bantuan AI Indonesia</p>
|
||||
<h1 class="text-3xl font-bold mb-2" data-i18n="ai_mentor.history_title">📊 AI Mentor Trading History</h1>
|
||||
<p class="text-blue-100 text-lg" data-i18n="ai_mentor.history_subtitle">Complete trading journey analysis with AI assistance</p>
|
||||
<div class="mt-4 flex items-center space-x-4">
|
||||
<span class="text-blue-200">🇮🇩 Bahasa Indonesia</span>
|
||||
<span class="text-blue-200">• 📈 Analisis Performa</span>
|
||||
<span class="text-blue-200">• 🧠 AI Insights</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.language">🇺🇸 English Language</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.performance_analysis">• 📈 Performance Analysis</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.ai_insights">• 🧠 AI Insights</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Statistics -->
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Total Laporan</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.total_reports">Total Reports</h3>
|
||||
<div class="text-3xl font-bold text-blue-600">{{ reports|length if reports else 0 }}</div>
|
||||
<p class="text-sm text-gray-500 mt-1">sesi dianalisis</p>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.sessions_analyzed">sessions analyzed</p>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Periode</h3>
|
||||
<div class="text-2xl font-bold text-purple-600">{{ days }} hari</div>
|
||||
<p class="text-sm text-gray-500 mt-1">riwayat terakhir</p>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.period">Period</h3>
|
||||
<div class="text-2xl font-bold text-purple-600">{{ days }} <span data-i18n="ai_mentor.days">days</span></div>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.last_history">last history</p>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Performa</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.performance">Performance</h3>
|
||||
{% set total_profit = reports|sum(attribute='profit_loss') if reports else 0 %}
|
||||
<div class="text-2xl font-bold {{ 'profit-positive' if total_profit > 0 else 'profit-negative' if total_profit < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(total_profit) }}
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 mt-1">total P&L</p>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.total_pnl">total P&L</p>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Win Rate</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2" data-i18n="ai_mentor.win_rate">Win Rate</h3>
|
||||
{% set profitable_sessions = reports|selectattr('profit_loss', '>', 0)|list|length if reports else 0 %}
|
||||
{% set win_rate = (profitable_sessions / reports|length * 100) if reports|length > 0 else 0 %}
|
||||
<div class="text-2xl font-bold {{ 'text-green-600' if win_rate >= 60 else 'text-red-600' if win_rate < 40 else 'text-yellow-600' }}">
|
||||
{{ "%.1f"|format(win_rate) }}%
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 mt-1">sesi profit</p>
|
||||
<p class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.profit_sessions">profit sessions</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Date Filter -->
|
||||
<div class="date-filter">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-lg font-semibold text-gray-700">Filter Periode</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-700" data-i18n="ai_mentor.period_filter">Period Filter</h3>
|
||||
<div class="flex space-x-2">
|
||||
<button class="filter-btn {{ 'active' if days == 7 }}" onclick="changeFilter(7)">7 Hari</button>
|
||||
<button class="filter-btn {{ 'active' if days == 30 }}" onclick="changeFilter(30)">30 Hari</button>
|
||||
<button class="filter-btn {{ 'active' if days == 90 }}" onclick="changeFilter(90)">90 Hari</button>
|
||||
<button class="filter-btn {{ 'active' if days == 365 }}" onclick="changeFilter(365)">1 Tahun</button>
|
||||
<button class="filter-btn {{ 'active' if days == 7 }}" onclick="changeFilter(7)" data-i18n="ai_mentor.filter_7_days">7 Days</button>
|
||||
<button class="filter-btn {{ 'active' if days == 30 }}" onclick="changeFilter(30)" data-i18n="ai_mentor.filter_30_days">30 Days</button>
|
||||
<button class="filter-btn {{ 'active' if days == 90 }}" onclick="changeFilter(90)" data-i18n="ai_mentor.filter_90_days">90 Days</button>
|
||||
<button class="filter-btn {{ 'active' if days == 365 }}" onclick="changeFilter(365)" data-i18n="ai_mentor.filter_1_year">1 Year</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -210,7 +211,7 @@
|
||||
📅 {{ (report.date if report.date else report.session_date).strftime('%d %B %Y') }}
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 mt-1">
|
||||
{{ (report.date if report.date else report.session_date).strftime('%A') }} - {{ 'Sesi Trading' }}
|
||||
{{ (report.date if report.date else report.session_date).strftime('%A') }} - <span data-i18n="ai_mentor.trading_session">Trading Session</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="session-performance">
|
||||
@@ -220,7 +221,7 @@
|
||||
</span>
|
||||
{% endif %}
|
||||
<span class="trades-count">
|
||||
{{ report.total_trades or report.trades|length or 0 }} trades
|
||||
{{ report.total_trades or report.trades|length or 0 }} <span data-i18n="ai_mentor.trades">trades</span>
|
||||
</span>
|
||||
<div class="text-xl font-bold {{ 'profit-positive' if (report.profit_loss or 0) > 0 else 'profit-negative' if (report.profit_loss or 0) < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(report.profit_loss or 0) }}
|
||||
@@ -230,18 +231,18 @@
|
||||
|
||||
{% if report.motivation %}
|
||||
<div class="ai-summary">
|
||||
<strong>🤖 AI Summary:</strong> {{ report.motivation[:200] }}{% if report.motivation|length > 200 %}...{% endif %}
|
||||
<strong data-i18n="ai_mentor.ai_summary">🤖 AI Summary:</strong> {{ report.motivation[:200] }}{% if report.motivation|length > 200 %}...{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex items-center justify-between mt-3">
|
||||
<div class="text-sm text-gray-500">
|
||||
{% if report.market_conditions %}
|
||||
🌐 {{ report.market_conditions|title }} Market
|
||||
🌐 {{ report.market_conditions|title }} <span data-i18n="ai_mentor.market">Market</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="text-blue-600 text-sm font-medium">
|
||||
Lihat Detail →
|
||||
<div class="text-blue-600 text-sm font-medium" data-i18n="ai_mentor.view_details">
|
||||
View Details →
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -251,8 +252,8 @@
|
||||
<!-- Pagination (jika diperlukan) -->
|
||||
{% if reports|length >= 10 %}
|
||||
<div class="mt-8 text-center">
|
||||
<button class="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
Muat Lebih Banyak
|
||||
<button class="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 transition-colors" data-i18n="ai_mentor.load_more">
|
||||
Load More
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -261,16 +262,16 @@
|
||||
<!-- Empty State -->
|
||||
<div class="empty-state">
|
||||
<div class="text-6xl mb-4">📊</div>
|
||||
<h3 class="text-xl font-semibold text-gray-700 mb-2">Belum Ada Riwayat Trading</h3>
|
||||
<p class="text-gray-500 mb-6">
|
||||
Mulai trading untuk mendapatkan analisis AI dan saran personal dari mentor digital Anda.
|
||||
<h3 class="text-xl font-semibold text-gray-700 mb-2" data-i18n="ai_mentor.no_history">No Trading History Yet</h3>
|
||||
<p class="text-gray-500 mb-6" data-i18n="ai_mentor.start_trading_for_history">
|
||||
Start trading to get AI analysis and personalized advice from your digital mentor.
|
||||
</p>
|
||||
<div class="space-x-4">
|
||||
<a href="/ai-mentor" class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors inline-block">
|
||||
Mulai Trading Session
|
||||
<span data-i18n="ai_mentor.start_trading_session">Start Trading Session</span>
|
||||
</a>
|
||||
<a href="/trading_bots" class="bg-gray-600 text-white px-6 py-3 rounded-lg hover:bg-gray-700 transition-colors inline-block">
|
||||
Lihat Trading Bots
|
||||
<span data-i18n="ai_mentor.view_trading_bots">View Trading Bots</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
<!-- Quick feedback form untuk modal AI mentor -->
|
||||
<form id=\"quickFeedbackForm\" onsubmit=\"submitQuickFeedback(event)\">
|
||||
<div class=\"space-y-4\">
|
||||
<form id="quickFeedbackForm" onsubmit="submitQuickFeedback(event)">
|
||||
<div class="space-y-4">
|
||||
<!-- Emosi Saat Ini -->
|
||||
<div>
|
||||
<label class=\"block text-sm font-semibold text-gray-700 mb-2\">🧠 Bagaimana perasaan Anda saat trading hari ini?</label>
|
||||
<div class=\"grid grid-cols-2 gap-2\">
|
||||
<button type=\"button\" onclick=\"selectEmotion('tenang')\" class=\"emotion-btn p-3 border rounded-lg text-left hover:bg-blue-50 focus:ring-2 focus:ring-blue-500\" data-emotion=\"tenang\">
|
||||
<div class=\"font-semibold text-green-600\">😌 Tenang</div>
|
||||
<div class=\"text-xs text-gray-500\">Pikiran jernih, tidak terburu-buru</div>
|
||||
<label class="block text-sm font-semibold text-gray-700 mb-2" data-i18n="ai_mentor.how_are_you_feeling">🧠 Bagaimana perasaan Anda saat trading hari ini?</label>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button type="button" onclick="selectEmotion('tenang')" class="emotion-btn p-3 border rounded-lg text-left hover:bg-blue-50 focus:ring-2 focus:ring-blue-500" data-emotion="tenang">
|
||||
<div class="font-semibold text-green-600" data-i18n="ai_mentor.emotion_calm">😌 Tenang</div>
|
||||
<div class="text-xs text-gray-500" data-i18n="ai_mentor.calm_description">Pikiran jernih, tidak terburu-buru</div>
|
||||
</button>
|
||||
<button type=\"button\" onclick=\"selectEmotion('serakah')\" class=\"emotion-btn p-3 border rounded-lg text-left hover:bg-yellow-50 focus:ring-2 focus:ring-yellow-500\" data-emotion=\"serakah\">
|
||||
<div class=\"font-semibold text-yellow-600\">🤑 Serakah</div>
|
||||
<div class=\"text-xs text-gray-500\">Ingin profit besar, agresif</div>
|
||||
<button type="button" onclick="selectEmotion('serakah')" class="emotion-btn p-3 border rounded-lg text-left hover:bg-yellow-50 focus:ring-2 focus:ring-yellow-500" data-emotion="serakah">
|
||||
<div class="font-semibold text-yellow-600" data-i18n="ai_mentor.emotion_greedy">🤑 Serakah</div>
|
||||
<div class="text-xs text-gray-500" data-i18n="ai_mentor.greedy_description">Ingin profit besar, agresif</div>
|
||||
</button>
|
||||
<button type=\"button\" onclick=\"selectEmotion('takut')\" class=\"emotion-btn p-3 border rounded-lg text-left hover:bg-purple-50 focus:ring-2 focus:ring-purple-500\" data-emotion=\"takut\">
|
||||
<div class=\"font-semibold text-purple-600\">😰 Takut</div>
|
||||
<div class=\"text-xs text-gray-500\">Khawatir loss, ragu-ragu</div>
|
||||
<button type="button" onclick="selectEmotion('takut')" class="emotion-btn p-3 border rounded-lg text-left hover:bg-purple-50 focus:ring-2 focus:ring-purple-500" data-emotion="takut">
|
||||
<div class="font-semibold text-purple-600" data-i18n="ai_mentor.emotion_fearful">😰 Takut</div>
|
||||
<div class="text-xs text-gray-500" data-i18n="ai_mentor.fearful_description">Khawatir loss, ragu-ragu</div>
|
||||
</button>
|
||||
<button type=\"button\" onclick=\"selectEmotion('frustasi')\" class=\"emotion-btn p-3 border rounded-lg text-left hover:bg-red-50 focus:ring-2 focus:ring-red-500\" data-emotion=\"frustasi\">
|
||||
<div class=\"font-semibold text-red-600\">😤 Frustasi</div>
|
||||
<div class=\"text-xs text-gray-500\">Kesal karena loss beruntun</div>
|
||||
<button type="button" onclick="selectEmotion('frustasi')" class="emotion-btn p-3 border rounded-lg text-left hover:bg-red-50 focus:ring-2 focus:ring-red-500" data-emotion="frustasi">
|
||||
<div class="font-semibold text-red-600" data-i18n="ai_mentor.emotion_frustrated">😤 Frustasi</div>
|
||||
<div class="text-xs text-gray-500" data-i18n="ai_mentor.frustrated_description">Kesal karena loss beruntun</div>
|
||||
</button>
|
||||
</div>
|
||||
<input type=\"hidden\" id=\"selectedEmotion\" name=\"emotions\" value=\"netral\" required>
|
||||
<input type="hidden" id="selectedEmotion" name="emotions" value="netral" required>
|
||||
</div>
|
||||
|
||||
<!-- P&L Saat Ini -->
|
||||
<div>
|
||||
<label for=\"currentPnL\" class=\"block text-sm font-semibold text-gray-700 mb-2\">💰 P&L Hari Ini (USD)</label>
|
||||
<input type=\"number\" id=\"currentPnL\" name=\"current_pnl\" step=\"0.01\"
|
||||
class=\"w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"
|
||||
placeholder=\"Contoh: 25.50 atau -15.30\">
|
||||
<label for="currentPnL" class="block text-sm font-semibold text-gray-700 mb-2" data-i18n="ai_mentor.today_pnl">💰 P&L Hari Ini (USD)</label>
|
||||
<input type="number" id="currentPnL" name="current_pnl" step="0.01"
|
||||
class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
placeholder="Contoh: 25.50 atau -15.30" data-i18n="ai_mentor.pnl_placeholder">
|
||||
</div>
|
||||
|
||||
<!-- Catatan Personal -->
|
||||
<div>
|
||||
<label for=\"personalNotes\" class=\"block text-sm font-semibold text-gray-700 mb-2\">📝 Catatan Trading Hari Ini</label>
|
||||
<textarea id=\"personalNotes\" name=\"notes\" rows=\"3\"
|
||||
class=\"w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"
|
||||
placeholder=\"Contoh: Hari ini fokus EURUSD, pakai SL ketat. Market agak volatile karena berita NFP...\"></textarea>
|
||||
<label for="personalNotes" class="block text-sm font-semibold text-gray-700 mb-2" data-i18n="ai_mentor.today_notes">📝 Catatan Trading Hari Ini</label>
|
||||
<textarea id="personalNotes" name="notes" rows="3"
|
||||
class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
placeholder="Contoh: Hari ini fokus EURUSD, pakai SL ketat. Market agak volatile karena berita NFP..." data-i18n="ai_mentor.notes_placeholder"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class=\"flex space-x-3\">
|
||||
<button type=\"button\" onclick=\"getInstantFeedback()\"
|
||||
class=\"flex-1 bg-green-600 text-white py-3 px-4 rounded-lg hover:bg-green-700 transition-colors\">
|
||||
⚡ Feedback Instan
|
||||
<div class="flex space-x-3">
|
||||
<button type="button" onclick="getInstantFeedback()"
|
||||
class="flex-1 bg-green-600 text-white py-3 px-4 rounded-lg hover:bg-green-700 transition-colors">
|
||||
<span data-i18n="ai_mentor.instant_feedback">⚡ Feedback Instan</span>
|
||||
</button>
|
||||
<button type=\"submit\"
|
||||
class=\"flex-1 bg-blue-600 text-white py-3 px-4 rounded-lg hover:bg-blue-700 transition-colors\">
|
||||
💾 Simpan Data
|
||||
<button type="submit"
|
||||
class="flex-1 bg-blue-600 text-white py-3 px-4 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
<span data-i18n="ai_mentor.save_data">💾 Simpan Data</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Instant Feedback Area -->
|
||||
<div id=\"instantFeedback\" class=\"mt-4 hidden\">
|
||||
<div class=\"bg-gradient-to-r from-blue-50 to-green-50 border border-blue-200 rounded-lg p-4\">
|
||||
<h4 class=\"font-bold text-blue-800 mb-2\">🤖 Feedback AI Mentor:</h4>
|
||||
<div id=\"feedbackContent\" class=\"text-gray-700\"></div>
|
||||
<div id="instantFeedback" class="mt-4 hidden">
|
||||
<div class="bg-gradient-to-r from-blue-50 to-green-50 border border-blue-200 rounded-lg p-4">
|
||||
<h4 class="font-bold text-blue-800 mb-2" data-i18n="ai_mentor.ai_feedback">🤖 Feedback AI Mentor:</h4>
|
||||
<div id="feedbackContent" class="text-gray-700"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@ function selectEmotion(emotion) {
|
||||
});
|
||||
|
||||
// Add selection to clicked button
|
||||
const clickedBtn = document.querySelector(`[data-emotion=\"${emotion}\"]`);
|
||||
const clickedBtn = document.querySelector(`[data-emotion="${emotion}"]`);
|
||||
clickedBtn.classList.add('ring-2', 'bg-blue-100', 'border-blue-500');
|
||||
|
||||
// Update hidden input
|
||||
@@ -92,7 +92,7 @@ function getInstantFeedback() {
|
||||
const feedbackDiv = document.getElementById('instantFeedback');
|
||||
const contentDiv = document.getElementById('feedbackContent');
|
||||
feedbackDiv.classList.remove('hidden');
|
||||
contentDiv.innerHTML = '<div class=\"animate-pulse\">🤖 AI sedang menganalisis trading Anda...</div>';
|
||||
contentDiv.innerHTML = '<div class="animate-pulse" data-i18n="ai_mentor.analyzing">🤖 AI sedang menganalisis trading Anda...</div>';
|
||||
|
||||
fetch('/ai-mentor/api/generate-instant-feedback', {
|
||||
method: 'POST',
|
||||
@@ -106,30 +106,30 @@ function getInstantFeedback() {
|
||||
if (data.success) {
|
||||
const feedback = data.feedback;
|
||||
contentDiv.innerHTML = `
|
||||
<div class=\"space-y-3\">
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<strong class=\"text-blue-700\">🧠 Analisis Emosi:</strong>
|
||||
<p class=\"text-gray-700\">${feedback.emotional_analysis}</p>
|
||||
<strong class="text-blue-700" data-i18n="ai_mentor.emotional_analysis">🧠 Analisis Emosi:</strong>
|
||||
<p class="text-gray-700">${feedback.emotional_analysis}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong class=\"text-green-700\">💪 Motivasi:</strong>
|
||||
<p class=\"text-gray-700\">${feedback.motivation}</p>
|
||||
<strong class="text-green-700" data-i18n="ai_mentor.motivation">💪 Motivasi:</strong>
|
||||
<p class="text-gray-700">${feedback.motivation}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong class=\"text-purple-700\">💡 Tips Cepat:</strong>
|
||||
<ul class=\"list-disc pl-5 text-gray-700\">
|
||||
<strong class="text-purple-700" data-i18n="ai_mentor.quick_tips">💡 Tips Cepat:</strong>
|
||||
<ul class="list-disc pl-5 text-gray-700">
|
||||
${feedback.quick_tips.map(tip => `<li>${tip}</li>`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
contentDiv.innerHTML = `<div class=\"text-red-600\">❌ ${data.message}</div>`;
|
||||
contentDiv.innerHTML = `<div class="text-red-600">❌ ${data.message}</div>`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
contentDiv.innerHTML = '<div class=\"text-red-600\">❌ Gagal mendapatkan feedback. Silakan coba lagi.</div>';
|
||||
contentDiv.innerHTML = '<div class="text-red-600" data-i18n="ai_mentor.failed_feedback">❌ Gagal mendapatkan feedback. Silakan coba lagi.</div>';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}ai_mentor.session_detail_title{% endblock %}
|
||||
{% block title %}📈 Detail Sesi {{ session_date }} - AI Mentor{% endblock %}
|
||||
|
||||
{% block head_extra %}
|
||||
@@ -141,17 +142,17 @@
|
||||
<!-- Back Navigation -->
|
||||
<a href="/ai-mentor/history" class="back-btn">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
Kembali ke Riwayat
|
||||
<span data-i18n="ai_mentor.back_to_history">Kembali ke Riwayat</span>
|
||||
</a>
|
||||
|
||||
<!-- Header -->
|
||||
<div class="mentor-card">
|
||||
<h1 class="text-3xl font-bold mb-2">📈 Detail Sesi Trading</h1>
|
||||
<p class="text-blue-100 text-lg">{{ session_date }} - Analisis lengkap dari AI Mentor Indonesia</p>
|
||||
<h1 class="text-3xl font-bold mb-2" data-i18n="ai_mentor.session_trading_detail">📈 Detail Sesi Trading</h1>
|
||||
<p class="text-blue-100 text-lg">{{ session_date }} - <span data-i18n="ai_mentor.full_analysis">Analisis lengkap dari AI Mentor Indonesia</span></p>
|
||||
<div class="mt-4 flex items-center space-x-4">
|
||||
<span class="text-blue-200">🇮🇩 AI Analysis</span>
|
||||
<span class="text-blue-200">• 🧠 Personal Insights</span>
|
||||
<span class="text-blue-200">• 📊 Performance Review</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.ai_analysis">🇮🇩 AI Analysis</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.personal_insights">• 🧠 Personal Insights</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.performance_review">• 📊 Performance Review</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -161,12 +162,12 @@
|
||||
<div class="text-2xl font-bold {{ 'profit-positive' if session_data.total_profit_loss > 0 else 'profit-negative' if session_data.total_profit_loss < 0 else 'text-gray-600' }}">
|
||||
${{ "%.2f"|format(session_data.total_profit_loss or 0) }}
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 mt-1">Total P&L</div>
|
||||
<div class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.total_pnl">Total P&L</div>
|
||||
</div>
|
||||
|
||||
<div class="perf-stat">
|
||||
<div class="text-2xl font-bold text-blue-600">{{ session_data.trades|length if session_data.trades else 0 }}</div>
|
||||
<div class="text-sm text-gray-500 mt-1">Total Trades</div>
|
||||
<div class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.total_trades">Total Trades</div>
|
||||
</div>
|
||||
|
||||
<div class="perf-stat">
|
||||
@@ -176,7 +177,7 @@
|
||||
<div class="text-2xl font-bold {{ 'text-green-600' if win_rate >= 60 else 'text-red-600' if win_rate < 40 else 'text-yellow-600' }}">
|
||||
{{ "%.1f"|format(win_rate) }}%
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 mt-1">Win Rate</div>
|
||||
<div class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.win_rate">Win Rate</div>
|
||||
</div>
|
||||
|
||||
<div class="perf-stat">
|
||||
@@ -185,7 +186,7 @@
|
||||
{% else %}
|
||||
<div class="text-2xl font-bold text-gray-400">-</div>
|
||||
{% endif %}
|
||||
<div class="text-sm text-gray-500 mt-1">Emotional State</div>
|
||||
<div class="text-sm text-gray-500 mt-1" data-i18n="ai_mentor.emotional_state">Emotional State</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -193,7 +194,7 @@
|
||||
<div class="section-grid">
|
||||
<!-- Trading Summary -->
|
||||
<div class="session-card">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">📊 Ringkasan Trading</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.trading_summary">📊 Ringkasan Trading</h3>
|
||||
|
||||
{% if session_data.trades %}
|
||||
<div class="space-y-2">
|
||||
@@ -219,23 +220,23 @@
|
||||
{% else %}
|
||||
<div class="text-center text-gray-500 py-8">
|
||||
<i class="fas fa-chart-line text-4xl mb-4 opacity-50"></i>
|
||||
<p>Tidak ada trade yang tercatat untuk sesi ini</p>
|
||||
<p data-i18n="ai_mentor.no_trades_recorded">Tidak ada trade yang tercatat untuk sesi ini</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Market Context -->
|
||||
<div class="session-card">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">🌐 Konteks Pasar</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.market_context">🌐 Konteks Pasar</h3>
|
||||
|
||||
<div class="market-context">
|
||||
<h4 class="font-semibold mb-2">Kondisi Pasar</h4>
|
||||
<h4 class="font-semibold mb-2" data-i18n="ai_mentor.market_conditions">Kondisi Pasar</h4>
|
||||
<p>{{ session_data.market_conditions|title if session_data.market_conditions else 'Normal' }}</p>
|
||||
</div>
|
||||
|
||||
{% if session_data.personal_notes %}
|
||||
<div class="mt-4">
|
||||
<h4 class="font-semibold text-gray-700 mb-2">📝 Catatan Personal</h4>
|
||||
<h4 class="font-semibold text-gray-700 mb-2" data-i18n="ai_mentor.personal_notes">📝 Catatan Personal</h4>
|
||||
<div class="bg-gray-50 p-3 rounded-lg">
|
||||
<p class="text-gray-700">{{ session_data.personal_notes }}</p>
|
||||
</div>
|
||||
@@ -247,7 +248,7 @@
|
||||
<!-- AI Analysis Sections -->
|
||||
{% if ai_report %}
|
||||
<div class="ai-section">
|
||||
<h3 class="text-xl font-semibold mb-4">🤖 Laporan AI Mentor</h3>
|
||||
<h3 class="text-xl font-semibold mb-4" data-i18n="ai_mentor.ai_mentor_report">🤖 Laporan AI Mentor</h3>
|
||||
<div class="prose max-w-none">
|
||||
{{ ai_report|safe }}
|
||||
</div>
|
||||
@@ -258,15 +259,15 @@
|
||||
<!-- Emotional Analysis -->
|
||||
{% if analysis.emosi_vs_performa %}
|
||||
<div class="ai-section">
|
||||
<h3 class="text-xl font-semibold mb-4">💭 Analisis Emosi vs Performa</h3>
|
||||
<h3 class="text-xl font-semibold mb-4" data-i18n="ai_mentor.emotional_analysis_vs_performance">💭 Analisis Emosi vs Performa</h3>
|
||||
<div class="emotion-analysis">
|
||||
<h4 class="font-semibold mb-2">Status Emosi: {{ session_data.emotions|title if session_data.emotions else 'Tidak Tercatat' }}</h4>
|
||||
<h4 class="font-semibold mb-2" data-i18n="ai_mentor.emotional_status">Status Emosi: {{ session_data.emotions|title if session_data.emotions else 'Tidak Tercatat' }}</h4>
|
||||
<p>{{ analysis.emosi_vs_performa.feedback if analysis.emosi_vs_performa.feedback else 'Analisis emosi tidak tersedia.' }}</p>
|
||||
</div>
|
||||
|
||||
{% if analysis.emosi_vs_performa.saran %}
|
||||
<div class="mt-4">
|
||||
<h4 class="font-semibold text-gray-700 mb-2">💡 Saran Emosional</h4>
|
||||
<h4 class="font-semibold text-gray-700 mb-2" data-i18n="ai_mentor.emotional_advice">💡 Saran Emosional</h4>
|
||||
<ul class="recommendation-list">
|
||||
{% if analysis.emosi_vs_performa.saran is string %}
|
||||
<li>{{ analysis.emosi_vs_performa.saran }}</li>
|
||||
@@ -284,7 +285,7 @@
|
||||
<!-- Recommendations -->
|
||||
{% if analysis.rekomendasi %}
|
||||
<div class="ai-section">
|
||||
<h3 class="text-xl font-semibold mb-4">🎯 Rekomendasi AI</h3>
|
||||
<h3 class="text-xl font-semibold mb-4" data-i18n="ai_mentor.ai_recommendations">🎯 Rekomendasi AI</h3>
|
||||
<ul class="recommendation-list">
|
||||
{% if analysis.rekomendasi is string %}
|
||||
<li>{{ analysis.rekomendasi }}</li>
|
||||
@@ -300,7 +301,7 @@
|
||||
<!-- Motivation -->
|
||||
{% if analysis.motivasi %}
|
||||
<div class="ai-section">
|
||||
<h3 class="text-xl font-semibold mb-4">🚀 Motivasi & Inspirasi</h3>
|
||||
<h3 class="text-xl font-semibold mb-4" data-i18n="ai_mentor.motivation_inspiration">🚀 Motivasi & Inspirasi</h3>
|
||||
<div class="ai-insight">
|
||||
<p class="text-lg font-medium text-blue-800">{{ analysis.motivasi }}</p>
|
||||
</div>
|
||||
@@ -310,7 +311,7 @@
|
||||
<!-- Learning Points -->
|
||||
{% if analysis.pembelajaran %}
|
||||
<div class="ai-section">
|
||||
<h3 class="text-xl font-semibold mb-4">📚 Poin Pembelajaran</h3>
|
||||
<h3 class="text-xl font-semibold mb-4" data-i18n="ai_mentor.learning_points">📚 Poin Pembelajaran</h3>
|
||||
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||
{% if analysis.pembelajaran is string %}
|
||||
<p class="text-green-800">{{ analysis.pembelajaran }}</p>
|
||||
@@ -329,13 +330,13 @@
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex justify-center space-x-4 mt-8">
|
||||
<a href="/ai-mentor/history" class="bg-gray-600 text-white px-6 py-3 rounded-lg hover:bg-gray-700 transition-colors">
|
||||
← Kembali ke Riwayat
|
||||
<span data-i18n="ai_mentor.back_to_history_button">← Kembali ke Riwayat</span>
|
||||
</a>
|
||||
<a href="/ai-mentor" class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
Dashboard AI Mentor
|
||||
<span data-i18n="ai_mentor.ai_mentor_dashboard">Dashboard AI Mentor</span>
|
||||
</a>
|
||||
<button onclick="generateNewAnalysis()" class="bg-purple-600 text-white px-6 py-3 rounded-lg hover:bg-purple-700 transition-colors">
|
||||
🔄 Analisis Ulang
|
||||
<span data-i18n="ai_mentor.reanalyze">🔄 Analisis Ulang</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}⚙️ Pengaturan AI Mentor - QuantumBotX{% endblock %}
|
||||
{% block title_key %}ai_mentor.settings_title{% endblock %}
|
||||
{% block title %}⚙️ AI Mentor Settings{% endblock %}
|
||||
|
||||
{% block head_extra %}
|
||||
<style>
|
||||
@@ -171,23 +172,23 @@ input:checked + .slider:before {
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Header -->
|
||||
<div class="mentor-card">
|
||||
<h1 class="text-3xl font-bold mb-2">⚙️ Pengaturan AI Mentor</h1>
|
||||
<p class="text-blue-100 text-lg">Kustomisasi pengalaman AI Trading Mentor sesuai preferensi Anda</p>
|
||||
<h1 class="text-3xl font-bold mb-2" data-i18n="ai_mentor.settings_title">⚙️ Pengaturan AI Mentor</h1>
|
||||
<p class="text-blue-100 text-lg" data-i18n="ai_mentor.settings_subtitle">Kustomisasi pengalaman AI Trading Mentor sesuai preferensi Anda</p>
|
||||
<div class="mt-4 flex items-center space-x-4">
|
||||
<span class="text-blue-200">🇮🇩 Indonesia Setup</span>
|
||||
<span class="text-blue-200">• ⚡ Real-time Config</span>
|
||||
<span class="text-blue-200">• 🎯 Personal</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.indonesia_setup">🇮🇩 Indonesia Setup</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.realtime_config">• ⚡ Real-time Config</span>
|
||||
<span class="text-blue-200" data-i18n="ai_mentor.personal">• 🎯 Personal</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Language & Regional Settings -->
|
||||
<div class="settings-section">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">🌏 Bahasa & Regional</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.language_regional">🌏 Bahasa & Regional</h3>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Bahasa Interface</h4>
|
||||
<p class="text-sm text-gray-500">Pilih bahasa untuk AI Mentor</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.interface_language">Bahasa Interface</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.language_choice">Pilih bahasa untuk AI Mentor</p>
|
||||
</div>
|
||||
<div class="language-selector">
|
||||
<div class="language-option active" data-lang="id">🇮🇩 Indonesia</div>
|
||||
@@ -197,18 +198,18 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Zona Waktu</h4>
|
||||
<p class="text-sm text-gray-500">Zona waktu untuk analisis trading</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.timezone">Zona Waktu</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.timezone_description">Zona waktu untuk analisis trading</p>
|
||||
</div>
|
||||
<div class="timezone-display">
|
||||
<div class="timezone-display" data-i18n="ai_mentor.timezone_wib">
|
||||
WIB (UTC+7) - Jakarta Time
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Format Mata Uang</h4>
|
||||
<p class="text-sm text-gray-500">Format tampilan profit/loss</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.currency_format">Format Mata Uang</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.currency_display">Format tampilan profit/loss</p>
|
||||
</div>
|
||||
<select class="time-input" style="width: 150px;">
|
||||
<option value="USD">USD ($)</option>
|
||||
@@ -220,12 +221,12 @@ input:checked + .slider:before {
|
||||
|
||||
<!-- AI Behavior Settings -->
|
||||
<div class="settings-section">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">🧠 Perilaku AI Mentor</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.ai_behavior">🧠 Perilaku AI Mentor</h3>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Analisis Otomatis</h4>
|
||||
<p class="text-sm text-gray-500">AI menganalisis setiap sesi trading secara otomatis</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.automatic_analysis">Analisis Otomatis</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.automatic_analysis_description">AI menganalisis setiap sesi trading secara otomatis</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" checked>
|
||||
@@ -235,8 +236,8 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Feedback Emosional</h4>
|
||||
<p class="text-sm text-gray-500">AI memberikan feedback berdasarkan kondisi emosi</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.emotional_feedback">Feedback Emosional</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.emotional_feedback_description">AI memberikan feedback berdasarkan kondisi emosi</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" checked>
|
||||
@@ -246,8 +247,8 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Motivasi Harian</h4>
|
||||
<p class="text-sm text-gray-500">Terima pesan motivasi setiap hari</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.daily_motivation">Motivasi Harian</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.daily_motivation_description">Terima pesan motivasi setiap hari</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" checked>
|
||||
@@ -257,36 +258,36 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Level Detail Analisis</h4>
|
||||
<p class="text-sm text-gray-500">Tingkat detail feedback AI</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.analysis_detail_level">Level Detail Analisis</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.analysis_detail_description">Tingkat detail feedback AI</p>
|
||||
</div>
|
||||
<select class="time-input" style="width: 150px;">
|
||||
<option value="basic">Basic</option>
|
||||
<option value="detailed" selected>Detailed</option>
|
||||
<option value="expert">Expert</option>
|
||||
<option value="basic" data-i18n="ai_mentor.basic">Basic</option>
|
||||
<option value="detailed" selected data-i18n="ai_mentor.detailed">Detailed</option>
|
||||
<option value="expert" data-i18n="ai_mentor.expert">Expert</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notification Settings -->
|
||||
<div class="settings-section">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">🔔 Notifikasi</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.notifications">🔔 Notifikasi</h3>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Laporan Harian</h4>
|
||||
<p class="text-sm text-gray-500">Waktu pengiriman laporan AI harian</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.daily_report">Laporan Harian</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.daily_report_time">Waktu pengiriman laporan AI harian</p>
|
||||
</div>
|
||||
<div class="notification-time">
|
||||
<input type="time" class="time-input" value="20:00">
|
||||
<span class="text-sm text-gray-500">WIB</span>
|
||||
<span class="text-sm text-gray-500" data-i18n="ai_mentor.timezone_wib_short">WIB</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Reminder Trading</h4>
|
||||
<p class="text-sm text-gray-500">Pengingat untuk input emosi dan catatan</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.trading_reminder">Reminder Trading</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.trading_reminder_description">Pengingat untuk input emosi dan catatan</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" checked>
|
||||
@@ -296,8 +297,8 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Alert Overtrading</h4>
|
||||
<p class="text-sm text-gray-500">Peringatan jika terlalu banyak trading</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.overtrading_alert">Alert Overtrading</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.overtrading_alert_description">Peringatan jika terlalu banyak trading</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox">
|
||||
@@ -308,12 +309,12 @@ input:checked + .slider:before {
|
||||
|
||||
<!-- Cultural Preferences -->
|
||||
<div class="settings-section">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">🎭 Preferensi Budaya</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.cultural_preferences">🎭 Preferensi Budaya</h3>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Mode Liburan Otomatis</h4>
|
||||
<p class="text-sm text-gray-500">Aktifkan mode Ramadan dan Natal secara otomatis</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.automatic_holiday_mode">Mode Liburan Otomatis</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.automatic_holiday_mode_description">Aktifkan mode Ramadan dan Natal secara otomatis</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" checked>
|
||||
@@ -323,8 +324,8 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Penyesuaian Risk Ramadan</h4>
|
||||
<p class="text-sm text-gray-500">Kurangi risk otomatis selama bulan Ramadan</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.ramadan_risk_adjustment">Penyesuaian Risk Ramadan</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.ramadan_risk_adjustment_description">Kurangi risk otomatis selama bulan Ramadan</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" checked>
|
||||
@@ -334,8 +335,8 @@ input:checked + .slider:before {
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Pause Trading Sahur/Iftar</h4>
|
||||
<p class="text-sm text-gray-500">Hentikan trading otomatis saat waktu sahur dan iftar</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.sahur_iftar_pause">Pause Trading Sahur/Iftar</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.sahur_iftar_pause_description">Hentikan trading otomatis saat waktu sahur dan iftar</p>
|
||||
</div>
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox">
|
||||
@@ -346,47 +347,47 @@ input:checked + .slider:before {
|
||||
|
||||
<!-- Data & Privacy -->
|
||||
<div class="settings-section">
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4">🔒 Data & Privacy</h3>
|
||||
<h3 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ai_mentor.data_privacy">🔒 Data & Privacy</h3>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Simpan Riwayat AI</h4>
|
||||
<p class="text-sm text-gray-500">Berapa lama menyimpan analisis AI</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.save_ai_history">Simpan Riwayat AI</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.save_ai_history_description">Berapa lama menyimpan analisis AI</p>
|
||||
</div>
|
||||
<select class="time-input" style="width: 150px;">
|
||||
<option value="30">30 Hari</option>
|
||||
<option value="90" selected>90 Hari</option>
|
||||
<option value="365">1 Tahun</option>
|
||||
<option value="unlimited">Unlimited</option>
|
||||
<option value="30" data-i18n="ai_mentor.30_days">30 Hari</option>
|
||||
<option value="90" selected data-i18n="ai_mentor.90_days">90 Hari</option>
|
||||
<option value="365" data-i18n="ai_mentor.1_year">1 Tahun</option>
|
||||
<option value="unlimited" data-i18n="ai_mentor.unlimited">Unlimited</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Export Data</h4>
|
||||
<p class="text-sm text-gray-500">Download semua data AI Mentor Anda</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.export_data">Export Data</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.export_data_description">Download semua data AI Mentor Anda</p>
|
||||
</div>
|
||||
<button class="save-btn" onclick="exportData()">📥 Export</button>
|
||||
<button class="save-btn" onclick="exportData()" data-i18n="ai_mentor.export">📥 Export</button>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<h4 class="font-medium text-gray-700">Reset Semua Data</h4>
|
||||
<p class="text-sm text-gray-500">⚠️ Hapus semua riwayat dan analisis AI</p>
|
||||
<h4 class="font-medium text-gray-700" data-i18n="ai_mentor.reset_all_data">Reset Semua Data</h4>
|
||||
<p class="text-sm text-gray-500" data-i18n="ai_mentor.reset_all_data_description">⚠️ Hapus semua riwayat dan analisis AI</p>
|
||||
</div>
|
||||
<button class="danger-btn" onclick="resetAllData()">🗑️ Reset</button>
|
||||
<button class="danger-btn" onclick="resetAllData()" data-i18n="ai_mentor.reset">🗑️ Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex justify-center space-x-4 mt-8">
|
||||
<button class="save-btn" onclick="saveSettings()">
|
||||
<button class="save-btn" onclick="saveSettings()" data-i18n="ai_mentor.save_settings">
|
||||
💾 Simpan Pengaturan
|
||||
</button>
|
||||
<button class="reset-btn" onclick="resetToDefaults()">
|
||||
<button class="reset-btn" onclick="resetToDefaults()" data-i18n="ai_mentor.reset_to_defaults">
|
||||
🔄 Reset ke Default
|
||||
</button>
|
||||
<a href="/ai-mentor" class="save-btn" style="text-decoration: none; display: inline-block;">
|
||||
<a href="/ai-mentor" class="save-btn" style="text-decoration: none; display: inline-block;" data-i18n="ai_mentor.back_to_dashboard">
|
||||
← Kembali ke Dashboard
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Riwayat Backtest{% endblock %}
|
||||
{% block title_key %}backtest.history_title{% endblock %}
|
||||
{% block title %}Backtest History{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-4">Riwayat Hasil Backtest</h2>
|
||||
|
||||
+22
-23
@@ -1,17 +1,15 @@
|
||||
<!-- templates/backtesting.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Backtester{% endblock %}
|
||||
{% block title_key %}nav.backtest{% endblock %}
|
||||
{% block title %}Strategy Backtester{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-2xl font-bold text-gray-800">Strategy Backtester</h2>
|
||||
<h2 class="text-2xl font-bold text-gray-800" data-i18n="nav.backtest">Strategy Backtester</h2>
|
||||
<div class="flex space-x-2">
|
||||
<button id="download-data-btn" class="bg-green-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-green-700 transition">
|
||||
<i class="fas fa-download mr-2"></i>Download Data MT5
|
||||
</button>
|
||||
<a href="{{ url_for('backtest_history_page') }}" class="bg-gray-200 text-gray-800 py-2 px-4 rounded-lg font-medium hover:bg-gray-300">
|
||||
<i class="fas fa-history mr-2"></i>Lihat Riwayat
|
||||
<i class="fas fa-history mr-2"></i><span data-i18n="action.view">Lihat Riwayat</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,14 +21,14 @@
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-blue-800">🚀 Enhanced Backtesting Engine Active</h3>
|
||||
<h3 class="text-sm font-medium text-blue-800" data-i18n="backtest.enhanced_engine_active">🚀 Enhanced Backtesting Engine Active</h3>
|
||||
<div class="mt-1 text-sm text-blue-700">
|
||||
<p>Your backtesting now includes:</p>
|
||||
<p data-i18n="backtest.includes">Your backtesting now includes:</p>
|
||||
<ul class="mt-1 list-disc list-inside text-xs space-y-1">
|
||||
<li>✅ <strong>Realistic spread costs</strong> - Actual trading costs deducted</li>
|
||||
<li>✅ <strong>ATR-based risk management</strong> - Dynamic position sizing</li>
|
||||
<li>✅ <strong>Instrument protection</strong> - Gold trading safeguards</li>
|
||||
<li>✅ <strong>Slippage simulation</strong> - More accurate execution modeling</li>
|
||||
<li>✅ <strong data-i18n="backtest.realistic_spread">Realistic spread costs</strong> - <span data-i18n="backtest.actual_costs">Actual trading costs deducted</span></li>
|
||||
<li>✅ <strong data-i18n="backtest.atr_risk">ATR-based risk management</strong> - <span data-i18n="backtest.dynamic_sizing">Dynamic position sizing</span></li>
|
||||
<li>✅ <strong data-i18n="backtest.instrument_protection">Instrument protection</strong> - <span data-i18n="backtest.gold_safeguards">Gold trading safeguards</span></li>
|
||||
<li>✅ <strong data-i18n="backtest.slippage">Slippage simulation</strong> - <span data-i18n="backtest.accurate_modeling">More accurate execution modeling</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,11 +41,11 @@
|
||||
<form id="backtest-form">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="strategy-select" class="block text-sm font-medium text-gray-700">Pilih Strategi</label>
|
||||
<label for="strategy-select" class="block text-sm font-medium text-gray-700" data-i18n="label.strategy">Pilih Strategi</label>
|
||||
<select id="strategy-select" name="strategy" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"></select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="data-file" class="block text-sm font-medium text-gray-700">Unggah Data Historis (CSV)</label>
|
||||
<label for="data-file" class="block text-sm font-medium text-gray-700" data-i18n="backtest.upload_data">Unggah Data Historis (CSV)</label>
|
||||
<input type="file" id="data-file" name="file" accept=".csv" class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100" required>
|
||||
</div>
|
||||
|
||||
@@ -55,28 +53,29 @@
|
||||
<div class="grid grid-cols-2 gap-4 pt-4 border-t">
|
||||
<div>
|
||||
<label for="sl_atr_multiplier" class="block text-sm font-medium text-gray-700">
|
||||
SL (ATR Multiplier)
|
||||
<span class="text-xs text-blue-600">🚀 Enhanced</span>
|
||||
<span data-i18n="label.sl_atr">SL (ATR Multiplier)</span>
|
||||
<span class="text-xs text-blue-600" data-i18n="backtest.enhanced">🚀 Enhanced</span>
|
||||
</label>
|
||||
<input type="number" name="sl_atr_multiplier" id="sl_atr_multiplier" value="2.0" step="0.1" min="0.5" max="5.0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
<p class="text-xs text-gray-500 mt-1">Dynamic SL based on volatility</p>
|
||||
<p class="text-xs text-gray-500 mt-1" data-i18n="backtest.dynamic_sl">Dynamic SL based on volatility</p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="tp_atr_multiplier" class="block text-sm font-medium text-gray-700">
|
||||
TP (ATR Multiplier)
|
||||
<span class="text-xs text-blue-600">🚀 Enhanced</span>
|
||||
<span data-i18n="label.tp_atr">TP (ATR Multiplier)</span>
|
||||
<span class="text-xs text-blue-600" data-i18n="backtest.enhanced">🚀 Enhanced</span>
|
||||
</label>
|
||||
<input type="number" name="tp_atr_multiplier" id="tp_atr_multiplier" value="4.0" step="0.1" min="1.0" max="10.0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
<p class="text-xs text-gray-500 mt-1">Dynamic TP based on volatility</p>
|
||||
<p class="text-xs text-gray-500 mt-1" data-i18n="backtest.dynamic_tp">Dynamic TP based on volatility</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="params-container" class="space-y-4 pt-4 border-t">
|
||||
<!-- Parameter akan dimuat di sini -->
|
||||
<span data-i18n="bots.strategy_params_loaded">Parameter strategi akan dimuat di sini</span>
|
||||
</div>
|
||||
<button type="submit" id="run-backtest-btn" class="w-full bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700">
|
||||
<button type="submit" id="run-backtest-btn" class="w-full bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700" data-i18n="backtest.run">
|
||||
Jalankan Backtest
|
||||
</button>
|
||||
</div>
|
||||
@@ -85,7 +84,7 @@
|
||||
|
||||
<!-- Kolom Hasil -->
|
||||
<div id="results-container" class="lg:col-span-2 bg-white p-6 rounded-lg shadow hidden">
|
||||
<h3 class="text-xl font-bold mb-4">Hasil Backtest</h3>
|
||||
<h3 class="text-xl font-bold mb-4" data-i18n="backtest.results">Hasil Backtest</h3>
|
||||
<div id="results-summary" class="grid grid-cols-2 md:grid-cols-3 gap-4 mb-6"></div>
|
||||
<div class="mb-6">
|
||||
<canvas id="equity-chart"></canvas>
|
||||
@@ -94,7 +93,7 @@
|
||||
</div>
|
||||
<div id="loading-spinner" class="lg:col-span-2 flex items-center justify-center hidden">
|
||||
<i class="fas fa-spinner fa-spin text-blue-500 text-4xl"></i>
|
||||
<p class="ml-4 text-gray-600">Menjalankan simulasi...</p>
|
||||
<p class="ml-4 text-gray-600" data-i18n="backtest.running">Menjalankan simulasi...</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
+6
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Dashboard{% endblock %} - QuantumBotX</title>
|
||||
<title data-i18n-key="{% block title_key %}dashboard.title{% endblock %}">{% block title %}Dashboard{% endblock %} - QuantumBotX</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
@@ -70,6 +70,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<!-- Global Language Switcher -->
|
||||
<div class="flex items-center space-x-1 bg-white rounded-lg shadow-sm border px-2 py-1">
|
||||
<button class="lang-btn px-2 py-1 text-xs rounded font-medium hover:bg-gray-100 transition-colors" data-lang="id">ID</button>
|
||||
<button class="lang-btn px-2 py-1 text-xs rounded font-medium hover:bg-gray-100 transition-colors" data-lang="en">EN</button>
|
||||
</div>
|
||||
<a href="/notifications" class="relative text-gray-500 hover:text-blue-600"><i class="fas fa-bell"></i><span id="notification-dot" class="absolute top-0 right-0 w-2 h-2 rounded-full bg-red-500 hidden"></span></a>
|
||||
<a href="/profile" class="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center hover:bg-gray-300"><i class="fas fa-user text-gray-600"></i></a>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!-- templates/bot_detail.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}bots.detail_title{% endblock %}
|
||||
{% block title %}Detail Bot{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
+10
-9
@@ -1,13 +1,14 @@
|
||||
<!-- templates/forex.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}market.forex_title{% endblock %}
|
||||
{% block title %}Forex Market{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Pasar Forex</h2>
|
||||
<p class="text-gray-600">Data harga real-time dari pasar valuta asing.</p>
|
||||
<h2 class="text-2xl font-bold text-gray-800" data-i18n="market.forex_title">Pasar Forex</h2>
|
||||
<p class="text-gray-600" data-i18n="market.forex_description">Data harga real-time dari pasar valuta asing.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,15 +16,15 @@
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Pasangan</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Harga Bid</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Harga Ask</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Spread</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.pair">Pasangan</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.bid_price">Harga Bid</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.ask_price">Harga Ask</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.spread">Spread</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="action.view">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="forex-table-body" class="bg-white divide-y divide-gray-200">
|
||||
<tr><td colspan="5" class="p-4 text-center text-gray-500">Memuat data forex...</td></tr>
|
||||
<tr><td colspan="5" class="p-4 text-center text-gray-500" data-i18n="market.loading">Memuat data forex...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -38,7 +39,7 @@
|
||||
</div>
|
||||
<div class="items-center px-4 py-3">
|
||||
<button id="close-modal" class="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-300">
|
||||
Close
|
||||
<span data-i18n="market.close">Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+11
-10
@@ -1,13 +1,14 @@
|
||||
<!-- templates/history.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Riwayat Transaksi{% endblock %}
|
||||
{% block title_key %}history.title{% endblock %}
|
||||
{% block title %}Riwayat Transaksi Global{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Riwayat Transaksi Global</h2>
|
||||
<p class="text-gray-600">Semua transaksi yang telah ditutup dari akun MetaTrader 5.</p>
|
||||
<h2 class="text-2xl font-bold text-gray-800" data-i18n="history.title">Riwayat Transaksi Global</h2>
|
||||
<p class="text-gray-600" data-i18n="history.description">Semua transaksi yang telah ditutup dari akun MetaTrader 5.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,17 +16,17 @@
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('symbol')">Simbol</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipe</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('volume')">Volume</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('profit')">Profit <span id="profit-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('time')">Waktu Penutupan <span id="time-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('magic')">Magic Number</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('symbol')"><span data-i18n="history.symbol">Simbol</span> <span id="symbol-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('type')"><span data-i18n="history.type">Tipe</span> <span id="type-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('volume')"><span data-i18n="history.volume">Volume</span> <span id="volume-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('profit')"><span data-i18n="history.profit">Profit</span> <span id="profit-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('time')"><span data-i18n="history.close_time">Waktu Penutupan</span> <span id="time-sort-icon"></span></th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" onclick="sortTable('magic')"><span data-i18n="history.magic">Magic Number</span> <span id="magic-sort-icon"></span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="history-table-body" class="bg-white divide-y divide-gray-200">
|
||||
<!-- Data akan dimuat di sini oleh JavaScript -->
|
||||
<tr><td colspan="6" class="p-4 text-center text-gray-500">Memuat riwayat...</td></tr>
|
||||
<tr><td colspan="6" class="p-4 text-center text-gray-500" data-i18n="history.loading">Memuat riwayat...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
+79
-73
@@ -107,13 +107,13 @@
|
||||
<div class="mb-6">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<h2 class="text-3xl font-bold text-gray-800">Dashboard Trading</h2>
|
||||
<p class="text-gray-600">Selamat datang kembali! Berikut ringkasan trading Anda hari ini.</p>
|
||||
<h2 class="text-3xl font-bold text-gray-800" data-i18n="dashboard.title">Dashboard Trading</h2>
|
||||
<p class="text-gray-600" data-i18n="dashboard.welcome_back">Selamat datang kembali! Berikut ringkasan trading Anda hari ini.</p>
|
||||
</div>
|
||||
<div class="ai-mentor-widget p-4 text-right">
|
||||
<div class="text-sm opacity-90">🤖 AI Mentor</div>
|
||||
<div class="text-xl font-bold" id="ai-mentor-status">Siap Membantu</div>
|
||||
<a href="/ai-mentor" class="text-sm underline opacity-90 hover:opacity-100">Lihat Analisis →</a>
|
||||
<div class="text-sm opacity-90" data-i18n="dashboard.ai_mentor">🤖 AI Mentor</div>
|
||||
<div class="text-xl font-bold" id="ai-mentor-status" data-i18n="dashboard.ai_mentor_ready">Siap Membantu</div>
|
||||
<a href="/ai-mentor" class="text-sm underline opacity-90 hover:opacity-100" data-i18n="dashboard.view_analysis">Lihat Analisis →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,7 +123,7 @@
|
||||
<div class="stat-card bg-white rounded-lg shadow p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-500">Total Saldo (Equity)</h3>
|
||||
<h3 class="text-sm font-medium text-gray-500" data-i18n="dashboard.total_equity">Total Saldo (Equity)</h3>
|
||||
<p id="total-equity" class="mt-1 text-2xl font-semibold text-gray-800">
|
||||
<i class="fas fa-spinner fa-spin text-gray-400"></i>
|
||||
</p>
|
||||
@@ -137,7 +137,7 @@
|
||||
<div class="stat-card bg-white rounded-lg shadow p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-500">Profit Hari Ini</h3>
|
||||
<h3 class="text-sm font-medium text-gray-500" data-i18n="dashboard.today_profit">Profit Hari Ini</h3>
|
||||
<p id="todays-profit" class="mt-1 text-2xl font-semibold text-gray-800">
|
||||
<i class="fas fa-spinner fa-spin text-gray-400"></i>
|
||||
</p>
|
||||
@@ -151,7 +151,7 @@
|
||||
<div class="stat-card bg-white rounded-lg shadow p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-500">Bot Aktif</h3>
|
||||
<h3 class="text-sm font-medium text-gray-500" data-i18n="dashboard.active_bots">Bot Aktif</h3>
|
||||
<p id="active-bots-count" class="mt-1 text-2xl font-semibold text-gray-800">
|
||||
<i class="fas fa-spinner fa-spin text-gray-400"></i>
|
||||
</p>
|
||||
@@ -165,7 +165,7 @@
|
||||
<div class="stat-card bg-white rounded-lg shadow p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-500">Total Bot</h3>
|
||||
<h3 class="text-sm font-medium text-gray-500" data-i18n="dashboard.total_bots">Total Bot</h3>
|
||||
<p id="total-bots-count" class="mt-1 text-2xl font-semibold text-gray-800">
|
||||
<i class="fas fa-spinner fa-spin text-gray-400"></i>
|
||||
</p>
|
||||
@@ -179,9 +179,9 @@
|
||||
<!-- New AI Mentor Quick Stats -->
|
||||
<div class="stat-card bg-gradient-to-br from-purple-500 to-blue-600 text-white rounded-lg shadow p-6">
|
||||
<div class="text-center">
|
||||
<h3 class="text-sm font-medium opacity-90">Status Emosi</h3>
|
||||
<p id="emotion-status" class="mt-1 text-xl font-semibold">😌 Tenang</p>
|
||||
<button onclick="quickEmotionCheck()" class="text-xs underline opacity-90 hover:opacity-100 mt-1">
|
||||
<h3 class="text-sm font-medium opacity-90" data-i18n="dashboard.emotion_status">Status Emosi</h3>
|
||||
<p id="emotion-status" class="mt-1 text-xl font-semibold" data-i18n="dashboard.emotion_calm">😌 Tenang</p>
|
||||
<button onclick="quickEmotionCheck()" class="text-xs underline opacity-90 hover:opacity-100 mt-1" data-i18n="dashboard.update_status">
|
||||
Update Status
|
||||
</button>
|
||||
</div>
|
||||
@@ -195,9 +195,9 @@
|
||||
<!-- Price Chart -->
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="text-lg font-semibold text-gray-700">📈 Grafik Harga EUR/USD</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-700" data-i18n="dashboard.price_chart">📈 Grafik Harga EUR/USD</h3>
|
||||
<div class="text-sm text-gray-500" id="last-updated">
|
||||
<i class="fas fa-clock"></i> Memuat...
|
||||
<i class="fas fa-clock"></i> <span data-i18n="dashboard.loading">Memuat...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
@@ -208,9 +208,9 @@
|
||||
<!-- RSI Chart -->
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="text-lg font-semibold text-gray-700">📊 RSI EUR/USD (H1)</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-700" data-i18n="dashboard.rsi_chart">📊 RSI EUR/USD (H1)</h3>
|
||||
<div class="text-sm text-gray-500">
|
||||
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800" data-i18n="dashboard.real_time">
|
||||
Real-time
|
||||
</span>
|
||||
</div>
|
||||
@@ -225,17 +225,17 @@
|
||||
<div class="space-y-6">
|
||||
<!-- AI Mentor Today -->
|
||||
<div class="bg-gradient-to-br from-indigo-500 to-purple-600 text-white rounded-lg shadow p-6">
|
||||
<h3 class="text-lg font-semibold mb-3">🧠 AI Mentor Hari Ini</h3>
|
||||
<h3 class="text-lg font-semibold mb-3" data-i18n="dashboard.ai_mentor_today">🧠 AI Mentor Hari Ini</h3>
|
||||
<div id="ai-mentor-summary" class="space-y-3">
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-3">
|
||||
<div class="text-sm opacity-90">Analisis Trading:</div>
|
||||
<div class="font-semibold" id="trading-analysis">Memuat...</div>
|
||||
<div class="text-sm opacity-90" data-i18n="dashboard.trading_analysis">Analisis Trading:</div>
|
||||
<div class="font-semibold" id="trading-analysis" data-i18n="dashboard.loading">Memuat...</div>
|
||||
</div>
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-3">
|
||||
<div class="text-sm opacity-90">Tips Hari Ini:</div>
|
||||
<div class="text-sm" id="daily-tip">Memuat...</div>
|
||||
<div class="text-sm opacity-90" data-i18n="dashboard.daily_tip">Tips Hari Ini:</div>
|
||||
<div class="text-sm" id="daily-tip" data-i18n="dashboard.loading">Memuat...</div>
|
||||
</div>
|
||||
<a href="/ai-mentor/today-report" class="block w-full bg-white bg-opacity-20 hover:bg-opacity-30 rounded-lg p-2 text-center text-sm font-medium transition">
|
||||
<a href="/ai-mentor/today-report" class="block w-full bg-white bg-opacity-20 hover:bg-opacity-30 rounded-lg p-2 text-center text-sm font-medium transition" data-i18n="dashboard.view_full_report">
|
||||
📊 Lihat Laporan Lengkap
|
||||
</a>
|
||||
</div>
|
||||
@@ -244,10 +244,10 @@
|
||||
<!-- Recent Activities -->
|
||||
<div class="bg-white rounded-lg shadow">
|
||||
<div class="p-4 border-b">
|
||||
<h3 class="text-lg font-semibold text-gray-800">⚡ Aktivitas Terbaru</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800" data-i18n="dashboard.recent_activities">⚡ Aktivitas Terbaru</h3>
|
||||
</div>
|
||||
<div id="recent-activities" class="max-h-80 overflow-y-auto">
|
||||
<div class="p-4 text-gray-500 text-center">Memuat aktivitas...</div>
|
||||
<div class="p-4 text-gray-500 text-center" data-i18n="dashboard.loading_activities">Memuat aktivitas...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -256,18 +256,18 @@
|
||||
<!-- BOT AKTIF -->
|
||||
<div class="bg-white rounded-lg shadow">
|
||||
<div class="p-6 border-b">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Active Trading Bots</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800" data-i18n="dashboard.active_trading_bots">Active Trading Bots</h3>
|
||||
</div>
|
||||
<div id="active-bots-list" class="divide-y">
|
||||
<p class="p-4 text-gray-500">Memuat daftar bot...</p>
|
||||
<p class="p-4 text-gray-500" data-i18n="dashboard.loading_bot_list">Memuat daftar bot...</p>
|
||||
</div>
|
||||
<div class="p-4 border-t">
|
||||
<a href="/trading_bots" class="block w-full text-center text-blue-600 font-medium hover:text-blue-800 transition">View All Bots</a>
|
||||
<a href="/trading_bots" class="block w-full text-center text-blue-600 font-medium hover:text-blue-800 transition" data-i18n="dashboard.view_all_bots">View All Bots</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Floating AI Button -->
|
||||
<button class="floating-ai-btn" onclick="window.location.href='/ai-mentor'" title="Chat dengan AI Mentor">
|
||||
<button class="floating-ai-btn" onclick="window.location.href='/ai-mentor'" data-i18n-title="dashboard.chat_with_ai_mentor" title="Chat dengan AI Mentor">
|
||||
🤖
|
||||
</button>
|
||||
{% endblock %}
|
||||
@@ -453,7 +453,7 @@ function loadDashboardData() {
|
||||
</div>
|
||||
`).join('');
|
||||
} else {
|
||||
botsList.innerHTML = '<p class="p-4 text-gray-500">Tidak ada bot yang aktif</p>';
|
||||
botsList.innerHTML = '<p class="p-4 text-gray-500" data-i18n="dashboard.no_active_bots">Tidak ada bot yang aktif</p>';
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -503,38 +503,38 @@ function loadAIMentorSummary() {
|
||||
if (data.success) {
|
||||
// Update emotion status
|
||||
const emotionMap = {
|
||||
'tenang': '😌 Tenang',
|
||||
'serakah': '🤑 Serakah',
|
||||
'takut': '😰 Takut',
|
||||
'frustasi': '😤 Frustasi',
|
||||
'netral': '😐 Netral'
|
||||
'tenang': window.QuantumBotXI18n.t('dashboard.emotion_calm'),
|
||||
'serakah': window.QuantumBotXI18n.t('dashboard.emotion_greedy'),
|
||||
'takut': window.QuantumBotXI18n.t('dashboard.emotion_fear'),
|
||||
'frustasi': window.QuantumBotXI18n.t('dashboard.emotion_frustrated'),
|
||||
'netral': window.QuantumBotXI18n.t('dashboard.emotion_neutral')
|
||||
};
|
||||
document.getElementById('emotion-status').textContent =
|
||||
emotionMap[data.today_emotions] || '😐 Netral';
|
||||
emotionMap[data.today_emotions] || window.QuantumBotXI18n.t('dashboard.emotion_neutral');
|
||||
|
||||
// Update AI analysis
|
||||
document.getElementById('trading-analysis').textContent =
|
||||
data.trading_analysis || 'Belum ada data hari ini';
|
||||
data.trading_analysis || window.QuantumBotXI18n.t('msg.no_data');
|
||||
|
||||
// Update daily tip
|
||||
document.getElementById('daily-tip').textContent =
|
||||
data.daily_tip || 'Mulai trading untuk mendapat tips personal!';
|
||||
data.daily_tip || window.QuantumBotXI18n.t('msg.no_data');
|
||||
|
||||
// Update AI mentor status
|
||||
const statusElement = document.getElementById('ai-mentor-status');
|
||||
if (data.today_has_data) {
|
||||
statusElement.textContent = 'Aktif Menganalisis';
|
||||
statusElement.textContent = window.QuantumBotXI18n.t('dashboard.ai_mentor_active');
|
||||
statusElement.className = 'text-xl font-bold text-green-100';
|
||||
} else {
|
||||
statusElement.textContent = 'Siap Membantu';
|
||||
statusElement.textContent = window.QuantumBotXI18n.t('dashboard.ai_mentor_ready');
|
||||
statusElement.className = 'text-xl font-bold';
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading AI mentor summary:', error);
|
||||
document.getElementById('trading-analysis').textContent = 'Error loading';
|
||||
document.getElementById('daily-tip').textContent = 'Error loading';
|
||||
document.getElementById('trading-analysis').textContent = window.QuantumBotXI18n.t('error.loading');
|
||||
document.getElementById('daily-tip').textContent = window.QuantumBotXI18n.t('error.loading');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -558,26 +558,32 @@ function loadRecentActivities() {
|
||||
`).join('');
|
||||
|
||||
document.getElementById('recent-activities').innerHTML =
|
||||
activitiesHtml || '<div class="p-4 text-gray-500 text-center">Belum ada aktivitas</div>';
|
||||
activitiesHtml || '<div class="p-4 text-gray-500 text-center" data-i18n="msg.no_data">Belum ada aktivitas</div>';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading recent activities:', error);
|
||||
document.getElementById('recent-activities').innerHTML =
|
||||
'<div class="p-4 text-red-500 text-center">Error loading activities</div>';
|
||||
'<div class="p-4 text-red-500 text-center" data-i18n="error.loading">Error loading activities</div>';
|
||||
});
|
||||
}
|
||||
|
||||
// Quick Emotion Check
|
||||
function quickEmotionCheck() {
|
||||
const emotions = ['tenang', 'serakah', 'takut', 'frustasi', 'netral'];
|
||||
const emotionNames = ['😌 Tenang', '🤑 Serakah', '😰 Takut', '😤 Frustasi', '😐 Netral'];
|
||||
const emotionNames = [
|
||||
window.QuantumBotXI18n.t('dashboard.emotion_calm'),
|
||||
window.QuantumBotXI18n.t('dashboard.emotion_greedy'),
|
||||
window.QuantumBotXI18n.t('dashboard.emotion_fear'),
|
||||
window.QuantumBotXI18n.t('dashboard.emotion_frustrated'),
|
||||
window.QuantumBotXI18n.t('dashboard.emotion_neutral')
|
||||
];
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center';
|
||||
modal.innerHTML = `
|
||||
<div class="bg-white rounded-lg p-6 max-w-sm w-full mx-4">
|
||||
<h3 class="text-lg font-semibold mb-4">🎯 Update Status Emosi</h3>
|
||||
<h3 class="text-lg font-semibold mb-4" data-i18n="dashboard.update_emotion_status">🎯 Update Status Emosi</h3>
|
||||
<div class="space-y-2">
|
||||
${emotions.map((emotion, index) => `
|
||||
<button onclick="updateEmotion('${emotion}')"
|
||||
@@ -587,7 +593,7 @@ function quickEmotionCheck() {
|
||||
`).join('')}
|
||||
</div>
|
||||
<button onclick="closeEmotionModal()"
|
||||
class="mt-4 w-full bg-gray-200 text-gray-800 py-2 rounded-lg hover:bg-gray-300 transition-colors">
|
||||
class="mt-4 w-full bg-gray-200 text-gray-800 py-2 rounded-lg hover:bg-gray-300 transition-colors" data-i18n="dashboard.cancel">
|
||||
Batal
|
||||
</button>
|
||||
</div>
|
||||
@@ -611,26 +617,26 @@ function updateEmotion(emotion) {
|
||||
if (data.success) {
|
||||
// Update UI immediately
|
||||
const emotionMap = {
|
||||
'tenang': '😌 Tenang',
|
||||
'serakah': '🤑 Serakah',
|
||||
'takut': '😰 Takut',
|
||||
'frustasi': '😤 Frustasi',
|
||||
'netral': '😐 Netral'
|
||||
'tenang': window.QuantumBotXI18n.t('dashboard.emotion_calm'),
|
||||
'serakah': window.QuantumBotXI18n.t('dashboard.emotion_greedy'),
|
||||
'takut': window.QuantumBotXI18n.t('dashboard.emotion_fear'),
|
||||
'frustasi': window.QuantumBotXI18n.t('dashboard.emotion_frustrated'),
|
||||
'netral': window.QuantumBotXI18n.t('dashboard.emotion_neutral')
|
||||
};
|
||||
document.getElementById('emotion-status').textContent = emotionMap[emotion];
|
||||
|
||||
// Show success message
|
||||
showNotification('Status emosi berhasil diupdate!', 'success');
|
||||
showNotification(window.QuantumBotXI18n.t('dashboard.emotion_updated'), 'success');
|
||||
|
||||
// Refresh AI mentor summary
|
||||
loadAIMentorSummary();
|
||||
} else {
|
||||
showNotification('Gagal update status emosi', 'error');
|
||||
showNotification(window.QuantumBotXI18n.t('dashboard.emotion_update_failed'), 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error updating emotion:', error);
|
||||
showNotification('Error: Gagal update status emosi', 'error');
|
||||
showNotification(window.QuantumBotXI18n.t('dashboard.error_updating_emotion'), 'error');
|
||||
})
|
||||
.finally(() => {
|
||||
closeEmotionModal();
|
||||
@@ -737,7 +743,7 @@ function updateRamadanWidgets(holidayData) {
|
||||
ramadanHtml += `
|
||||
<div class="holiday-widget ramadan-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">⏱️ Hitung Mundur Iftar</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.countdown.iftar">⏱️ Hitung Mundur Iftar</h3>
|
||||
<i class="fas fa-moon"></i>
|
||||
</div>
|
||||
<div class="ramadan-countdown">
|
||||
@@ -755,7 +761,7 @@ function updateRamadanWidgets(holidayData) {
|
||||
ramadanHtml += `
|
||||
<div class="holiday-widget ramadan-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🧘♂️ Pengingat Kesabaran</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.patience_reminder">🧘♂️ Pengingat Kesabaran</h3>
|
||||
<i class="fas fa-heart"></i>
|
||||
</div>
|
||||
<div class="text-sm italic text-center">
|
||||
@@ -771,12 +777,12 @@ function updateRamadanWidgets(holidayData) {
|
||||
ramadanHtml += `
|
||||
<div class="holiday-widget ramadan-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🛡️ Penyesuaian Risiko</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.risk_adjustment">🛡️ Penyesuaian Risiko</h3>
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold">${riskReduction.toFixed(0)}%</div>
|
||||
<div class="text-sm opacity-90">Pengurangan risiko otomatis</div>
|
||||
<div class="text-sm opacity-90" data-i18n="holiday.risk_reduction">Pengurangan risiko otomatis</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -787,7 +793,7 @@ function updateRamadanWidgets(holidayData) {
|
||||
ramadanHtml += `
|
||||
<div class="holiday-widget ramadan-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">⏰ Waktu Trading Optimal</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.optimal_trading_hours">⏰ Waktu Trading Optimal</h3>
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
@@ -822,14 +828,14 @@ function updateChristmasWidgets(holidayData) {
|
||||
christmasHtml += `
|
||||
<div class="holiday-widget christmas-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🎄 Hitung Mundur Natal</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.countdown.christmas">🎄 Hitung Mundur Natal</h3>
|
||||
<i class="fas fa-gift"></i>
|
||||
</div>
|
||||
<div class="ramadan-countdown">
|
||||
${daysDiff}
|
||||
</div>
|
||||
<div class="text-center text-sm opacity-90 mt-2">
|
||||
hari lagi sampai Natal
|
||||
<span data-i18n="holiday.countdown.days_until">hari lagi sampai</span> Natal
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -841,12 +847,12 @@ function updateChristmasWidgets(holidayData) {
|
||||
christmasHtml += `
|
||||
<div class="holiday-widget christmas-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🛡️ Penyesuaian Risiko</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.risk_adjustment">🛡️ Penyesuaian Risiko</h3>
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold">${riskReduction.toFixed(0)}%</div>
|
||||
<div class="text-sm opacity-90">Pengurangan risiko otomatis</div>
|
||||
<div class="text-sm opacity-90" data-i18n="holiday.risk_reduction">Pengurangan risiko otomatis</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -857,7 +863,7 @@ function updateChristmasWidgets(holidayData) {
|
||||
christmasHtml += `
|
||||
<div class="holiday-widget christmas-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">✨ Salam Natal</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.christmas_greeting">✨ Salam Natal</h3>
|
||||
<i class="fas fa-star"></i>
|
||||
</div>
|
||||
<div class="text-sm text-center italic">
|
||||
@@ -873,12 +879,12 @@ function updateChristmasWidgets(holidayData) {
|
||||
christmasHtml += `
|
||||
<div class="holiday-widget christmas-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">📏 Penyesuaian Lot</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.lot_adjustment">📏 Penyesuaian Lot</h3>
|
||||
<i class="fas fa-ruler"></i>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold">${lotSizeReduction.toFixed(0)}%</div>
|
||||
<div class="text-sm opacity-90">Pengurangan ukuran lot</div>
|
||||
<div class="text-sm opacity-90" data-i18n="holiday.lot_reduction">Pengurangan ukuran lot</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -903,14 +909,14 @@ function updateNewYearWidgets(holidayData) {
|
||||
newYearHtml += `
|
||||
<div class="holiday-widget new-year-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🎆 Hitung Mundur Tahun Baru</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.countdown.new_year">🎆 Hitung Mundur Tahun Baru</h3>
|
||||
<i class="fas fa-champagne-glasses"></i>
|
||||
</div>
|
||||
<div class="ramadan-countdown">
|
||||
${daysDiff}
|
||||
</div>
|
||||
<div class="text-center text-sm opacity-90 mt-2">
|
||||
hari lagi sampai Tahun Baru
|
||||
<span data-i18n="holiday.countdown.days_until">hari lagi sampai</span> Tahun Baru
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -921,12 +927,12 @@ function updateNewYearWidgets(holidayData) {
|
||||
newYearHtml += `
|
||||
<div class="holiday-widget new-year-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🛡️ Penyesuaian Risiko</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.risk_adjustment">🛡️ Penyesuaian Risiko</h3>
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold">${riskReduction.toFixed(0)}%</div>
|
||||
<div class="text-sm opacity-90">Pengurangan risiko otomatis</div>
|
||||
<div class="text-sm opacity-90" data-i18n="holiday.risk_reduction">Pengurangan risiko otomatis</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -936,10 +942,10 @@ function updateNewYearWidgets(holidayData) {
|
||||
newYearHtml += `
|
||||
<div class="holiday-widget new-year-widget p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold">🎯 Resolusi Trading</h3>
|
||||
<h3 class="text-lg font-semibold" data-i18n="holiday.new_year_resolution">🎯 Resolusi Trading</h3>
|
||||
<i class="fas fa-bullseye"></i>
|
||||
</div>
|
||||
<div class="text-sm text-center">
|
||||
<div class="text-sm text-center" data-i18n="holiday.new_year_goal_setting">
|
||||
Waktu yang tepat untuk menetapkan tujuan trading tahun ini
|
||||
</div>
|
||||
</div>
|
||||
@@ -955,7 +961,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const floatingBtn = document.createElement('button');
|
||||
floatingBtn.className = 'floating-ai-btn';
|
||||
floatingBtn.innerHTML = '🤖';
|
||||
floatingBtn.title = 'Chat dengan AI Mentor';
|
||||
floatingBtn.title = window.QuantumBotXI18n.t('dashboard.chat_with_ai_mentor');
|
||||
floatingBtn.onclick = () => window.location.href = '/ai-mentor';
|
||||
document.body.appendChild(floatingBtn);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<!-- templates/notifications.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}nav.notifications{% endblock %}
|
||||
{% block title %}Notifikasi{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6">Notifikasi</h2>
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6" data-i18n="nav.notifications">Notifikasi</h2>
|
||||
<div class="bg-white rounded-lg shadow">
|
||||
<!-- Kontainer ini akan diisi oleh JavaScript -->
|
||||
<div id="notifications-container" class="divide-y divide-gray-200">
|
||||
<p class="p-6 text-center text-gray-500">Memuat notifikasi...</p>
|
||||
<p class="p-6 text-center text-gray-500" data-i18n="notifications.loading">Memuat notifikasi...</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('static', filename='js/notifications.js') }}"></script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
+13
-12
@@ -1,12 +1,13 @@
|
||||
<!-- templates/portfolio.html -->
|
||||
{% extends "base.html" %}
|
||||
{% block title_key %}portfolio.title{% endblock %}
|
||||
{% block title %}Portfolio Real-Time{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Portfolio Real-Time</h2>
|
||||
<p class="text-gray-600">Posisi trading yang sedang terbuka di akun MetaTrader 5.</p>
|
||||
<h2 class="text-2xl font-bold text-gray-800" data-i18n="portfolio.title">Portfolio Real-Time</h2>
|
||||
<p class="text-gray-600" data-i18n="portfolio.description">Posisi trading yang sedang terbuka di akun MetaTrader 5.</p>
|
||||
</div>
|
||||
<div id="portfolio-summary" class="text-right">
|
||||
<!-- Summary akan dimuat di sini -->
|
||||
@@ -17,13 +18,13 @@
|
||||
<div class="grid grid-cols-1 lg:grid-cols-5 gap-6 mb-6">
|
||||
<!-- Chart P/L (lebih lebar) -->
|
||||
<div class="lg:col-span-3 bg-white rounded-lg shadow p-4">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-2">Grafik Profit/Loss Terbuka (Real-Time)</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-2" data-i18n="portfolio.pnl_chart">Grafik Profit/Loss Terbuka (Real-Time)</h3>
|
||||
<div style="height: 250px;"><canvas id="pnlChart"></canvas></div>
|
||||
</div>
|
||||
|
||||
<!-- Chart Alokasi Aset (lebih kecil) -->
|
||||
<div class="lg:col-span-2 bg-white rounded-lg shadow p-4">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-2">Alokasi Aset</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-2" data-i18n="portfolio.allocation_chart">Alokasi Aset</h3>
|
||||
<div style="height: 250px;"><canvas id="assetAllocationChart"></canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,16 +33,16 @@
|
||||
<table class="min-w-full bg-white rounded-lg shadow overflow-hidden">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Simbol</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipe</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Volume</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Harga Buka</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Profit/Loss</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Magic Number</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="portfolio.symbol">Simbol</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="portfolio.type">Tipe</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="portfolio.volume">Volume</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="portfolio.open_price">Harga Buka</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="portfolio.profit_loss">Profit/Loss</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="portfolio.magic">Magic Number</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="portfolio-table-body" class="bg-white divide-y divide-gray-200">
|
||||
<tr><td colspan="6" class="p-4 text-center text-gray-500">Memuat posisi terbuka...</td></tr>
|
||||
<tr><td colspan="6" class="p-4 text-center text-gray-500" data-i18n="portfolio.loading">Memuat posisi terbuka...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -52,4 +53,4 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
|
||||
<script src="{{ url_for('static', filename='js/portfolio.js') }}"></script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
+22
-25
@@ -1,43 +1,40 @@
|
||||
<!-- templates/profile.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}profile.title{% endblock %}
|
||||
{% block title %}Profil{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6">Profil Saya</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div class="md:col-span-1">
|
||||
<div class="bg-white p-6 rounded-lg shadow text-center">
|
||||
<div class="w-24 h-24 rounded-full bg-gray-200 flex items-center justify-center mx-auto mb-4">
|
||||
<i class="fas fa-user fa-3x text-gray-500"></i>
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6" data-i18n="profile.my_profile">Profil Saya</h2>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<div class="lg:col-span-1">
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="w-24 h-24 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 text-4xl font-bold mb-4">RC</div>
|
||||
<h3 id="profile-display-name" class="text-xl font-bold text-gray-800" data-i18n="profile.loading">Memuat...</h3>
|
||||
<p id="profile-join-date" class="text-xs text-gray-400 mt-2" data-i18n="profile.joined_since">Bergabung sejak: Juli 2025</p>
|
||||
</div>
|
||||
<h3 id="profile-display-name" class="text-xl font-bold text-gray-800">Memuat...</h3>
|
||||
<p class="text-sm text-gray-500">Developer</p>
|
||||
<p id="profile-join-date" class="text-xs text-gray-400 mt-2">Bergabung sejak: Juli 2025</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<div class="bg-white p-6 rounded-lg shadow">
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4">Detail Akun</h3>
|
||||
<form id="profile-form" class="space-y-4">
|
||||
<div class="lg:col-span-2">
|
||||
<div class="bg-white rounded-lg shadow">
|
||||
<div class="p-6 border-b">
|
||||
<h3 class="text-lg font-semibold text-gray-800" data-i18n="settings.profile">Profil</h3>
|
||||
</div>
|
||||
<form id="profile-form" class="p-6 space-y-4">
|
||||
<div>
|
||||
<label for="profile-name" class="text-sm font-medium text-gray-700">Nama Lengkap</label>
|
||||
<input type="text" id="profile-name" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm" required>
|
||||
<label for="profile-name" class="text-sm font-medium text-gray-700" data-i18n="label.full_name">Nama Lengkap</label>
|
||||
<input type="text" id="profile-name" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="profile-email" class="text-sm font-medium text-gray-700">Alamat Email</label>
|
||||
<input type="email" id="profile-email" class="mt-1 block w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-md" required>
|
||||
<label for="profile-email" class="text-sm font-medium text-gray-700" data-i18n="label.email">Alamat Email</label>
|
||||
<input type="email" id="profile-email" class="mt-1 block w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" required readonly>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4 pt-6">Keamanan</h3>
|
||||
<div>
|
||||
<label for="profile-password" class="text-sm font-medium text-gray-700">Ganti Password (kosongkan jika tidak ingin diubah)</label>
|
||||
<input type="password" id="profile-password" placeholder="••••••••" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm">
|
||||
</div>
|
||||
<div class="flex justify-end pt-4">
|
||||
<button type="submit" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700">Simpan Perubahan</button>
|
||||
<label for="profile-password" class="text-sm font-medium text-gray-700" data-i18n="label.password">Ganti Password (kosongkan jika tidak ingin diubah)</label>
|
||||
<input type="password" id="profile-password" data-i18n-placeholder="profile.password_placeholder" placeholder="••••••••" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
||||
</div>
|
||||
<button type="submit" id="save-profile-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700" data-i18n="msg.save_changes">Simpan Perubahan</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+39
-40
@@ -1,17 +1,17 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Ramadan Trading Mode{% endblock %}
|
||||
{% block title_key %}ramadan.page_title{% endblock %}
|
||||
{% block title %}🌙 Ramadan Trading Mode{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Header -->
|
||||
<div class="mb-8 text-center">
|
||||
<h1 class="text-3xl font-bold text-gray-800 mb-2">🌙 Ramadan Trading Mode</h1>
|
||||
<p class="text-gray-600">Bulan suci dengan fitur trading yang menghormati ibadah puasa</p>
|
||||
<h1 class="text-3xl font-bold text-gray-800 mb-2" data-i18n="ramadan.title">🌙 Ramadan Trading Mode</h1>
|
||||
<p class="text-gray-600" data-i18n="ramadan.subtitle">Bulan suci dengan fitur trading yang menghormati ibadah puasa</p>
|
||||
<div class="mt-4 p-4 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<p class="text-blue-800">
|
||||
<i class="fas fa-info-circle"></i> Mode ini aktif secara otomatis selama bulan Ramadan dan akan
|
||||
menyesuaikan pengaturan trading Anda untuk menghormati waktu ibadah. Anda tidak perlu mengaktifkannya secara manual.
|
||||
<i class="fas fa-info-circle"></i> <span data-i18n="ramadan.info">Mode ini aktif secara otomatis selama bulan Ramadan dan akan menyesuaikan pengaturan trading Anda untuk menghormati waktu ibadah. Anda tidak perlu mengaktifkannya secara manual.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -19,23 +19,23 @@
|
||||
<!-- Current Status Card -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-800">Status Ramadan</h2>
|
||||
<span id="ramadan-status" class="px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800">
|
||||
<h2 class="text-xl font-semibold text-gray-800" data-i18n="ramadan.status">Status Ramadan</h2>
|
||||
<span id="ramadan-status" class="px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800" data-i18n="ramadan.loading">
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div class="border rounded-lg p-4">
|
||||
<div class="text-sm text-gray-500 mb-1">Periode Ramadan</div>
|
||||
<div id="ramadan-period" class="text-lg font-semibold text-blue-600">
|
||||
<div class="text-sm text-gray-500 mb-1" data-i18n="ramadan.period">Periode Ramadan</div>
|
||||
<div id="ramadan-period" class="text-lg font-semibold text-blue-600" data-i18n="ramadan.loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border rounded-lg p-4">
|
||||
<div class="text-sm text-gray-500 mb-1">Salam Ramadan</div>
|
||||
<div id="ramadan-greeting" class="text-lg font-semibold text-green-600">
|
||||
<div class="text-sm text-gray-500 mb-1" data-i18n="ramadan.greeting">Salam Ramadan</div>
|
||||
<div id="ramadan-greeting" class="text-lg font-semibold text-green-600" data-i18n="ramadan.loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,79 +44,79 @@
|
||||
|
||||
<!-- Iftar Countdown -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4">⏱️ Hitung Mundur Iftar</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ramadan.iftar_countdown">⏱️ Hitung Mundur Iftar</h2>
|
||||
|
||||
<div class="flex justify-center items-center">
|
||||
<div class="text-center mx-4">
|
||||
<div id="iftar-hours" class="text-4xl font-bold text-gray-800">00</div>
|
||||
<div class="text-sm text-gray-500">Jam</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.hours">Jam</div>
|
||||
</div>
|
||||
<div class="text-4xl font-bold text-gray-300">:</div>
|
||||
<div class="text-center mx-4">
|
||||
<div id="iftar-minutes" class="text-4xl font-bold text-gray-800">00</div>
|
||||
<div class="text-sm text-gray-500">Menit</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.minutes">Menit</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-4 text-gray-600">
|
||||
Sampai <span id="next-prayer">Iftar</span>
|
||||
<span data-i18n="ramadan.until">Sampai</span> <span id="next-prayer" data-i18n="ramadan.iftar">Iftar</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trading Adjustments -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4">⚙️ Penyesuaian Trading</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ramadan.trading_adjustments">⚙️ Penyesuaian Trading</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3">Waktu Istirahat Puasa</h3>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3" data-i18n="ramadan.fasting_times">Waktu Istirahat Puasa</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full bg-yellow-500 mr-3"></div>
|
||||
<div>
|
||||
<div class="font-medium">Sahur</div>
|
||||
<div class="text-sm text-gray-500">03:30 - 05:00 WIB</div>
|
||||
<div class="font-medium" data-i18n="ramadan.suhoor">Sahur</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.suhoor_time">03:30 - 05:00 WIB</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full bg-orange-500 mr-3"></div>
|
||||
<div>
|
||||
<div class="font-medium">Iftar</div>
|
||||
<div class="text-sm text-gray-500">18:00 - 19:30 WIB</div>
|
||||
<div class="font-medium" data-i18n="ramadan.iftar_time">Iftar</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.iftar_time_range">18:00 - 19:30 WIB</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full bg-purple-500 mr-3"></div>
|
||||
<div>
|
||||
<div class="font-medium">Tarawih</div>
|
||||
<div class="text-sm text-gray-500">20:00 - 21:30 WIB</div>
|
||||
<div class="font-medium" data-i18n="ramadan.tarawih">Tarawih</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.tarawih_time">20:00 - 21:30 WIB</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3">Penyesuaian Risiko</h3>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3" data-i18n="ramadan.risk_adjustments">Penyesuaian Risiko</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full bg-red-500 mr-3"></div>
|
||||
<div>
|
||||
<div class="font-medium">Reduced Risk Mode</div>
|
||||
<div class="text-sm text-gray-500">20% pengurangan risiko selama puasa</div>
|
||||
<div class="font-medium" data-i18n="ramadan.reduced_risk_mode">Reduced Risk Mode</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.reduced_risk_description">20% pengurangan risiko selama puasa</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full bg-blue-500 mr-3"></div>
|
||||
<div>
|
||||
<div class="font-medium">Patience Mode</div>
|
||||
<div class="text-sm text-gray-500">Fokus pada kualitas bukan kuantitas</div>
|
||||
<div class="font-medium" data-i18n="ramadan.patience_mode">Patience Mode</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.patience_mode_description">Fokus pada kualitas bukan kuantitas</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 rounded-full bg-green-500 mr-3"></div>
|
||||
<div>
|
||||
<div class="font-medium">Optimal Hours</div>
|
||||
<div class="text-sm text-gray-500">22:00 - 03:00 WIB</div>
|
||||
<div class="font-medium" data-i18n="ramadan.optimal_hours">Optimal Hours</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.optimal_hours_time">22:00 - 03:00 WIB</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,33 +126,32 @@
|
||||
|
||||
<!-- Zakat Calculator -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4">💰 Kalkulator Zakat Trading</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ramadan.zakat_calculator">💰 Kalkulator Zakat Trading</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3">Informasi Zakat</h3>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3" data-i18n="ramadan.zakat_information">Informasi Zakat</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="border rounded-lg p-3">
|
||||
<div class="text-sm text-gray-500">Nisab Emas</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.gold_nisab">Nisab Emas</div>
|
||||
<div class="text-lg font-semibold">85 gram</div>
|
||||
</div>
|
||||
<div class="border rounded-lg p-3">
|
||||
<div class="text-sm text-gray-500">Nisab Perak</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.silver_nisab">Nisab Perak</div>
|
||||
<div class="text-lg font-semibold">595 gram</div>
|
||||
</div>
|
||||
<div class="border rounded-lg p-3">
|
||||
<div class="text-sm text-gray-500">Persentase Zakat</div>
|
||||
<div class="text-sm text-gray-500" data-i18n="ramadan.zakat_percentage">Persentase Zakat</div>
|
||||
<div class="text-lg font-semibold">2.5%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3">Pengingat Zakat</h3>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3" data-i18n="ramadan.zakat_reminder">Pengingat Zakat</h3>
|
||||
<div class="border rounded-lg p-4 bg-blue-50">
|
||||
<p class="text-gray-700">
|
||||
Zakat perdagangan: 2.5% dari profit trading selama 1 tahun hijriah.
|
||||
Jangan lupa menghitung zakat dari profit trading Anda selama Ramadan.
|
||||
<span data-i18n="ramadan.zakat_trading_reminder">Zakat perdagangan: 2.5% dari profit trading selama 1 tahun hijriah. Jangan lupa menghitung zakat dari profit trading Anda selama Ramadan.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -161,10 +160,10 @@
|
||||
|
||||
<!-- Patience Reminder -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6">
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4">🧘♂️ Pengingat Kesabaran</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="ramadan.patience_reminder">🧘♂️ Pengingat Kesabaran</h2>
|
||||
|
||||
<div class="border rounded-lg p-6 bg-green-50 text-center">
|
||||
<div id="patience-reminder" class="text-lg text-gray-700 italic">
|
||||
<div id="patience-reminder" class="text-lg text-gray-700 italic" data-i18n="ramadan.loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+24
-23
@@ -1,51 +1,52 @@
|
||||
<!-- templates/settings.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}settings.title{% endblock %}
|
||||
{% block title %}Pengaturan{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6">Pengaturan</h2>
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6" data-i18n="settings.title">Pengaturan</h2>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<div class="lg:col-span-2 space-y-6">
|
||||
<div class="bg-white p-6 rounded-lg shadow">
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="profile-title">Profil</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="profile-title" data-i18n="settings.profile">Profil</h3>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-700" id="full-name-label">Nama Lengkap</label>
|
||||
<label class="text-sm font-medium text-gray-700" id="full-name-label" data-i18n="label.full_name">Nama Lengkap</label>
|
||||
<input type="text" value="Reynov Christian" id="full-name-input" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-700" id="email-label">Alamat Email</label>
|
||||
<label class="text-sm font-medium text-gray-700" id="email-label" data-i18n="label.email">Alamat Email</label>
|
||||
<input type="email" value="contact@chrisnov.com" id="email-input" class="mt-1 block w-full px-3 py-2 bg-gray-100 border border-gray-300 rounded-md shadow-sm" readonly>
|
||||
</div>
|
||||
<button id="save-profile-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700">Simpan Perubahan</button>
|
||||
<button id="save-profile-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700" data-i18n="msg.save_changes">Simpan Perubahan</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-lg shadow">
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="preferences-title">Preferensi</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="preferences-title" data-i18n="settings.preferences">Preferensi</h3>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-700" id="language-label">Bahasa</label>
|
||||
<label class="text-sm font-medium text-gray-700" id="language-label" data-i18n="settings.language">Bahasa</label>
|
||||
<select id="language-select" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
||||
<option value="id">Indonesia</option>
|
||||
<option value="en">English</option>
|
||||
<option value="id" data-i18n="settings.indonesian">Indonesia</option>
|
||||
<option value="en" data-i18n="settings.english">English</option>
|
||||
</select>
|
||||
<p class="text-xs text-gray-500 mt-1">Application language settings</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-700" id="theme-label">Tema</label>
|
||||
<label class="text-sm font-medium text-gray-700" id="theme-label" data-i18n="settings.theme">Tema</label>
|
||||
<select id="theme-select" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
||||
<option value="light">Terang</option>
|
||||
<option value="dark">Gelap (Segera Hadir)</option>
|
||||
<option value="light" data-i18n="settings.light">Terang</option>
|
||||
<option value="dark" data-i18n="settings.dark">Gelap (Segera Hadir)</option>
|
||||
</select>
|
||||
</div>
|
||||
<button id="save-preferences-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700">Simpan Preferensi</button>
|
||||
<button id="save-preferences-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700" data-i18n="msg.save_preferences">Simpan Preferensi</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-6 rounded-lg shadow">
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="api-keys-title">API Keys Bursa</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="api-keys-title" data-i18n="settings.api_keys">API Keys Bursa</h3>
|
||||
<div class="space-y-4">
|
||||
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<div class="flex">
|
||||
@@ -53,13 +54,13 @@
|
||||
<i class="fas fa-info-circle text-yellow-400"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm text-yellow-800" id="api-info-text">
|
||||
<p class="text-sm text-yellow-800" id="api-info-text" data-i18n="settings.api_info">
|
||||
API Keys akan digunakan oleh versi QuantumBotX berikutnya untuk mengakses broker non-MT5.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600" id="api-placeholder-text">
|
||||
<div class="text-sm text-gray-600" id="api-placeholder-text" data-i18n="settings.api_placeholder">
|
||||
Fitur ini akan tersedia di QuantumBotX API versi mendatang.
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,24 +69,24 @@
|
||||
|
||||
<div class="lg:col-span-1 space-y-6">
|
||||
<div class="bg-white p-6 rounded-lg shadow">
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="quick-settings-title">Pengaturan Cepat</h3>
|
||||
<h3 class="text-lg font-semibold text-gray-800 border-b pb-4 mb-4" id="quick-settings-title" data-i18n="settings.quick_settings">Pengaturan Cepat</h3>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-700" id="notifications-label">Notifikasi Email</span>
|
||||
<span class="text-sm text-gray-700" id="notifications-label" data-i18n="settings.email_notifications">Notifikasi Email</span>
|
||||
<input type="checkbox" id="email-notifications" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-700" id="auto-update-label">Update Otomatis Strategi</span>
|
||||
<span class="text-sm text-gray-700" id="auto-update-label" data-i18n="settings.auto_update">Update Otomatis Strategi</span>
|
||||
<input type="checkbox" id="auto-update" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-700" id="demo-mode-label">Mode Demo</span>
|
||||
<span class="text-sm text-gray-700" id="demo-mode-label" data-i18n="settings.demo_mode">Mode Demo</span>
|
||||
<input type="checkbox" id="demo-mode" checked class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
<div class="text-sm text-gray-600" id="version-info">
|
||||
<strong>Versi:</strong> 2.0.0<br>
|
||||
<strong>Terakhir Update:</strong> September 2025
|
||||
<strong data-i18n="settings.version">Versi:</strong> 2.0.0<br>
|
||||
<strong data-i18n="settings.last_updated">Terakhir Update:</strong> September 2025
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,4 +96,4 @@
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('static', filename='js/settings.js') }}"></script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
+10
-9
@@ -1,13 +1,14 @@
|
||||
<!-- templates/stocks.html (Setelah Refactor) -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}market.stocks_title{% endblock %}
|
||||
{% block title %}Stocks Market{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Pasar Saham</h2>
|
||||
<p class="text-gray-600">Data harga real-time dari pasar saham global.</p>
|
||||
<h2 class="text-2xl font-bold text-gray-800" data-i18n="market.stocks_title">Pasar Saham</h2>
|
||||
<p class="text-gray-600" data-i18n="market.stocks_description">Data harga real-time dari pasar saham global.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,15 +16,15 @@
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Saham</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Harga</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Perubahan 24j</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Waktu</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.stock">Saham</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.price">Harga</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.change_24h">Perubahan 24j</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="market.time">Waktu</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="action.view">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="stocks-table-body" class="bg-white divide-y divide-gray-200">
|
||||
<tr><td colspan="5" class="p-4 text-center text-gray-500">Memuat data saham...</td></tr>
|
||||
<tr><td colspan="5" class="p-4 text-center text-gray-500" data-i18n="market.loading_stocks">Memuat data saham...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -38,7 +39,7 @@
|
||||
</div>
|
||||
<div class="items-center px-4 py-3">
|
||||
<button id="close-modal" class="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-300">
|
||||
Close
|
||||
<span data-i18n="market.close">Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<!-- templates/strategy_switcher/dashboard.html -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}strategy_switcher.title{% endblock %}
|
||||
{% block title %}Strategy Switcher Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Header -->
|
||||
<div class="mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-800 mb-2">🔄 Automatic Strategy Switcher</h1>
|
||||
<p class="text-gray-600">Real-time monitoring and performance analytics for automatic strategy switching</p>
|
||||
<h1 class="text-3xl font-bold text-gray-800 mb-2" data-i18n="strategy_switcher.header">🔄 Automatic Strategy Switcher</h1>
|
||||
<p class="text-gray-600" data-i18n="strategy_switcher.subtitle">Real-time monitoring and performance analytics for automatic strategy switching</p>
|
||||
</div>
|
||||
|
||||
<!-- Current Status Card -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-800">Current Status</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-800" data-i18n="strategy_switcher.current_status">Current Status</h2>
|
||||
<div class="flex space-x-2">
|
||||
<button id="manual-trigger" class="px-3 py-1 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm">
|
||||
<button id="manual-trigger" class="px-3 py-1 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm" data-i18n="strategy_switcher.manual_evaluate">
|
||||
Manual Evaluate
|
||||
</button>
|
||||
<span id="cooldown-status" class="px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800">
|
||||
<span id="cooldown-status" class="px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800" data-i18n="strategy_switcher.loading">
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
@@ -27,22 +27,22 @@
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div class="border rounded-lg p-4">
|
||||
<div class="text-sm text-gray-500 mb-1">Active Strategy</div>
|
||||
<div id="current-strategy" class="text-lg font-semibold text-blue-600">
|
||||
<div class="text-sm text-gray-500 mb-1" data-i18n="strategy_switcher.active_strategy">Active Strategy</div>
|
||||
<div id="current-strategy" class="text-lg font-semibold text-blue-600" data-i18n="strategy_switcher.loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border rounded-lg p-4">
|
||||
<div class="text-sm text-gray-500 mb-1">Active Symbol</div>
|
||||
<div id="current-symbol" class="text-lg font-semibold text-blue-600">
|
||||
<div class="text-sm text-gray-500 mb-1" data-i18n="strategy_switcher.active_symbol">Active Symbol</div>
|
||||
<div id="current-symbol" class="text-lg font-semibold text-blue-600" data-i18n="strategy_switcher.loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border rounded-lg p-4">
|
||||
<div class="text-sm text-gray-500 mb-1">Last Switch</div>
|
||||
<div id="last-switch" class="text-lg font-semibold">
|
||||
<div class="text-sm text-gray-500 mb-1" data-i18n="strategy_switcher.last_switch">Last Switch</div>
|
||||
<div id="last-switch" class="text-lg font-semibold" data-i18n="strategy_switcher.loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,8 +52,8 @@
|
||||
<!-- Strategy Rankings -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-800">📊 Strategy Performance Rankings</h2>
|
||||
<button id="refresh-rankings" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm">
|
||||
<h2 class="text-xl font-semibold text-gray-800" data-i18n="strategy_switcher.performance_rankings">📊 Strategy Performance Rankings</h2>
|
||||
<button id="refresh-rankings" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm" data-i18n="strategy_switcher.refresh_rankings">
|
||||
Refresh Rankings
|
||||
</button>
|
||||
</div>
|
||||
@@ -62,17 +62,17 @@
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Rank</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Strategy/Symbol</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Composite Score</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Profitability</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Risk Control</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Market Fit</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="strategy_switcher.rank">Rank</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="strategy_switcher.strategy_symbol">Strategy/Symbol</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="strategy_switcher.composite_score">Composite Score</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="strategy_switcher.profitability">Profitability</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="strategy_switcher.risk_control">Risk Control</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="strategy_switcher.market_fit">Market Fit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="rankings-table" class="bg-white divide-y divide-gray-200">
|
||||
<tr>
|
||||
<td colspan="6" class="px-6 py-4 text-center text-gray-500">
|
||||
<td colspan="6" class="px-6 py-4 text-center text-gray-500" data-i18n="strategy_switcher.loading_strategy_rankings">
|
||||
Loading strategy rankings...
|
||||
</td>
|
||||
</tr>
|
||||
@@ -84,14 +84,14 @@
|
||||
<!-- Recent Switches -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-800">⚡ Recent Strategy Switches</h2>
|
||||
<button id="refresh-switches" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm">
|
||||
<h2 class="text-xl font-semibold text-gray-800" data-i18n="strategy_switcher.recent_switches">⚡ Recent Strategy Switches</h2>
|
||||
<button id="refresh-switches" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 text-sm" data-i18n="strategy_switcher.refresh_switches">
|
||||
Refresh Switches
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="recent-switches-container">
|
||||
<div class="text-center py-8 text-gray-500">
|
||||
<div class="text-center py-8 text-gray-500" data-i18n="strategy_switcher.loading_recent_switches">
|
||||
Loading recent switches...
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,22 +99,22 @@
|
||||
|
||||
<!-- Monitored Instruments -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6">
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4">🔍 Monitored Instruments & Strategies</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-800 mb-4" data-i18n="strategy_switcher.monitored_instruments">🔍 Monitored Instruments & Strategies</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3"> Instruments</h3>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3" data-i18n="strategy_switcher.instruments"> Instruments</h3>
|
||||
<div id="monitored-instruments" class="flex flex-wrap gap-2">
|
||||
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800">
|
||||
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800" data-i18n="strategy_switcher.loading">
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3">Strategies</h3>
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-3" data-i18n="strategy_switcher.strategies">Strategies</h3>
|
||||
<div id="test-strategies" class="flex flex-wrap gap-2">
|
||||
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800">
|
||||
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800" data-i18n="strategy_switcher.loading">
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
@@ -142,16 +142,16 @@ function updateStatus(status) {
|
||||
if (status.last_switch_time) {
|
||||
lastSwitchElement.textContent = formatDateTime(status.last_switch_time);
|
||||
} else {
|
||||
lastSwitchElement.innerHTML = '<span class="text-gray-400">Never</span>';
|
||||
lastSwitchElement.innerHTML = '<span class="text-gray-400" data-i18n="strategy_switcher.never">Never</span>';
|
||||
}
|
||||
|
||||
const cooldownElement = document.getElementById('cooldown-status');
|
||||
if (status.in_cooldown) {
|
||||
cooldownElement.className = 'px-3 py-1 rounded-full text-sm font-medium bg-yellow-100 text-yellow-800';
|
||||
cooldownElement.textContent = 'Cooldown Active';
|
||||
cooldownElement.textContent = window.QuantumBotXI18n.t('strategy_switcher.cooldown_active');
|
||||
} else {
|
||||
cooldownElement.className = 'px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800';
|
||||
cooldownElement.textContent = 'Active';
|
||||
cooldownElement.textContent = window.QuantumBotXI18n.t('strategy_switcher.active');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ function updateRankings(rankings) {
|
||||
if (!rankings || rankings.length === 0) {
|
||||
tableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="6" class="px-6 py-4 text-center text-gray-500">
|
||||
<td colspan="6" class="px-6 py-4 text-center text-gray-500" data-i18n="strategy_switcher.no_strategy_rankings">
|
||||
No strategy rankings available
|
||||
</td>
|
||||
</tr>
|
||||
@@ -217,7 +217,7 @@ function updateRecentSwitches(switches) {
|
||||
|
||||
if (!switches || switches.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="text-center py-8 text-gray-500">
|
||||
<div class="text-center py-8 text-gray-500" data-i18n="strategy_switcher.no_strategy_switches">
|
||||
<p>No strategy switches recorded yet.</p>
|
||||
</div>
|
||||
`;
|
||||
@@ -233,16 +233,16 @@ function updateRecentSwitches(switches) {
|
||||
if (decision.action === 'STRATEGY_SWITCH') {
|
||||
switchDetails = `
|
||||
<div class="text-sm">
|
||||
<span class="font-medium">Switched from</span>
|
||||
<span class="font-medium" data-i18n="strategy_switcher.switch_from">Switched from</span>
|
||||
<span class="text-red-600">${decision.old_strategy}/${decision.old_symbol}</span>
|
||||
<span class="font-medium">to</span>
|
||||
<span class="font-medium" data-i18n="strategy_switcher.switch_to">to</span>
|
||||
<span class="text-green-600">${decision.new_strategy}/${decision.new_symbol}</span>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
switchDetails = `
|
||||
<div class="text-sm">
|
||||
<span class="font-medium">Initialized with</span>
|
||||
<span class="font-medium" data-i18n="strategy_switcher.initialized_with">Initialized with</span>
|
||||
<span class="text-green-600">${decision.new_strategy}/${decision.new_symbol}</span>
|
||||
</div>
|
||||
`;
|
||||
@@ -269,7 +269,7 @@ function updateRecentSwitches(switches) {
|
||||
|
||||
<div class="text-right">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
Score: ${decision.confidence.toFixed(3)}
|
||||
<span data-i18n="strategy_switcher.score">Score:</span> ${decision.confidence.toFixed(3)}
|
||||
</div>
|
||||
${improvementHtml}
|
||||
</div>
|
||||
@@ -294,7 +294,7 @@ function updateConfiguration(config) {
|
||||
</span>`
|
||||
).join(' ');
|
||||
} else {
|
||||
instrumentsContainer.innerHTML = '<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800">None</span>';
|
||||
instrumentsContainer.innerHTML = '<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800" data-i18n="strategy_switcher.none">None</span>';
|
||||
}
|
||||
|
||||
if (config.test_strategies && config.test_strategies.length > 0) {
|
||||
@@ -304,7 +304,7 @@ function updateConfiguration(config) {
|
||||
</span>`
|
||||
).join(' ');
|
||||
} else {
|
||||
strategiesContainer.innerHTML = '<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800">None</span>';
|
||||
strategiesContainer.innerHTML = '<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800" data-i18n="strategy_switcher.none">None</span>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,16 +322,16 @@ async function manualTrigger() {
|
||||
|
||||
if (result.success) {
|
||||
// Show success message
|
||||
alert('Manual strategy evaluation completed successfully!');
|
||||
alert(window.QuantumBotXI18n.t('msg.success'));
|
||||
// Refresh all data
|
||||
fetchData();
|
||||
} else {
|
||||
// Show error message
|
||||
alert(`Error: ${result.error}`);
|
||||
alert(`${window.QuantumBotXI18n.t('msg.error')}: ${result.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error triggering manual evaluation:', error);
|
||||
alert('Error triggering manual evaluation. Check console for details.');
|
||||
alert(`${window.QuantumBotXI18n.t('error.connection')}. Check console for details.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Set up manual trigger button
|
||||
document.getElementById('manual-trigger').addEventListener('click', function() {
|
||||
if (confirm('Are you sure you want to manually trigger strategy evaluation?')) {
|
||||
if (confirm(window.QuantumBotXI18n.t('strategy_switcher.manual_trigger_confirm'))) {
|
||||
manualTrigger();
|
||||
}
|
||||
});
|
||||
|
||||
+39
-37
@@ -1,5 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title_key %}bots.title{% endblock %}
|
||||
{% block title %}Trading Bots{% endblock %}
|
||||
|
||||
{% block head_extra %}
|
||||
@@ -10,26 +11,26 @@
|
||||
<!-- Header Halaman: Judul di kiri, tombol di kanan -->
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Trading Bots</h2>
|
||||
<p class="text-gray-600">Kelola semua bot dan strategi Anda.</p>
|
||||
<h2 class="text-2xl font-bold text-gray-800" data-i18n="bots.title">Trading Bots</h2>
|
||||
<p class="text-gray-600" data-i18n="bots.manage">Kelola semua bot dan strategi Anda.</p>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button id="start-all-btn" class="bg-green-500 text-white py-2 px-4 rounded-lg font-medium hover:bg-green-600 transition flex items-center" title="Jalankan semua bot yang dijeda">
|
||||
<i class="fas fa-play mr-2"></i> Start All</button>
|
||||
<button id="stop-all-btn" class="bg-red-500 text-white py-2 px-4 rounded-lg font-medium hover:bg-red-600 transition flex items-center" title="Hentikan semua bot yang aktif">
|
||||
<i class="fas fa-stop mr-2"></i> Stop All</button>
|
||||
<button id="create-bot-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700 transition flex items-center"><i class="fas fa-plus mr-2"></i> Buat Bot Baru</button>
|
||||
<button id="start-all-btn" class="bg-green-500 text-white py-2 px-4 rounded-lg font-medium hover:bg-green-600 transition flex items-center" data-i18n-title="bots.start_all_title" title="Jalankan semua bot yang dijeda">
|
||||
<i class="fas fa-play mr-2"></i> <span data-i18n="action.start_all">Start All</span></button>
|
||||
<button id="stop-all-btn" class="bg-red-500 text-white py-2 px-4 rounded-lg font-medium hover:bg-red-600 transition flex items-center" data-i18n-title="bots.stop_all_title" title="Hentikan semua bot yang aktif">
|
||||
<i class="fas fa-stop mr-2"></i> <span data-i18n="action.stop_all">Stop All</span></button>
|
||||
<button id="create-bot-btn" class="bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700 transition flex items-center"><i class="fas fa-plus mr-2"></i> <span data-i18n="action.create_new_bot">Buat Bot Baru</span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-gray-200" aria-label="Trading Bots Table">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nama / Pasar</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Parameter</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Konfigurasi</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
|
||||
<th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="bots.name_market">Nama / Pasar</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="bots.parameters">Parameter</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="bots.configuration">Konfigurasi</th>
|
||||
<th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="label.status">Status</th>
|
||||
<th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider" data-i18n="bots.actions">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="bots-table-body" class="bg-white divide-y divide-gray-200"></tbody>
|
||||
@@ -46,12 +47,12 @@
|
||||
|
||||
<!-- Header Modal (Tidak akan ikut ter-scroll) -->
|
||||
<div class="flex-shrink-0 flex items-start justify-between p-5 border-b rounded-t">
|
||||
<h3 id="modal-title" class="text-xl font-semibold text-gray-900">
|
||||
<h3 id="modal-title" class="text-xl font-semibold text-gray-900" data-i18n="bots.create_new">
|
||||
🚀 Buat Bot Baru
|
||||
</h3>
|
||||
<button type="button" id="cancel-create" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center">
|
||||
<i class="fas fa-times"></i>
|
||||
<span class="sr-only">Tutup modal</span>
|
||||
<span class="sr-only" data-i18n="bots.close_modal">Tutup modal</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -61,45 +62,45 @@
|
||||
<!-- Baris 1: Nama & Pasar -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="name" class="block mb-2 text-sm font-medium text-gray-900">Nama Bot</label>
|
||||
<input type="text" name="name" id="name" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" placeholder="Contoh: XAUUSD Hybrid H1" required>
|
||||
<label for="name" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.bot_name">Nama Bot</label>
|
||||
<input type="text" name="name" id="name" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" data-i18n-placeholder="bots.example_name" placeholder="Contoh: XAUUSD Hybrid H1" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="market" class="block mb-2 text-sm font-medium text-gray-900">Pasar</label>
|
||||
<input type="text" name="market" id="market" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" placeholder="Contoh: XAUUSD atau EURUSD" required>
|
||||
<label for="market" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.market">Pasar</label>
|
||||
<input type="text" name="market" id="market" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" data-i18n-placeholder="bots.example_market" placeholder="Contoh: XAUUSD atau EURUSD" required>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Baris 2: Lot, SL, TP -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div>
|
||||
<label for="risk_percent" class="block mb-2 text-sm font-medium text-gray-900">Risk per Trade (%)</label>
|
||||
<label for="risk_percent" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.risk_per_trade">Risk per Trade (%)</label>
|
||||
<input type="number" name="risk_percent" id="risk_percent" value="1.0" step="0.1" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="sl_atr_multiplier" class="block mb-2 text-sm font-medium text-gray-900">SL (ATR Multiplier)</label>
|
||||
<label for="sl_atr_multiplier" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.sl_atr">SL (ATR Multiplier)</label>
|
||||
<input type="number" name="sl_atr_multiplier" id="sl_atr_multiplier" value="2.0" step="0.1" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="tp_atr_multiplier" class="block mb-2 text-sm font-medium text-gray-900">TP (ATR Multiplier)</label>
|
||||
<label for="tp_atr_multiplier" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.tp_atr">TP (ATR Multiplier)</label>
|
||||
<input type="number" name="tp_atr_multiplier" id="tp_atr_multiplier" value="4.0" step="0.1" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Baris 3: Timeframe & Interval -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="timeframe" class="block mb-2 text-sm font-medium text-gray-900">Timeframe</label>
|
||||
<label for="timeframe" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.timeframe">Timeframe</label>
|
||||
<select id="timeframe" name="timeframe" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
<option value="M1">1 Menit</option>
|
||||
<option value="M5">5 Menit</option>
|
||||
<option value="M15">15 Menit</option>
|
||||
<option value="M30">30 Menit</option>
|
||||
<option value="H1" selected>1 Jam</option>
|
||||
<option value="H4">4 Jam</option>
|
||||
<option value="D1">1 Hari</option>
|
||||
<option value="M1" data-i18n="bots.timeframe_1m">1 Menit</option>
|
||||
<option value="M5" data-i18n="bots.timeframe_5m">5 Menit</option>
|
||||
<option value="M15" data-i18n="bots.timeframe_15m">15 Menit</option>
|
||||
<option value="M30" data-i18n="bots.timeframe_30m">30 Menit</option>
|
||||
<option value="H1" selected data-i18n="bots.timeframe_1h">1 Jam</option>
|
||||
<option value="H4" data-i18n="bots.timeframe_4h">4 Jam</option>
|
||||
<option value="D1" data-i18n="bots.timeframe_1d">1 Hari</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="check_interval_seconds" class="block mb-2 text-sm font-medium text-gray-900">Interval Cek (detik)</label>
|
||||
<label for="check_interval_seconds" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.check_interval">Interval Cek (detik)</label>
|
||||
<input type="number" name="check_interval_seconds" id="check_interval_seconds" value="60" step="1" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,27 +108,28 @@
|
||||
<div class="border-t pt-4">
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" id="enable_strategy_switching" name="enable_strategy_switching" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500">
|
||||
<label for="enable_strategy_switching" class="ml-2 text-sm font-medium text-gray-900">Aktifkan Automatic Strategy Switching</label>
|
||||
<label for="enable_strategy_switching" class="ml-2 text-sm font-medium text-gray-900" data-i18n="bots.enable_strategy_switching">Aktifkan Automatic Strategy Switching</label>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-gray-500">Jika diaktifkan, bot akan secara otomatis beralih ke strategi terbaik berdasarkan kinerja terkini.</p>
|
||||
<p class="mt-1 text-xs text-gray-500" data-i18n="bots.strategy_switching_info">Jika diaktifkan, bot akan secara otomatis beralih ke strategi terbaik berdasarkan kinerja terkini.</p>
|
||||
</div>
|
||||
<!-- Baris 4: Strategi & Parameternya -->
|
||||
<div>
|
||||
<label for="strategy" class="block mb-2 text-sm font-medium text-gray-900">Strategi</label>
|
||||
<label for="strategy" class="block mb-2 text-sm font-medium text-gray-900" data-i18n="label.strategy">Strategi</label>
|
||||
<select id="strategy" name="strategy" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required>
|
||||
<option value="" disabled selected>Pilih sebuah strategi</option>
|
||||
<option value="" disabled selected data-i18n="bots.select_strategy">Pilih sebuah strategi</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="strategy-params-container" class="grid grid-cols-1 md:grid-cols-2 gap-6 pt-4 border-t">
|
||||
<!-- Parameter strategi akan dimuat di sini oleh JavaScript -->
|
||||
<span data-i18n="bots.strategy_params_loaded">Parameter strategi akan dimuat di sini oleh JavaScript</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Footer Modal (Tidak akan ikut ter-scroll) -->
|
||||
<div class="flex-shrink-0 flex items-center p-6 space-x-2 border-t border-gray-200 rounded-b">
|
||||
<button type="submit" id="submit-bot-btn" form="create-bot-form" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center">Buat Bot</button>
|
||||
<button type="button" id="cancel-create-footer" class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10">Batal</button>
|
||||
<button type="submit" id="submit-bot-btn" form="create-bot-form" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center" data-i18n="bots.create_bot">Buat Bot</button>
|
||||
<button type="button" id="cancel-create-footer" class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10" data-i18n="bots.cancel">Batal</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -135,4 +137,4 @@
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('static', filename='js/trading_bots.js') }}"></script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "api/app.py",
|
||||
"use": "@vercel/python",
|
||||
"config": {
|
||||
"runtime": "python3.12"
|
||||
}
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "api/app.py"
|
||||
}
|
||||
],
|
||||
"env": {
|
||||
"SKIP_MT5_INIT": "1"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user