# backtest.py """ Script principal para ejecutar backtests """ import os from dotenv import load_dotenv from pathlib import Path from datetime import datetime, timedelta from src.utils.logger import log from src.data.storage import StorageManager from src.backtest.engine import BacktestEngine from src.backtest.metrics import print_backtest_report, calculate_all_metrics from src.strategies import MovingAverageCrossover, BuyAndHold, RSIStrategy def setup_environment(): """Carga variables de entorno""" env_path = Path(__file__).parent / 'config' / 'secrets.env' load_dotenv(dotenv_path=env_path) log.success("✓ Variables de entorno cargadas") def run_backtest_demo(): """ Demo de backtesting con estrategia simple """ log.info("="*70) log.info("🧪 BACKTESTING - DEMO") log.info("="*70) # Setup setup_environment() # Configuración del backtest symbol = 'BTC/USDT' timeframe = '1h' days_back = 60 # 2 meses de datos log.info(f"\n📊 Configuración:") log.info(f" Símbolo: {symbol}") log.info(f" Timeframe: {timeframe}") log.info(f" Periodo: {days_back} días") # Conectar a base de datos storage = StorageManager( db_host=os.getenv('DB_HOST'), db_port=int(os.getenv('DB_PORT', 5432)), db_name=os.getenv('DB_NAME'), db_user=os.getenv('DB_USER'), db_password=os.getenv('DB_PASSWORD'), ) # Cargar datos log.info("\n📥 Cargando datos desde PostgreSQL...") end_date = datetime.now() start_date = end_date - timedelta(days=days_back) data = storage.load_ohlcv( symbol=symbol, timeframe=timeframe, start_date=start_date, end_date=end_date, use_cache=False ) if data.empty: log.error(f"❌ No hay datos disponibles para {symbol} {timeframe}") log.info("💡 Ejecuta primero: python download_data.py") return log.success(f"✓ Datos cargados: {len(data)} velas") log.info(f" Desde: {data.index[0]}") log.info(f" Hasta: {data.index[-1]}") # Crear estrategia strategy = MovingAverageCrossover( fast_period=10, slow_period=30, ma_type='sma' ) # Crear motor de backtesting engine = BacktestEngine( strategy=strategy, initial_capital=10000, commission=0.001, # 0.1% slippage=0.0005, # 0.05% position_size=0.95 # Usar 95% del capital ) # Ejecutar backtest log.info("\n🚀 Ejecutando backtest...") results = engine.run(data) # Mostrar resultados print_backtest_report(results) # Calcular métricas adicionales additional_metrics = calculate_all_metrics(results) if additional_metrics: print("\n📈 MÉTRICAS ADICIONALES:") print(f" Sortino Ratio: {additional_metrics['sortino_ratio']:>12.2f}") print(f" Calmar Ratio: {additional_metrics['calmar_ratio']:>12.2f}") print(f" Expectancy: ${additional_metrics['expectancy']:>12,.2f}") print(f" Risk/Reward: {additional_metrics['risk_reward_ratio']:>12.2f}") print(f" Recovery Factor: {additional_metrics['recovery_factor']:>12.2f}") # Mostrar algunos trades de ejemplo if results['trades']: print(f"\n📋 TRADES (primeros 5):") for i, trade in enumerate(results['trades'][:5], 1): print(f"\n Trade #{i}:") print(f" Entrada: {trade.entry_time} @ ${trade.entry_price:.2f}") print(f" Salida: {trade.exit_time} @ ${trade.exit_price:.2f}") print(f" PnL: ${trade.pnl:>10.2f} ({trade.pnl_percentage:>6.2f}%)") print(f" Duración: {trade.duration:.1f}h") # Cleanup storage.close() log.info("\n" + "="*70) log.success("✅ DEMO COMPLETADO") log.info("="*70) return results def compare_strategies_demo(): """ Compara múltiples estrategias sobre los mismos datos """ log.info("="*70) log.info("🔍 COMPARACIÓN DE ESTRATEGIAS") log.info("="*70) setup_environment() # Configuración symbol = 'BTC/USDT' timeframe = '1h' days_back = 60 # Conectar a base de datos y cargar datos storage = StorageManager( db_host=os.getenv('DB_HOST'), db_port=int(os.getenv('DB_PORT', 5432)), db_name=os.getenv('DB_NAME'), db_user=os.getenv('DB_USER'), db_password=os.getenv('DB_PASSWORD'), ) end_date = datetime.now() start_date = end_date - timedelta(days=days_back) data = storage.load_ohlcv(symbol, timeframe, start_date, end_date, use_cache=False) if data.empty: log.error(f"❌ No hay datos disponibles") return log.success(f"✓ Datos cargados: {len(data)} velas") # Definir estrategias a comparar strategies = [ ('Buy & Hold', BuyAndHold()), ('MA Cross (10/30 SMA)', MovingAverageCrossover(10, 30, 'sma')), ('MA Cross (20/50 EMA)', MovingAverageCrossover(20, 50, 'ema')), ('RSI (30/70)', RSIStrategy(14, 30, 70)), ] # Ejecutar backtest para cada estrategia all_results = {} for name, strategy in strategies: log.info(f"\n🧪 Testeando: {name}") engine = BacktestEngine( strategy=strategy, initial_capital=10000, commission=0.001, position_size=0.95 ) results = engine.run(data) all_results[name] = results log.info(f" Retorno: {results['total_return_pct']:.2f}%") log.info(f" Trades: {results['total_trades']}") log.info(f" Win Rate: {results['win_rate_pct']:.2f}%") # Comparar resultados from src.backtest.metrics import compare_strategies compare_strategies(all_results) storage.close() log.success("✅ COMPARACIÓN COMPLETADA") return all_results if __name__ == "__main__": import sys if len(sys.argv) > 1 and sys.argv[1] == 'compare': # Modo comparación compare_strategies_demo() else: # Modo demo simple run_backtest_demo() print("\n💡 TIP: Para comparar estrategias usa: python backtest.py compare")