Files
XauBot/backtests/archive/test_simulation.py
T
GifariKemal 7af9183af3 feat: Smart AI Trading Bot for XAUUSD with ML and SMC
- XGBoost ML model with 37 features for market direction prediction
- Smart Money Concepts (SMC): Order Blocks, FVG, BOS, CHoCH
- HMM market regime detection (trending/ranging/volatile)
- ATR-based stop loss with 1.5 ATR minimum distance
- Broker-level SL protection with fallback
- Time-based exit (max 6 hours per trade)
- Session-aware trading optimized for London/NY overlap
- Auto-retraining based on market conditions
- Telegram notifications and web dashboard
- Backtest results: 63.9% win rate, 2.64 profit factor, 4.83 Sharpe

Backtest period: Jan 2025 - Feb 2026, 654 trades, $4,189 net P/L

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:01:35 +07:00

211 lines
6.8 KiB
Python

"""
Simulation Test - Test the improved trading system without real trades.
Uses real market data but only simulates decisions.
"""
import asyncio
import sys
from datetime import datetime, timedelta
from loguru import logger
from dotenv import load_dotenv
# Configure logging
logger.remove()
logger.add(sys.stdout, format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{message}</cyan>", level="INFO")
load_dotenv()
async def run_simulation():
"""Run simulation test with improved settings."""
print("=" * 60)
print("SIMULATION TEST - IMPROVED TRADING SYSTEM")
print("=" * 60)
print()
# Import components
from src.mt5_connector import MT5Connector
from src.feature_eng import FeatureEngineer
from src.ml_model import TradingModel
from src.smc_polars import SMCAnalyzer, SMCSignal
from src.regime_detector import MarketRegimeDetector
from src.session_filter import SessionFilter
from src.dynamic_confidence import create_dynamic_confidence
from src.smart_risk_manager import create_smart_risk_manager
# Initialize
import os
mt5 = MT5Connector(
login=int(os.getenv('MT5_LOGIN')),
password=os.getenv('MT5_PASSWORD'),
server=os.getenv('MT5_SERVER'),
)
if not mt5.connect():
print("Failed to connect to MT5")
return
print(f"Connected to MT5")
print(f"Balance: ${mt5.account_balance:,.2f}")
print(f"Equity: ${mt5.account_equity:,.2f}")
print()
# Components
feature_eng = FeatureEngineer()
ml_model = TradingModel()
ml_model.load("models/xgboost_model.pkl")
smc = SMCAnalyzer()
regime = MarketRegimeDetector()
regime.load()
session_filter = SessionFilter()
dynamic_conf = create_dynamic_confidence()
risk_manager = create_smart_risk_manager(mt5.account_balance)
print("=" * 60)
print("IMPROVED SETTINGS:")
print("=" * 60)
print(f" ML-only threshold: 85%+ required")
print(f" SMC+ML: Both MUST agree")
print(f" Market quality: Skip POOR and AVOID")
print(f" Min ML confidence: 70%")
print(f" Trade cooldown: 5 minutes")
print(f" Max lot: 0.02")
print(f" Max loss/trade: $30")
print(f" Max daily loss: 2%")
print("=" * 60)
print()
# Fetch data
symbol = "XAUUSD"
df = mt5.get_market_data(symbol, "M5", count=500)
if df is None or len(df) == 0:
print("Failed to fetch data (market might be closed)")
print("Using last available data...")
df = mt5.get_market_data(symbol, "M5", count=500)
if df is None or len(df) == 0:
print("Still no data - market is closed")
mt5.disconnect()
return
print(f"Fetched {len(df)} bars of {symbol} M5 data")
print(f"Latest price: ${df['close'][-1]:,.2f}")
print()
# Feature engineering
df = feature_eng.calculate_all(df)
# Add SMC features (required by ML model)
df = smc.calculate_all(df)
# Regime detection
df = regime.predict(df) # Adds regime columns to df
regime_state = regime.get_current_state(df) # Get regime state object
print(f"Current Regime: {regime_state.regime.value if regime_state else 'N/A'}")
print(f"Recommendation: {regime_state.recommendation if regime_state else 'N/A'}")
print()
# Session check
can_trade, reason, _ = session_filter.can_trade()
session_info = session_filter.get_status_report()
print(f"Session: {session_info.get('current_session', 'Unknown')}")
print(f"Can Trade: {can_trade} - {reason}")
print()
# ML Prediction
feature_cols = [c for c in df.columns if c in ml_model.feature_names]
ml_pred = ml_model.predict(df, feature_cols)
print(f"ML Prediction: {ml_pred.signal} ({ml_pred.confidence:.0%})")
print()
# SMC Signal
smc_signal = smc.generate_signal(df)
if smc_signal:
print(f"SMC Signal: {smc_signal.signal_type} ({smc_signal.confidence:.0%})")
print(f" Entry: {smc_signal.entry_price:.2f}")
print(f" SL: {smc_signal.stop_loss:.2f}")
print(f" TP: {smc_signal.take_profit:.2f}")
else:
print("SMC Signal: NONE")
print()
# Dynamic Confidence Analysis
market_analysis = dynamic_conf.analyze_market(
session=session_info.get('current_session', 'Unknown'),
regime=regime_state.regime.value,
volatility=session_info.get('volatility', 'medium'),
trend_direction=regime_state.regime.value,
has_smc_signal=(smc_signal is not None),
ml_signal=ml_pred.signal,
ml_confidence=ml_pred.confidence,
)
print("=" * 60)
print("MARKET ANALYSIS:")
print("=" * 60)
print(f" Quality: {market_analysis.quality.value.upper()}")
print(f" Score: {market_analysis.score}")
print(f" Threshold: {market_analysis.confidence_threshold:.0%}")
print()
for reason in market_analysis.reasons:
print(f" {reason}")
print()
# Entry Decision
print("=" * 60)
print("ENTRY DECISION (SIMULATION):")
print("=" * 60)
# Check conditions
should_trade = False
trade_reason = ""
# 1. Market quality check
if market_analysis.quality.value in ["poor", "avoid"]:
trade_reason = f"SKIP: Market quality {market_analysis.quality.value}"
# 2. ML confidence check
elif ml_pred.confidence < 0.70:
trade_reason = f"SKIP: ML confidence {ml_pred.confidence:.0%} < 70%"
# 3. ML-only (no SMC)
elif smc_signal is None:
if ml_pred.confidence >= 0.85:
should_trade = True
trade_reason = f"TRADE (ML-ONLY): {ml_pred.signal} at {ml_pred.confidence:.0%}"
else:
trade_reason = f"SKIP: ML-only needs 85%+, got {ml_pred.confidence:.0%}"
# 4. SMC + ML combination
else:
ml_agrees = (
(smc_signal.signal_type == "BUY" and ml_pred.signal == "BUY") or
(smc_signal.signal_type == "SELL" and ml_pred.signal == "SELL")
)
if ml_agrees:
should_trade = True
trade_reason = f"TRADE (SMC+ML): {smc_signal.signal_type} - Both agree!"
else:
trade_reason = f"SKIP: SMC={smc_signal.signal_type} vs ML={ml_pred.signal} - Disagree"
print(f" {trade_reason}")
print()
if should_trade:
# Calculate lot size
lot = risk_manager.calculate_lot_size(
entry_price=df['close'][-1],
confidence=ml_pred.confidence,
regime=regime_state.regime.value,
)
print(f" Simulated Trade:")
print(f" Direction: {ml_pred.signal}")
print(f" Lot Size: {lot}")
print(f" Entry: ${df['close'][-1]:,.2f}")
else:
print(f" No trade - waiting for better conditions")
print()
print("=" * 60)
print("SIMULATION COMPLETE")
print("=" * 60)
mt5.disconnect()
if __name__ == "__main__":
asyncio.run(run_simulation())