#!/usr/bin/env python3 """ 🗑️ Historical Trades Cleanup Behandelt die 240 'historical' Trades mit NULL profit """ import sqlite3 import shutil from datetime import datetime DB_PATH = "trading_bot.db" BACKUP_DIR = "backups" def create_backup(): """Backup erstellen""" timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') backup_path = f"{BACKUP_DIR}/trading_bot_before_historical_cleanup_{timestamp}.db" shutil.copy(DB_PATH, backup_path) print(f"✅ Backup: {backup_path}") return backup_path def analyze_historical_trades(conn): """Analysiere historical trades""" print("\n" + "="*80) print("📊 ANALYSE: Historical Trades") print("="*80) cursor = conn.cursor() # Basic info cursor.execute(""" SELECT COUNT(*) as total, MIN(entry_time) as first_trade, MAX(entry_time) as last_trade, COUNT(DISTINCT DATE(entry_time)) as trading_days FROM trades WHERE status = 'historical' AND net_profit IS NULL """) total, first, last, days = cursor.fetchone() print(f"\nTotal: {total} Trades") print(f"Zeitraum: {first} bis {last}") print(f"Trading Days: {days}") # Session breakdown cursor.execute(""" SELECT session, COUNT(*) as count FROM trades WHERE status = 'historical' AND net_profit IS NULL GROUP BY session ORDER BY count DESC """) print("\nSession Breakdown:") for session, count in cursor.fetchall(): print(f" {session:10} {count:3} Trades") # Quality breakdown cursor.execute(""" SELECT quality, COUNT(*) as count, ROUND(AVG(confidence), 1) as avg_conf FROM trades WHERE status = 'historical' AND net_profit IS NULL GROUP BY quality """) print("\nQuality Breakdown:") for quality, count, conf in cursor.fetchall(): print(f" {quality if quality else 'NULL':12} {count:3} Trades (avg conf: {conf}%)") return total def option_delete_historical(conn): """Option 1: Lösche alle historical trades""" print("\n" + "="*80) print("🗑️ OPTION 1: Alle historical Trades LÖSCHEN") print("="*80) cursor = conn.cursor() cursor.execute("DELETE FROM trades WHERE status = 'historical' AND net_profit IS NULL") deleted = cursor.rowcount print(f"✅ Gelöscht: {deleted} Trades") conn.commit() def option_mark_as_invalid(conn): """Option 2: Markiere als invalid statt löschen""" print("\n" + "="*80) print("🏷️ OPTION 2: Als 'invalid' markieren") print("="*80) cursor = conn.cursor() cursor.execute(""" UPDATE trades SET status = 'invalid_historical' WHERE status = 'historical' AND net_profit IS NULL """) updated = cursor.rowcount print(f"✅ Markiert: {updated} Trades als 'invalid_historical'") conn.commit() def option_set_zero_profit(conn): """Option 3: Setze net_profit = 0 (als breakeven)""" print("\n" + "="*80) print("💰 OPTION 3: net_profit = 0 setzen (Breakeven)") print("="*80) cursor = conn.cursor() cursor.execute(""" UPDATE trades SET net_profit = 0.0, profit = 0.0, profit_pct = 0.0, exit_reason = 'historical_migration_breakeven' WHERE status = 'historical' AND net_profit IS NULL """) updated = cursor.rowcount print(f"✅ Updated: {updated} Trades auf Breakeven gesetzt") conn.commit() def verify_cleanup(conn): """Verifiziere Cleanup""" print("\n" + "="*80) print("✅ VERIFICATION") print("="*80) cursor = conn.cursor() # Count historical cursor.execute("SELECT COUNT(*) FROM trades WHERE status = 'historical'") historical = cursor.fetchone()[0] # Count NULL profits cursor.execute("SELECT COUNT(*) FROM trades WHERE net_profit IS NULL") null_profits = cursor.fetchone()[0] # Count invalid cursor.execute("SELECT COUNT(*) FROM trades WHERE status = 'invalid_historical'") invalid = cursor.fetchone()[0] print(f"Historical Trades: {historical}") print(f"NULL Profits: {null_profits}") print(f"Invalid Historical: {invalid}") # Performance cursor.execute(""" SELECT COUNT(*) as total, SUM(CASE WHEN net_profit > 0 THEN 1 ELSE 0 END) as wins, SUM(CASE WHEN net_profit < 0 THEN 1 ELSE 0 END) as losses, ROUND(SUM(net_profit), 2) as total_profit FROM trades WHERE net_profit IS NOT NULL """) total, wins, losses, profit = cursor.fetchone() win_rate = (wins / total * 100) if total > 0 else 0 print(f"\nGesamt Performance (nur valide Trades):") print(f" Total: {total}") print(f" Wins: {wins} ({win_rate:.1f}%)") print(f" Losses: {losses}") print(f" Total Profit: ${profit}") def main(): print("="*80) print("🗑️ HISTORICAL TRADES CLEANUP") print("="*80) # Backup backup_path = create_backup() # Connect conn = sqlite3.connect(DB_PATH) try: # Analyze total = analyze_historical_trades(conn) # Ask user print("\n" + "="*80) print("❓ AUSWAHL") print("="*80) print("\nWas soll mit den 240 historical Trades passieren?") print() print("1️⃣ LÖSCHEN - Alle historical trades permanent entfernen") print(" Pro: Saubere Datenbank") print(" Con: Daten unwiederbringlich weg") print() print("2️⃣ MARKIEREN - Als 'invalid_historical' markieren (behalten aber ausblenden)") print(" Pro: Daten bleiben erhalten") print(" Con: Nimmt Speicherplatz") print() print("3️⃣ BREAKEVEN - net_profit = 0 setzen (als Breakeven-Trades behandeln)") print(" Pro: Fließen in Statistik ein") print(" Con: Verfälscht Performance-Daten") print() print("4️⃣ ABBRECHEN - Nichts tun, Trades behalten wie sie sind") print() choice = input("Ihre Wahl (1-4): ").strip() if choice == "1": option_delete_historical(conn) elif choice == "2": option_mark_as_invalid(conn) elif choice == "3": option_set_zero_profit(conn) elif choice == "4": print("\n⏸️ Abgebrochen - Keine Änderungen") return else: print(f"\n❌ Ungültige Wahl: {choice}") return # Verify verify_cleanup(conn) print("\n" + "="*80) print("✅ CLEANUP ABGESCHLOSSEN") print("="*80) print(f"\nBackup: {backup_path}") except Exception as e: print(f"\n❌ ERROR: {e}") conn.rollback() # Restore backup print(f"Restore Backup: {backup_path}") shutil.copy(backup_path, DB_PATH) print("✅ Backup wiederhergestellt") finally: conn.close() if __name__ == "__main__": main()