all changes done over the last 2 weeks
This commit is contained in:
@@ -0,0 +1,365 @@
|
||||
#!/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
|
||||
)
|
||||
Reference in New Issue
Block a user