#!/usr/bin/env python3 """ Strategy Comparison Script Runs both strategies and compares their performance. """ import sys # Add src directory to path for imports sys.path.append('src') sys.path.append('config') from src.logger_setup import setup_logging from src.data_handler import DataHandler from src.strategy_factory import get_strategy import logging def run_strategy_comparison(): """Compare both strategies side by side""" setup_logging() logger = logging.getLogger(__name__) print("=" * 80) print("STRATEGY COMPARISON - CONSERVATIVE vs ENHANCED") print("=" * 80) try: # Get data once for both strategies data_handler = DataHandler() bars = data_handler.get_historical_data(days=180) if bars.empty: print("āŒ No historical data available") return # Calculate technical indicators bars = data_handler.calculate_technical_indicators(bars) strategies = ['conservative', 'enhanced'] results = {} for strategy_type in strategies: print(f"\nšŸ“Š Running {strategy_type.upper()} strategy...") try: # Create strategy strategy = get_strategy(strategy_type) # Generate signals strategy_bars = bars.copy() strategy_bars = strategy.generate_signals(strategy_bars) # Run simulation results[strategy_type] = run_strategy_simulation(strategy_bars, strategy) print(f"āœ… {strategy.name} completed") except Exception as e: print(f"āŒ Error running {strategy_type} strategy: {e}") continue # Display comparison display_strategy_comparison(results) except Exception as e: logger.error(f"Error in strategy comparison: {e}") print(f"āŒ Comparison failed: {e}") def run_strategy_simulation(bars, strategy): """Run simulation for a strategy""" # Position tracking position = 0 entry_price = None highest_price_since_entry = None bars_since_entry = 0 trades = [] bars['position'] = 0 for i in range(1, len(bars)): current_price = bars['close'].iloc[i] if bars['buy_signal'].iloc[i] and position == 0: # Entry conditions if strategy.get_entry_conditions(bars, i): position = 1 entry_price = current_price highest_price_since_entry = current_price bars_since_entry = 0 elif position == 1: bars_since_entry += 1 if current_price > highest_price_since_entry: highest_price_since_entry = current_price # Exit conditions should_exit, exit_reason = strategy.should_exit_position( current_price=current_price, entry_price=entry_price, highest_price=highest_price_since_entry, bars_since_entry=bars_since_entry, sell_signal=bars['sell_signal'].iloc[i], ema_trend=bars['ema_trend'].iloc[i] ) if should_exit: # Record trade profit_pct = (current_price / entry_price - 1) trades.append({ 'entry_price': entry_price, 'exit_price': current_price, 'profit_pct': profit_pct, 'bars_held': bars_since_entry, 'exit_reason': exit_reason }) position = 0 entry_price = None highest_price_since_entry = None bars_since_entry = 0 bars.iloc[i, bars.columns.get_loc('position')] = position # Calculate returns bars['market_return'] = bars['close'].pct_change() bars['strategy_return'] = bars['position'].shift(1) * bars['market_return'] # Apply costs trade_cost = 0.0005 bars['position_change'] = bars['position'].diff().abs() bars['costs'] = bars['position_change'] * trade_cost bars['strategy_return'] = bars['strategy_return'] - bars['costs'] # Cumulative returns bars['cum_strategy'] = (1 + bars['strategy_return']).cumprod() - 1 bars['cum_market'] = (1 + bars['market_return']).cumprod() - 1 # Calculate metrics total_return = bars['cum_strategy'].iloc[-1] * 100 market_return = bars['cum_market'].iloc[-1] * 100 if len(trades) > 0: import numpy as np trade_returns = [t['profit_pct'] for t in trades] trade_returns = np.array(trade_returns) win_rate = (trade_returns > 0).mean() * 100 avg_win = trade_returns[trade_returns > 0].mean() * 100 if (trade_returns > 0).any() else 0 avg_loss = trade_returns[trade_returns < 0].mean() * 100 if (trade_returns < 0).any() else 0 max_win = trade_returns.max() * 100 max_loss = trade_returns.min() * 100 total_wins = trade_returns[trade_returns > 0].sum() total_losses = abs(trade_returns[trade_returns < 0].sum()) profit_factor = total_wins / total_losses if total_losses > 0 else float('inf') else: win_rate = avg_win = avg_loss = max_win = max_loss = profit_factor = 0 # Max drawdown running_max = bars['cum_strategy'].cummax() drawdown = (bars['cum_strategy'] - running_max) max_drawdown = drawdown.min() * 100 # Sharpe ratio if bars['strategy_return'].std() > 0: import numpy as np sharpe = bars['strategy_return'].mean() / bars['strategy_return'].std() * np.sqrt(365 * 24) else: sharpe = 0 return { 'total_return': total_return, 'market_return': market_return, 'outperformance': total_return - market_return, 'sharpe_ratio': sharpe, 'max_drawdown': max_drawdown, 'total_trades': len(trades), 'win_rate': win_rate, 'profit_factor': profit_factor, 'avg_win': avg_win, 'avg_loss': avg_loss, 'max_win': max_win, 'max_loss': max_loss, 'time_in_market': (bars['position'] > 0).mean() * 100, 'trades': trades } def display_strategy_comparison(results): """Display side-by-side comparison""" if len(results) < 2: print("āŒ Need at least 2 strategies to compare") return print("\n" + "=" * 100) print("STRATEGY COMPARISON RESULTS") print("=" * 100) # Header print(f"{'Metric':<25} {'Conservative':<20} {'Enhanced':<20} {'Difference':<15}") print("-" * 100) conservative = results.get('conservative', {}) enhanced = results.get('enhanced', {}) metrics = [ ('Total Return', 'total_return', '%'), ('Market Return', 'market_return', '%'), ('Outperformance', 'outperformance', '%'), ('Sharpe Ratio', 'sharpe_ratio', ''), ('Max Drawdown', 'max_drawdown', '%'), ('Total Trades', 'total_trades', ''), ('Win Rate', 'win_rate', '%'), ('Profit Factor', 'profit_factor', ''), ('Avg Win', 'avg_win', '%'), ('Avg Loss', 'avg_loss', '%'), ('Max Win', 'max_win', '%'), ('Max Loss', 'max_loss', '%'), ('Time in Market', 'time_in_market', '%'), ] for display_name, key, unit in metrics: cons_val = conservative.get(key, 0) enh_val = enhanced.get(key, 0) diff = enh_val - cons_val if unit == '%': cons_str = f"{cons_val:>8.2f}%" enh_str = f"{enh_val:>8.2f}%" diff_str = f"{diff:>+8.2f}%" else: cons_str = f"{cons_val:>8.2f}" enh_str = f"{enh_val:>8.2f}" diff_str = f"{diff:>+8.2f}" print(f"{display_name:<25} {cons_str:<20} {enh_str:<20} {diff_str:<15}") print("=" * 100) # Summary print("\nšŸ“‹ SUMMARY:") if enhanced.get('total_return', 0) > conservative.get('total_return', 0): winner = "Enhanced" return_diff = enhanced.get('total_return', 0) - conservative.get('total_return', 0) else: winner = "Conservative" return_diff = conservative.get('total_return', 0) - enhanced.get('total_return', 0) print(f"šŸ† Best performing strategy: {winner} (+{return_diff:.2f}% return)") # Risk comparison cons_risk = abs(conservative.get('max_drawdown', 0)) enh_risk = abs(enhanced.get('max_drawdown', 0)) if cons_risk < enh_risk: print(f"šŸ›”ļø Lower risk strategy: Conservative ({cons_risk:.2f}% max drawdown)") else: print(f"šŸ›”ļø Lower risk strategy: Enhanced ({enh_risk:.2f}% max drawdown)") print("\nšŸ’” RECOMMENDATIONS:") print("• Conservative: Better for letting big winners run, more relaxed exits") print("• Enhanced: Better risk control, tighter stops for early losses") print("• Choose based on your risk tolerance and market conditions") if __name__ == "__main__": run_strategy_comparison()