mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-27 18:57:47 +00:00
224 lines
8.7 KiB
Python
224 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Debug backtesting execution to find why trades aren't being executed
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
import pandas as pd
|
|
import numpy as np
|
|
from datetime import datetime, timedelta
|
|
|
|
def debug_enhanced_backtest():
|
|
"""Debug the enhanced backtest step by step"""
|
|
print("🔍 DEBUGGING ENHANCED BACKTEST EXECUTION")
|
|
print("=" * 70)
|
|
|
|
try:
|
|
# Import components
|
|
from core.backtesting.enhanced_engine import EnhancedBacktestEngine, InstrumentConfig
|
|
from core.strategies.ma_crossover import MACrossoverStrategy
|
|
|
|
# Create simple test data
|
|
np.random.seed(42)
|
|
base_price = 1.1000
|
|
|
|
data = []
|
|
for i in range(50):
|
|
# Create simple price movement
|
|
if i < 25:
|
|
price = base_price + i * 0.0001 # Uptrend
|
|
else:
|
|
price = base_price + (50-i) * 0.0001 # Downtrend
|
|
|
|
time = datetime(2024, 1, 1) + timedelta(hours=i)
|
|
data.append({
|
|
'time': time,
|
|
'open': price,
|
|
'high': price + 0.00005,
|
|
'low': price - 0.00005,
|
|
'close': price,
|
|
'volume': 10000
|
|
})
|
|
|
|
df = pd.DataFrame(data)
|
|
print(f"Created {len(df)} bars of simple test data")
|
|
|
|
# Strategy setup
|
|
class MockBot:
|
|
def __init__(self):
|
|
self.market_for_mt5 = "EURUSD"
|
|
self.timeframe = "H1"
|
|
|
|
params = {
|
|
'fast_period': 5,
|
|
'slow_period': 15,
|
|
'risk_percent': 1.0,
|
|
'sl_atr_multiplier': 2.0,
|
|
'tp_atr_multiplier': 4.0
|
|
}
|
|
|
|
# Generate signals
|
|
strategy = MACrossoverStrategy(bot_instance=MockBot(), params=params)
|
|
df_with_signals = strategy.analyze_df(df.copy())
|
|
|
|
# Add ATR
|
|
df_with_signals.ta.atr(length=14, append=True)
|
|
df_with_signals.dropna(inplace=True)
|
|
df_with_signals.reset_index(inplace=True)
|
|
|
|
print(f"After processing: {len(df_with_signals)} bars")
|
|
|
|
# Check signals
|
|
signal_counts = df_with_signals['signal'].value_counts()
|
|
print(f"Signals: {dict(signal_counts)}")
|
|
|
|
# Show signal bars
|
|
signal_bars = df_with_signals[df_with_signals['signal'] != 'HOLD']
|
|
print("Signal bars:")
|
|
for i, row in signal_bars.iterrows():
|
|
print(f" Index {i}: {row['signal']} | Close: {row['close']:.5f} | ATR: {row.get('ATRr_14', 'Missing')}")
|
|
|
|
if len(signal_bars) == 0:
|
|
print("❌ No signals generated - can't debug execution")
|
|
return
|
|
|
|
# Manual backtest loop simulation
|
|
print("\\n🔄 SIMULATING BACKTEST LOOP...")
|
|
|
|
# Initialize
|
|
engine = EnhancedBacktestEngine()
|
|
config = InstrumentConfig.get_config('EURUSD')
|
|
|
|
capital = 10000.0
|
|
trades = []
|
|
in_position = False
|
|
|
|
# Enhanced parameter handling (matching the real engine)
|
|
risk_percent = float(params.get('risk_percent', params.get('lot_size', 1.0)))
|
|
sl_atr_multiplier = float(params.get('sl_atr_multiplier', params.get('sl_pips', 2.0)))
|
|
tp_atr_multiplier = float(params.get('tp_atr_multiplier', params.get('tp_pips', 4.0)))
|
|
|
|
print("Engine parameters:")
|
|
print(f" Risk: {risk_percent}%")
|
|
print(f" SL: {sl_atr_multiplier}x ATR")
|
|
print(f" TP: {tp_atr_multiplier}x ATR")
|
|
print(f" Config: {config}")
|
|
|
|
# Loop through data
|
|
for i in range(1, len(df_with_signals)):
|
|
current_bar = df_with_signals.iloc[i]
|
|
|
|
if capital <= 0:
|
|
print(f"💀 Capital exhausted at bar {i}")
|
|
break
|
|
|
|
if not in_position:
|
|
signal = current_bar.get("signal", "HOLD")
|
|
|
|
if signal in ['BUY', 'SELL']:
|
|
print(f"\\n📊 Processing signal at bar {i}:")
|
|
print(f" Signal: {signal}")
|
|
print(f" Price: {current_bar['close']}")
|
|
print(f" Capital: ${capital:.2f}")
|
|
|
|
atr_value = current_bar.get('ATRr_14', 0)
|
|
print(f" ATR: {atr_value}")
|
|
|
|
if atr_value <= 0:
|
|
print(" ❌ Invalid ATR - skipping")
|
|
continue
|
|
|
|
# Calculate distances
|
|
sl_distance = atr_value * sl_atr_multiplier
|
|
tp_distance = atr_value * tp_atr_multiplier
|
|
|
|
print(f" SL distance: {sl_distance:.5f}")
|
|
print(f" TP distance: {tp_distance:.5f}")
|
|
|
|
# Calculate position size
|
|
lot_size = engine.calculate_position_size(
|
|
'EURUSD', capital, risk_percent, sl_distance, atr_value, config
|
|
)
|
|
|
|
print(f" Calculated lot size: {lot_size}")
|
|
|
|
if lot_size <= 0:
|
|
print(" ❌ Invalid lot size - skipping")
|
|
continue
|
|
|
|
# Calculate entry price
|
|
entry_price = engine.calculate_realistic_entry_price(
|
|
signal, current_bar['close'], config['typical_spread_pips'],
|
|
config['pip_size'], config.get('slippage_pips', 0)
|
|
)
|
|
|
|
print(f" Entry price: {entry_price:.5f}")
|
|
|
|
# Set SL/TP levels
|
|
if signal == 'BUY':
|
|
sl_price = entry_price - sl_distance
|
|
tp_price = entry_price + tp_distance
|
|
else:
|
|
sl_price = entry_price + sl_distance
|
|
tp_price = entry_price - tp_distance
|
|
|
|
print(f" SL: {sl_price:.5f}")
|
|
print(f" TP: {tp_price:.5f}")
|
|
|
|
# Check for emergency brake (from enhanced engine)
|
|
if config == InstrumentConfig.GOLD:
|
|
estimated_risk = sl_distance * lot_size * config['contract_size']
|
|
max_risk_dollar = capital * config.get('emergency_brake_percent', 0.05)
|
|
if estimated_risk > max_risk_dollar:
|
|
print(" 🚨 Emergency brake triggered - skipping")
|
|
continue
|
|
|
|
print(" ✅ Trade would be executed!")
|
|
|
|
# For debugging, let's see if we can find the next exit
|
|
for j in range(i+1, len(df_with_signals)):
|
|
future_bar = df_with_signals.iloc[j]
|
|
|
|
if signal == 'BUY':
|
|
if future_bar['low'] <= sl_price:
|
|
print(f" 📉 SL would hit at bar {j}")
|
|
break
|
|
elif future_bar['high'] >= tp_price:
|
|
print(f" 📈 TP would hit at bar {j}")
|
|
break
|
|
else: # SELL
|
|
if future_bar['high'] >= sl_price:
|
|
print(f" 📉 SL would hit at bar {j}")
|
|
break
|
|
elif future_bar['low'] <= tp_price:
|
|
print(f" 📈 TP would hit at bar {j}")
|
|
break
|
|
|
|
if j > i + 10: # Only check next 10 bars
|
|
print(" ⏰ No exit in next 10 bars")
|
|
break
|
|
|
|
trades.append({'signal': signal, 'entry': entry_price})
|
|
|
|
if len(trades) >= 3: # Limit debug output
|
|
break
|
|
|
|
print("\\n📋 DEBUG SUMMARY:")
|
|
print(f"Processed {len(trades)} potential trades")
|
|
|
|
if len(trades) > 0:
|
|
print("✅ Trade logic is working - trades should execute")
|
|
print("❓ The issue might be in the actual enhanced_engine implementation")
|
|
else:
|
|
print("❌ No trades processed - issue in trade logic")
|
|
|
|
except Exception as e:
|
|
print(f"Error in debug: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
if __name__ == '__main__':
|
|
debug_enhanced_backtest() |