#!/usr/bin/env python3 """ šŸ“Š Trading Bot Performance Analysis (Simple Version - No Dependencies) Umfassende Performance-Auswertung mit nur SQLite """ import sqlite3 from datetime import datetime from collections import defaultdict # ========================================== # DATABASE QUERIES # ========================================== def get_closed_trades(db_path="trading_bot.db", exclude_historical=True): """Lade geschlossene Trades""" conn = sqlite3.connect(db_path) conn.row_factory = sqlite3.Row cursor = conn.cursor() query = """ SELECT ticket, symbol, type, volume, entry_price, exit_price, sl_price, tp_price, entry_time, exit_time, session, regime, quality, confidence, timeframe_alignment, risk_amount, risk_pct, profit, commission, swap, net_profit, profit_pct, rr_ratio, exit_reason, status FROM trades WHERE status = 'closed' """ if exclude_historical: query += " AND status != 'historical'" query += " ORDER BY exit_time DESC" cursor.execute(query) trades = [dict(row) for row in cursor.fetchall()] conn.close() return trades # ========================================== # OVERALL PERFORMANCE # ========================================== def calculate_overall_metrics(trades): """Berechne Overall Performance""" if not trades: return None total_trades = len(trades) wins = [t for t in trades if t['net_profit'] > 0] losses = [t for t in trades if t['net_profit'] <= 0] win_rate = (len(wins) / total_trades * 100) if total_trades > 0 else 0 total_profit = sum(t['net_profit'] for t in trades) avg_profit = total_profit / total_trades if total_trades > 0 else 0 avg_win = sum(t['net_profit'] for t in wins) / len(wins) if wins else 0 avg_loss = sum(t['net_profit'] for t in losses) / len(losses) if losses else 0 profit_factor = abs(avg_win / avg_loss) if avg_loss != 0 else 0 # Calculate drawdown cumulative = 0 max_cumulative = 0 max_drawdown = 0 for trade in sorted(trades, key=lambda x: x['exit_time']): cumulative += trade['net_profit'] if cumulative > max_cumulative: max_cumulative = cumulative drawdown = cumulative - max_cumulative if drawdown < max_drawdown: max_drawdown = drawdown return { 'total_trades': total_trades, 'winning_trades': len(wins), 'losing_trades': len(losses), 'win_rate': win_rate, 'total_profit': total_profit, 'avg_profit': avg_profit, 'avg_win': avg_win, 'avg_loss': avg_loss, 'profit_factor': profit_factor, 'max_drawdown': max_drawdown } # ========================================== # SESSION ANALYSIS # ========================================== def analyze_by_session(trades): """Performance pro Session""" sessions = defaultdict(lambda: {'trades': [], 'wins': 0, 'losses': 0, 'profit': 0}) for trade in trades: session = trade['session'] sessions[session]['trades'].append(trade) sessions[session]['profit'] += trade['net_profit'] if trade['net_profit'] > 0: sessions[session]['wins'] += 1 else: sessions[session]['losses'] += 1 results = [] for session, data in sessions.items(): total = len(data['trades']) win_rate = (data['wins'] / total * 100) if total > 0 else 0 avg_profit = data['profit'] / total if total > 0 else 0 avg_win = sum(t['net_profit'] for t in data['trades'] if t['net_profit'] > 0) avg_win = avg_win / data['wins'] if data['wins'] > 0 else 0 avg_loss = sum(t['net_profit'] for t in data['trades'] if t['net_profit'] <= 0) avg_loss = avg_loss / data['losses'] if data['losses'] > 0 else 0 results.append({ 'session': session.upper(), 'trades': total, 'wins': data['wins'], 'losses': data['losses'], 'win_rate': win_rate, 'total_profit': data['profit'], 'avg_profit': avg_profit, 'avg_win': avg_win, 'avg_loss': avg_loss }) return sorted(results, key=lambda x: x['total_profit'], reverse=True) # ========================================== # CONFIDENCE ANALYSIS # ========================================== def analyze_by_confidence(trades): """Performance pro Confidence Level""" bins = [(0, 60), (60, 70), (70, 75), (75, 80), (80, 100)] conf_groups = defaultdict(lambda: {'trades': [], 'wins': 0, 'profit': 0}) for trade in trades: conf = trade['confidence'] for bin_min, bin_max in bins: if bin_min <= conf < bin_max: key = f"{bin_min}-{bin_max}" conf_groups[key]['trades'].append(trade) conf_groups[key]['profit'] += trade['net_profit'] if trade['net_profit'] > 0: conf_groups[key]['wins'] += 1 break results = [] for conf_range, data in conf_groups.items(): total = len(data['trades']) win_rate = (data['wins'] / total * 100) if total > 0 else 0 avg_profit = data['profit'] / total if total > 0 else 0 results.append({ 'confidence_range': conf_range, 'trades': total, 'wins': data['wins'], 'win_rate': win_rate, 'total_profit': data['profit'], 'avg_profit': avg_profit }) return sorted(results, key=lambda x: x['confidence_range']) # ========================================== # EXIT REASON ANALYSIS # ========================================== def analyze_by_exit_reason(trades): """Performance pro Exit Reason""" reasons = defaultdict(lambda: {'trades': [], 'wins': 0, 'profit': 0}) for trade in trades: reason = trade['exit_reason'] reasons[reason]['trades'].append(trade) reasons[reason]['profit'] += trade['net_profit'] if trade['net_profit'] > 0: reasons[reason]['wins'] += 1 results = [] for reason, data in reasons.items(): total = len(data['trades']) win_rate = (data['wins'] / total * 100) if total > 0 else 0 avg_profit = data['profit'] / total if total > 0 else 0 results.append({ 'exit_reason': reason.upper().replace('_', ' '), 'trades': total, 'wins': data['wins'], 'win_rate': win_rate, 'total_profit': data['profit'], 'avg_profit': avg_profit }) return sorted(results, key=lambda x: x['total_profit'], reverse=True) # ========================================== # TIME ANALYSIS # ========================================== def analyze_by_hour(trades): """Performance pro Stunde""" hours = defaultdict(lambda: {'trades': 0, 'wins': 0, 'profit': 0}) for trade in trades: hour = int(trade['entry_time'][11:13]) # Extract hour from timestamp hours[hour]['trades'] += 1 hours[hour]['profit'] += trade['net_profit'] if trade['net_profit'] > 0: hours[hour]['wins'] += 1 results = [] for hour, data in hours.items(): win_rate = (data['wins'] / data['trades'] * 100) if data['trades'] > 0 else 0 avg_profit = data['profit'] / data['trades'] if data['trades'] > 0 else 0 results.append({ 'hour': hour, 'trades': data['trades'], 'wins': data['wins'], 'win_rate': win_rate, 'total_profit': data['profit'], 'avg_profit': avg_profit }) return sorted(results, key=lambda x: x['total_profit'], reverse=True) # ========================================== # PRINT FUNCTIONS # ========================================== def print_section(title): """Print section header""" print("\n" + "=" * 70) print(f" {title}") print("=" * 70) def print_overall(metrics): """Print overall metrics""" print_section("šŸ“Š OVERALL PERFORMANCE") print(f"\n{'Total Trades:':<25} {metrics['total_trades']}") print(f"{'Winning Trades:':<25} {metrics['winning_trades']} ({metrics['win_rate']:.1f}%)") print(f"{'Losing Trades:':<25} {metrics['losing_trades']}") print(f"\n{'Total Profit:':<25} ${metrics['total_profit']:.2f}") print(f"{'Average Profit/Trade:':<25} ${metrics['avg_profit']:.2f}") print(f"{'Average Win:':<25} ${metrics['avg_win']:.2f}") print(f"{'Average Loss:':<25} ${metrics['avg_loss']:.2f}") print(f"{'Profit Factor:':<25} {metrics['profit_factor']:.2f}") print(f"\n{'Max Drawdown:':<25} ${metrics['max_drawdown']:.2f}") def print_table(data, title): """Print data as table""" print_section(title) if not data: print("\nNo data available") return # Print header headers = list(data[0].keys()) print("\n" + " | ".join(f"{h:<15}" for h in headers)) print("-" * (len(headers) * 18)) # Print rows for row in data: values = [] for key, val in row.items(): if isinstance(val, float): values.append(f"{val:>15.2f}") else: values.append(f"{str(val):<15}") print(" | ".join(values)) # ========================================== # MAIN ANALYSIS # ========================================== def run_analysis(db_path="trading_bot.db", exclude_historical=True): """Run complete performance analysis""" print("=" * 70) print("šŸ“Š TRADING BOT PERFORMANCE ANALYSIS") print("=" * 70) print(f"\nAnalysis Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"Database: {db_path}") print(f"Exclude Historical: {exclude_historical}") # Load data trades = get_closed_trades(db_path, exclude_historical) if not trades: print("\nāŒ No closed trades found!") print("\nPossible reasons:") print(" • Position Monitor not running") print(" • No trades have been closed yet") print(" • Database not synced from VPS") return print(f"\nLoaded {len(trades)} closed trades") # Overall Metrics overall = calculate_overall_metrics(trades) print_overall(overall) # Session Analysis session_data = analyze_by_session(trades) print_table(session_data, "šŸ“ PERFORMANCE BY SESSION") # Confidence Analysis conf_data = analyze_by_confidence(trades) print_table(conf_data, "šŸŽÆ PERFORMANCE BY CONFIDENCE LEVEL") # Exit Reason Analysis exit_data = analyze_by_exit_reason(trades) print_table(exit_data, "🚪 PERFORMANCE BY EXIT REASON") # Hourly Analysis (Top 10) hourly_data = analyze_by_hour(trades) print_table(hourly_data[:10], "ā° TOP 10 HOURS (UTC)") # Recommendations print_section("šŸ’” RECOMMENDATIONS") if session_data: best = session_data[0] worst = session_data[-1] print(f"\nāœ… Best Session: {best['session']}") print(f" Win Rate: {best['win_rate']:.1f}%") print(f" Total Profit: ${best['total_profit']:.2f}") if worst['total_profit'] < 0: print(f"\nāŒ Worst Session: {worst['session']}") print(f" Win Rate: {worst['win_rate']:.1f}%") print(f" Total Loss: ${worst['total_profit']:.2f}") print(f"\n → Consider disabling {worst['session']} session") if conf_data: best_conf = max(conf_data, key=lambda x: x['total_profit']) print(f"\nšŸŽÆ Best Confidence Range: {best_conf['confidence_range']}") print(f" Win Rate: {best_conf['win_rate']:.1f}%") print(f" Total Profit: ${best_conf['total_profit']:.2f}") print("\n" + "=" * 70) print("āœ… Analysis Complete!") print("=" * 70) if __name__ == "__main__": run_analysis( db_path="trading_bot.db", exclude_historical=True )