234 lines
6.4 KiB
Python
234 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
🔧 Fix Closed Positions - Manual Update
|
|
Aktualisiert geschlossene Positionen in der Datenbank mit Exit-Daten aus MT5
|
|
"""
|
|
|
|
import MetaTrader5 as mt
|
|
import sqlite3
|
|
from datetime import datetime, timedelta
|
|
|
|
print("=" * 60)
|
|
print("🔧 MANUAL FIX: Closed Positions Update")
|
|
print("=" * 60)
|
|
|
|
# ==========================================
|
|
# 1. CONNECT TO MT5
|
|
# ==========================================
|
|
|
|
print("\n1️⃣ Verbinde mit MT5...")
|
|
|
|
if not mt.initialize():
|
|
print(f"❌ MT5 Connection failed: {mt.last_error()}")
|
|
exit(1)
|
|
|
|
print("✅ MT5 verbunden")
|
|
|
|
# ==========================================
|
|
# 2. CONNECT TO DATABASE
|
|
# ==========================================
|
|
|
|
print("2️⃣ Verbinde mit Datenbank...")
|
|
|
|
conn = sqlite3.connect("trading_bot.db")
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
print("✅ Datenbank verbunden")
|
|
|
|
# ==========================================
|
|
# 3. FIND CLOSED POSITIONS
|
|
# ==========================================
|
|
|
|
print("\n3️⃣ Suche geschlossene Positionen...")
|
|
|
|
# Get all open trades from DB
|
|
cursor.execute("""
|
|
SELECT ticket, symbol, type, entry_price, sl_price, tp_price, entry_time
|
|
FROM trades
|
|
WHERE status = 'open'
|
|
""")
|
|
|
|
db_open_trades = cursor.fetchall()
|
|
|
|
# Get current MT5 positions
|
|
mt5_positions = mt.positions_get()
|
|
mt5_tickets = {pos.ticket for pos in mt5_positions} if mt5_positions else set()
|
|
|
|
# Find closed positions
|
|
closed_tickets = []
|
|
for trade in db_open_trades:
|
|
if trade['ticket'] not in mt5_tickets:
|
|
closed_tickets.append(trade)
|
|
|
|
print(f"✅ Gefunden: {len(closed_tickets)} geschlossene Positionen")
|
|
|
|
if not closed_tickets:
|
|
print("\n✅ Keine geschlossenen Positionen zu updaten!")
|
|
mt.shutdown()
|
|
conn.close()
|
|
exit(0)
|
|
|
|
# ==========================================
|
|
# 4. UPDATE EACH CLOSED POSITION
|
|
# ==========================================
|
|
|
|
print("\n4️⃣ Update geschlossene Positionen...")
|
|
|
|
now = datetime.now()
|
|
days_ago = now - timedelta(days=30)
|
|
|
|
updated_count = 0
|
|
failed_count = 0
|
|
|
|
for trade in closed_tickets:
|
|
ticket = trade['ticket']
|
|
print(f"\n Processing Ticket {ticket}...")
|
|
|
|
try:
|
|
# Get deals history with time range (last 30 days)
|
|
deals = mt.history_deals_get(days_ago, now, ticket=ticket)
|
|
|
|
if not deals:
|
|
print(f" ❌ No history found")
|
|
failed_count += 1
|
|
continue
|
|
|
|
# Find close deal (entry == 1)
|
|
close_deal = None
|
|
for deal in deals:
|
|
if deal.entry == 1: # Entry out = Close
|
|
close_deal = deal
|
|
break
|
|
|
|
if not close_deal:
|
|
print(f" ❌ No close deal found")
|
|
failed_count += 1
|
|
continue
|
|
|
|
# Calculate exit data
|
|
exit_price = close_deal.price
|
|
exit_time = datetime.fromtimestamp(close_deal.time)
|
|
profit = close_deal.profit
|
|
commission = close_deal.commission
|
|
swap = close_deal.swap
|
|
net_profit = profit + commission + swap
|
|
|
|
# Calculate duration
|
|
entry_time = datetime.strptime(trade['entry_time'], '%Y-%m-%d %H:%M:%S')
|
|
duration_hours = (exit_time - entry_time).total_seconds() / 3600
|
|
|
|
# Calculate RR ratio
|
|
rr_ratio = None
|
|
if trade['sl_price'] and trade['tp_price']:
|
|
risk = abs(trade['entry_price'] - trade['sl_price'])
|
|
reward = abs(trade['tp_price'] - trade['entry_price'])
|
|
if risk > 0:
|
|
rr_ratio = reward / risk
|
|
|
|
# Determine exit reason
|
|
exit_reason = "manual_close"
|
|
tolerance = 0.5
|
|
|
|
if trade['tp_price'] and trade['sl_price']:
|
|
if trade['type'] == "BUY":
|
|
if abs(exit_price - trade['tp_price']) <= tolerance:
|
|
exit_reason = "take_profit"
|
|
elif abs(exit_price - trade['sl_price']) <= tolerance:
|
|
exit_reason = "stop_loss"
|
|
else: # SELL
|
|
if abs(exit_price - trade['tp_price']) <= tolerance:
|
|
exit_reason = "take_profit"
|
|
elif abs(exit_price - trade['sl_price']) <= tolerance:
|
|
exit_reason = "stop_loss"
|
|
|
|
# Update database
|
|
cursor.execute("""
|
|
UPDATE trades
|
|
SET
|
|
exit_price = ?,
|
|
exit_time = ?,
|
|
duration_hours = ?,
|
|
profit = ?,
|
|
commission = ?,
|
|
swap = ?,
|
|
net_profit = ?,
|
|
rr_ratio = ?,
|
|
status = 'closed',
|
|
exit_reason = ?
|
|
WHERE ticket = ?
|
|
""", (
|
|
exit_price,
|
|
exit_time.strftime('%Y-%m-%d %H:%M:%S'),
|
|
duration_hours,
|
|
profit,
|
|
commission,
|
|
swap,
|
|
net_profit,
|
|
rr_ratio,
|
|
exit_reason,
|
|
ticket
|
|
))
|
|
|
|
conn.commit()
|
|
|
|
print(f" ✅ Updated successfully!")
|
|
print(f" Exit: {exit_price}")
|
|
print(f" Time: {exit_time}")
|
|
print(f" Profit: ${net_profit:.2f}")
|
|
print(f" Reason: {exit_reason}")
|
|
|
|
updated_count += 1
|
|
|
|
except Exception as e:
|
|
print(f" ❌ Error: {e}")
|
|
failed_count += 1
|
|
|
|
# ==========================================
|
|
# 5. SUMMARY
|
|
# ==========================================
|
|
|
|
print("\n" + "=" * 60)
|
|
print("📊 ZUSAMMENFASSUNG")
|
|
print("=" * 60)
|
|
|
|
print(f"\n✅ Erfolgreich updated: {updated_count}")
|
|
print(f"❌ Fehlgeschlagen: {failed_count}")
|
|
|
|
if updated_count > 0:
|
|
print("\n🎉 Datenbank wurde erfolgreich aktualisiert!")
|
|
print(" Dashboard zeigt jetzt Profit-Daten an.")
|
|
else:
|
|
print("\n⚠️ Keine Positionen konnten aktualisiert werden.")
|
|
print(" Prüfe MT5 History-Einstellungen.")
|
|
|
|
# ==========================================
|
|
# 6. VERIFY
|
|
# ==========================================
|
|
|
|
print("\n" + "=" * 60)
|
|
print("🔍 VERIFIZIERUNG")
|
|
print("=" * 60)
|
|
|
|
cursor.execute("""
|
|
SELECT
|
|
COUNT(*) as total,
|
|
SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) as closed,
|
|
SUM(CASE WHEN net_profit IS NOT NULL THEN 1 ELSE 0 END) as with_profit
|
|
FROM trades
|
|
WHERE status != 'historical'
|
|
""")
|
|
|
|
stats = cursor.fetchone()
|
|
print(f"\nLive Trades:")
|
|
print(f" Total: {stats['total']}")
|
|
print(f" Closed: {stats['closed']}")
|
|
print(f" Mit Profit: {stats['with_profit']}")
|
|
|
|
mt.shutdown()
|
|
conn.close()
|
|
|
|
print("\n" + "=" * 60)
|
|
print("✅ Fix abgeschlossen!")
|
|
print("=" * 60)
|