322 lines
7.4 KiB
Markdown
322 lines
7.4 KiB
Markdown
# 📊 Position Monitor - Exit Tracking Guide
|
|||
|
|
|
||
|
|
## Was macht der Position Monitor?
|
||
|
|
|
||
|
|
Der Position Monitor überwacht alle offenen Positionen in der Datenbank und erkennt automatisch, wenn sie geschlossen werden (via Stop Loss, Take Profit oder manuell).
|
||
|
|
|
||
|
|
**Problem gelöst:** Trades werden per SL/TP geschlossen, aber der Bot weiß nichts davon → kein Profit im Dashboard
|
||
|
|
|
||
|
|
**Lösung:** Position Monitor prüft jede Minute, ob Positionen noch offen sind und aktualisiert die Datenbank mit Exit-Daten.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔧 Installation (BEREITS ERLEDIGT!)
|
||
|
|
|
||
|
|
Die Integration wurde automatisch vorgenommen:
|
||
|
|
|
||
|
|
### ✅ Neue Cell nach Infrastructure Setup:
|
||
|
|
```python
|
||
|
|
from position_monitor import PositionMonitor
|
||
|
|
|
||
|
|
# Create Position Monitor
|
||
|
|
position_monitor = PositionMonitor(infra.db, infra.telegram)
|
||
|
|
```
|
||
|
|
|
||
|
|
### ✅ Scheduler Job hinzugefügt:
|
||
|
|
```python
|
||
|
|
scheduler.add_job(
|
||
|
|
func=position_monitor.check_open_positions,
|
||
|
|
trigger='interval',
|
||
|
|
minutes=1,
|
||
|
|
id='position_monitor'
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🚀 Aktivierung
|
||
|
|
|
||
|
|
### Schritt 1: Notebook neu starten
|
||
|
|
```
|
||
|
|
Jupyter Menu: Kernel → Restart & Run All
|
||
|
|
```
|
||
|
|
|
||
|
|
### Schritt 2: Verifizieren
|
||
|
|
Führe in einer Notebook-Cell aus:
|
||
|
|
```python
|
||
|
|
scheduler.get_jobs()
|
||
|
|
```
|
||
|
|
|
||
|
|
**Erwartete Ausgabe:**
|
||
|
|
```
|
||
|
|
[
|
||
|
|
<Job (id=adaptive_trading_check ...)>,
|
||
|
|
<Job (id=status_report ...)>,
|
||
|
|
<Job (id=daily_report ...)>,
|
||
|
|
<Job (id=weekly_report ...)>,
|
||
|
|
<Job (id=position_monitor ...)> # ← Dieser muss da sein!
|
||
|
|
]
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 Was wird beim Exit geloggt?
|
||
|
|
|
||
|
|
Wenn ein Trade geschlossen wird, erfasst der Monitor automatisch:
|
||
|
|
|
||
|
|
### Exit-Daten:
|
||
|
|
- **exit_price** - Schlusskurs
|
||
|
|
- **exit_time** - Zeitpunkt des Exits
|
||
|
|
- **duration_hours** - Trade-Dauer in Stunden
|
||
|
|
- **profit** - Bruttogewinn/-verlust
|
||
|
|
- **commission** - Gebühren
|
||
|
|
- **swap** - Swap-Kosten
|
||
|
|
- **net_profit** - Nettogewinn (profit + commission + swap)
|
||
|
|
- **exit_reason** - Grund: "take_profit", "stop_loss", oder "manual_close"
|
||
|
|
- **rr_ratio** - Risk/Reward Ratio (falls SL/TP bekannt)
|
||
|
|
- **status** - Wird auf "closed" gesetzt
|
||
|
|
|
||
|
|
### Telegram Notification:
|
||
|
|
```
|
||
|
|
🔴 Trade Closed
|
||
|
|
|
||
|
|
Symbol: XAUUSD
|
||
|
|
Type: BUY
|
||
|
|
Entry: 2645.50
|
||
|
|
Exit: 2650.25
|
||
|
|
Exit Reason: TAKE_PROFIT
|
||
|
|
Net Profit: +$12.50
|
||
|
|
Duration: 2.5 hours
|
||
|
|
Session: NY
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 Wie funktioniert die Erkennung?
|
||
|
|
|
||
|
|
```python
|
||
|
|
def check_open_positions(self):
|
||
|
|
# 1. Hole alle offenen Trades aus DB
|
||
|
|
open_trades = self.db.get_open_trades()
|
||
|
|
|
||
|
|
# 2. Hole aktuelle Positionen von MT5
|
||
|
|
mt5_positions = mt.positions_get()
|
||
|
|
mt5_tickets = {pos.ticket for pos in mt5_positions}
|
||
|
|
|
||
|
|
# 3. Vergleiche
|
||
|
|
for trade in open_trades:
|
||
|
|
if trade['ticket'] not in mt5_tickets:
|
||
|
|
# Position geschlossen → Update DB
|
||
|
|
self._handle_closed_position(ticket, trade)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Exit-Grund Bestimmung:
|
||
|
|
|
||
|
|
```python
|
||
|
|
def _determine_exit_reason(exit_price, sl_price, tp_price, trade_type):
|
||
|
|
tolerance = 0.5 # Pips Toleranz
|
||
|
|
|
||
|
|
if trade_type == "BUY":
|
||
|
|
if abs(exit_price - tp_price) <= tolerance:
|
||
|
|
return "take_profit"
|
||
|
|
elif abs(exit_price - sl_price) <= tolerance:
|
||
|
|
return "stop_loss"
|
||
|
|
|
||
|
|
return "manual_close"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🧪 Testing
|
||
|
|
|
||
|
|
### Test 1: Manuell testen (optional)
|
||
|
|
```python
|
||
|
|
# In Notebook Cell:
|
||
|
|
position_monitor.check_open_positions()
|
||
|
|
```
|
||
|
|
|
||
|
|
**Ausgabe wenn keine geschlossenen Positionen:**
|
||
|
|
```
|
||
|
|
(Keine Ausgabe, alles OK)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Ausgabe wenn Position geschlossen wurde:**
|
||
|
|
```
|
||
|
|
✅ Updated closed position 12345: take_profit, Profit: 12.50
|
||
|
|
```
|
||
|
|
|
||
|
|
### Test 2: Live Test
|
||
|
|
1. Öffne einen Trade manuell in MT5
|
||
|
|
2. Schließe ihn nach 1-2 Minuten via TP/SL
|
||
|
|
3. Warte 1 Minute (nächster Monitor-Check)
|
||
|
|
4. Prüfe Dashboard → Profit sollte sichtbar sein
|
||
|
|
5. Prüfe Telegram → Exit-Notification sollte kommen
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📈 Dashboard Integration
|
||
|
|
|
||
|
|
### Vor Position Monitor:
|
||
|
|
```sql
|
||
|
|
SELECT * FROM trades WHERE status = 'open';
|
||
|
|
-- Alle Trades zeigen status='open', auch geschlossene
|
||
|
|
-- net_profit = NULL für alle
|
||
|
|
```
|
||
|
|
|
||
|
|
### Nach Position Monitor:
|
||
|
|
```sql
|
||
|
|
SELECT * FROM trades WHERE status = 'closed';
|
||
|
|
-- Geschlossene Trades haben:
|
||
|
|
-- • status = 'closed'
|
||
|
|
-- • exit_price, exit_time
|
||
|
|
-- • net_profit berechnet
|
||
|
|
-- • exit_reason bekannt
|
||
|
|
```
|
||
|
|
|
||
|
|
### Dashboard Queries profitieren:
|
||
|
|
```python
|
||
|
|
# Profit-Berechnung funktioniert jetzt:
|
||
|
|
cursor.execute("""
|
||
|
|
SELECT
|
||
|
|
SUM(net_profit) as total_profit,
|
||
|
|
COUNT(*) as trade_count,
|
||
|
|
AVG(net_profit) as avg_profit
|
||
|
|
FROM trades
|
||
|
|
WHERE status = 'closed'
|
||
|
|
""")
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔍 Troubleshooting
|
||
|
|
|
||
|
|
### Problem 1: Job läuft nicht
|
||
|
|
**Check:**
|
||
|
|
```python
|
||
|
|
scheduler.get_jobs()
|
||
|
|
# Ist 'position_monitor' in der Liste?
|
||
|
|
```
|
||
|
|
|
||
|
|
**Lösung:**
|
||
|
|
```python
|
||
|
|
# Manuell hinzufügen:
|
||
|
|
from position_monitor import PositionMonitor
|
||
|
|
position_monitor = PositionMonitor(infra.db, infra.telegram)
|
||
|
|
|
||
|
|
scheduler.add_job(
|
||
|
|
func=position_monitor.check_open_positions,
|
||
|
|
trigger='interval',
|
||
|
|
minutes=1,
|
||
|
|
id='position_monitor'
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Problem 2: Keine Updates in DB
|
||
|
|
**Check:**
|
||
|
|
```python
|
||
|
|
# Prüfe ob position_monitor existiert:
|
||
|
|
print(position_monitor)
|
||
|
|
|
||
|
|
# Teste manuell:
|
||
|
|
position_monitor.check_open_positions()
|
||
|
|
```
|
||
|
|
|
||
|
|
**Check Logs:**
|
||
|
|
```python
|
||
|
|
# Schaue nach Fehlern im Logger
|
||
|
|
import logging
|
||
|
|
logging.basicConfig(level=logging.DEBUG)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Problem 3: Exit-Reason immer "manual_close"
|
||
|
|
**Ursache:** TP/SL Preise nicht genau getroffen (Slippage)
|
||
|
|
|
||
|
|
**Lösung:** Tolerance erhöhen in [position_monitor.py:140](position_monitor.py#L140)
|
||
|
|
```python
|
||
|
|
tolerance = 1.0 # War: 0.5 Pips
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 Monitoring
|
||
|
|
|
||
|
|
### Check Position Monitor Status:
|
||
|
|
```python
|
||
|
|
# In Notebook:
|
||
|
|
print("Position Monitor Status:")
|
||
|
|
print(f" Database: {position_monitor.db}")
|
||
|
|
print(f" Telegram: {position_monitor.telegram}")
|
||
|
|
|
||
|
|
# Offene Trades in DB:
|
||
|
|
open_trades = position_monitor.db.get_open_trades()
|
||
|
|
print(f" Open Trades: {len(open_trades)}")
|
||
|
|
|
||
|
|
# Aktuelle Positionen in MT5:
|
||
|
|
mt5_positions = mt.positions_get()
|
||
|
|
print(f" MT5 Positions: {len(mt5_positions) if mt5_positions else 0}")
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logs überwachen:
|
||
|
|
```python
|
||
|
|
# Logger auf DEBUG setzen für mehr Details:
|
||
|
|
import logging
|
||
|
|
logging.getLogger('position_monitor').setLevel(logging.DEBUG)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 Performance Impact
|
||
|
|
|
||
|
|
- **CPU:** Minimal (läuft nur 1x/Minute)
|
||
|
|
- **Memory:** Minimal (~10KB)
|
||
|
|
- **Network:** 1 MT5 API Call pro Minute
|
||
|
|
- **Database:** 1 SELECT + N UPDATEs (N = geschlossene Positionen)
|
||
|
|
|
||
|
|
**Empfehlung:** Position Monitor läuft problemlos 24/7
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 💡 Best Practices
|
||
|
|
|
||
|
|
### ✅ DO:
|
||
|
|
- Position Monitor immer aktiviert lassen
|
||
|
|
- Telegram Notifications eingeschaltet lassen
|
||
|
|
- Logs regelmäßig prüfen
|
||
|
|
|
||
|
|
### ❌ DON'T:
|
||
|
|
- Position Monitor während aktivem Trading stoppen
|
||
|
|
- Exit-Daten manuell in DB ändern (Monitoring überschreibt)
|
||
|
|
- Tolerance zu hoch setzen (falsche Exit-Reasons)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📝 Zusammenfassung
|
||
|
|
|
||
|
|
**Was hast du jetzt?**
|
||
|
|
✅ Automatische Exit-Erkennung
|
||
|
|
✅ Profit/Loss Tracking
|
||
|
|
✅ Exit-Grund Bestimmung (TP/SL/Manual)
|
||
|
|
✅ Telegram Notifications für Exits
|
||
|
|
✅ Dashboard zeigt vollständige Trade-Daten
|
||
|
|
✅ Historische Performance-Analyse möglich
|
||
|
|
|
||
|
|
**Nächste Schritte:**
|
||
|
|
1. Notebook neu starten: `Kernel → Restart & Run All`
|
||
|
|
2. Verifizieren: `scheduler.get_jobs()`
|
||
|
|
3. Ersten Trade öffnen und schließen (Test)
|
||
|
|
4. Dashboard prüfen → Profit sollte sichtbar sein
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔗 Verwandte Dateien
|
||
|
|
|
||
|
|
- [position_monitor.py](position_monitor.py) - Monitor Implementation
|
||
|
|
- [trading_database.py](trading_database.py) - Database Integration
|
||
|
|
- [telegram_notifier.py](telegram_notifier.py) - Notification System
|
||
|
|
- [infrastructure_patch.py](infrastructure_patch.py) - Infrastructure Setup
|
||
|
|
- [TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb](TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb) - Main Bot
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Status:** ✅ Vollständig integriert und einsatzbereit!
|