# OTB-254: EXPIRED Trades PNL Correction & Settings Table

## Problem

1. **EXPIRED Trades:** PNL war 0.0 trotz Transaktionen
2. **PNL Berechnung Bug:** Hardcodierter Multiplier von 100 (funktionierte nur für SPX)
3. **OPEN Trades Bug:** realizedPNL zeigte Werte für offene Positionen (semantisch falsch)

## Lösung

### 1. Settings-Tabelle für Key-Value Storage

Neue Tabelle `settings` für:
- One-time Migration Flags (z.B. `pnl_correction_expired_trades_done`)
- UI-Einstellungen (z.B. `ui_theme`, `ui_language`)
- Feature Flags (z.B. `feature_x_enabled`)
- System State (z.B. `last_maintenance_date`)

**Schema:**
```sql
CREATE TABLE settings (
    key VARCHAR PRIMARY KEY,
    value VARCHAR NULL,
    description VARCHAR NULL,
    updated_at TIMESTAMP NULL
);
```

**CRUD-Funktionen in `optrabot/crud.py`:**
- `get_setting(session, key)` - Setting-Objekt abrufen
- `get_setting_value(session, key, default)` - Nur Wert abrufen
- `set_setting(session, key, value, description)` - Setting erstellen/aktualisieren
- `delete_setting(session, key)` - Setting löschen

### 2. Fix für TradeHelper.updateTrade()

**Datei:** `optrabot/tradehelper.py`

**Änderungen:**

1. **Multiplier von Symbol holen:**
```python
from optrabot import symbolinfo

multiplier = 100  # Default
if trade.symbol in symbolinfo.symbol_infos:
    multiplier = symbolinfo.symbol_infos[trade.symbol].multiplier
```

2. **Korrekte PNL-Logik:**
```python
# Für geschlossene Legs (openContracts == 0):
statusData.realPNL = statusData.unrealPNL  # Volle PNL realisiert
trade.realizedPNL += statusData.realPNL

# Für offene Legs (openContracts != 0):
statusData.realPNL = -statusData.fees  # Nur Fees als Kosten
# NICHT zu trade.realizedPNL addieren - offene Positionen zählen nicht!
```

**Semantik:**
- **realizedPNL** = Nur geschlossene Positionen
- **OPEN Trades** mit allen offenen Legs: realizedPNL = 0
- **CLOSED Trades**: realizedPNL = tatsächlicher P&L aller Legs

### 3. Fix für EOD Settlement

**Datei:** `optrabot/trademanager.py`

In `performEODSettlement()` wird jetzt `TradeHelper.updateTrade()` aufgerufen **bevor** der Status auf `EXPIRED` gesetzt wird:

```python
# Update PNL based on transactions before setting status to EXPIRED
TradeHelper.updateTrade(managedTrade.trade)

managedTrade.status = 'EXPIRED'
managedTrade.trade.status = 'EXPIRED'
```

### 3. Fix für EOD Settlement

**Datei:** `optrabot/trademanager.py`

In `performEODSettlement()` wird jetzt `TradeHelper.updateTrade()` aufgerufen **bevor** der Status auf `EXPIRED` gesetzt wird:

```python
# Update PNL based on transactions before setting status to EXPIRED
TradeHelper.updateTrade(managedTrade.trade)

managedTrade.status = 'EXPIRED'
managedTrade.trade.status = 'EXPIRED'
```

### 4. Einmalige Datenkorrektur

**Datei:** `optrabot/database.py`

Zwei Korrekturen werden ausgeführt:

1. **pnl_correction_expired_trades_done**: Korrigiert EXPIRED Trades
2. **pnl_correction_multiplier_fix_done**: Korrigiert ALLE Trades (Multiplier + PNL-Logik)

**Beispiel:**
- Trade 911 (OPEN, alle Legs offen): `-$6.37` (nur Fees) → `$0.00` ✅
- Trade 906 (CLOSED, alle Legs geschlossen): `-$37.57` → `-$37.57` ✅ (keine Änderung nötig)

Bei OptraBot-Start am 24.10.2025: **265 Trades korrigiert**

### 5. Alembic Migration

**Datei:** `optrabot/alembic/versions/fca33d484976_add_settings_table_for_key_value_storage.py`

Migration erstellt die `settings` Tabelle:
- `upgrade()`: CREATE TABLE settings
- `downgrade()`: DROP TABLE settings

**Revisions:**
- Revision ID: `fca33d484976`
- Revises: `a1b2c3d4e5f6` (Trade Groups Migration)

## Testablauf

### Test-Script: `test_pnl_correction.py`

1. Erstellt Test-Trade mit Status=EXPIRED und realizedPNL=0.0
2. Fügt Transaktionen hinzu (Sell $100, Expire worthless)
3. Ruft `updateDatabase()` auf
4. Verifiziert: PNL wurde auf $99.35 korrigiert
5. Cleanup: Löscht Test-Trade und Flag

**Ergebnis:** ✅ PNL correction successful!

### Manueller Test

```python
from optrabot.database import SessionLocal
from optrabot import crud

with SessionLocal() as session:
    # Flag prüfen
    flag = crud.get_setting(session, 'pnl_correction_expired_trades_done')
    print(f'Flag: {flag.key} = {flag.value}')
    print(f'Description: {flag.description}')
    
    # Flag löschen (für erneuten Test)
    crud.delete_setting(session, 'pnl_correction_expired_trades_done')
```

## Verwendung der Settings-Tabelle

### Beispiele

```python
from optrabot.database import SessionLocal
from optrabot import crud

with SessionLocal() as session:
    # Setting setzen
    crud.set_setting(session, 'ui_theme', 'dark', 'User interface theme')
    
    # Setting abrufen
    theme = crud.get_setting_value(session, 'ui_theme', default='light')
    
    # Setting prüfen (Boolean)
    feature_enabled = crud.get_setting_value(session, 'feature_x', default='false') == 'true'
    
    # Setting löschen
    crud.delete_setting(session, 'old_setting')
```

### Empfohlene Konventionen

**One-time Flags:**
- Format: `<action>_done` (z.B. `pnl_correction_expired_trades_done`)
- Value: `'true'` wenn durchgeführt
- Description: Details zur Ausführung (Zeitstempel, Anzahl korrigiert, etc.)

**Feature Flags:**
- Format: `feature_<name>_enabled`
- Value: `'true'` oder `'false'`

**UI Settings:**
- Format: `ui_<component>_<setting>`
- Value: String-Wert (z.B. `'dark'`, `'en'`, `'large'`)

**System State:**
- Format: `system_<state>` oder `last_<action>`
- Value: String (oft ISO-Timestamp)

## Deployment

### Automatischer Ablauf

1. OptraBot startet
2. `updateDatabase()` wird aufgerufen
3. Alembic führt Migration aus → `settings` Tabelle wird erstellt
4. `_run_data_corrections()` wird aufgerufen
5. PNL-Korrektur läuft für alle EXPIRED Trades
6. Flag wird gesetzt
7. Bei allen zukünftigen Starts: Korrektur wird übersprungen

### Manuelle Alembic-Befehle

```bash
# Status prüfen
poetry run alembic current

# Migration ausführen
poetry run alembic upgrade head

# Migration rückgängig machen
poetry run alembic downgrade -1
```

## Geänderte Dateien

1. ✅ `optrabot/models.py` - Setting Model hinzugefügt
2. ✅ `optrabot/crud.py` - CRUD-Funktionen für Settings
3. ✅ `optrabot/database.py` - Datenkorrektur-Logik
4. ✅ `optrabot/trademanager.py` - EOD Settlement Fix
5. ✅ `optrabot/alembic/versions/fca33d484976_add_settings_table_for_key_value_storage.py` - Migration
6. ✅ `test_pnl_correction.py` - Testskript (nicht für Produktion)

## Vorteile

✅ **Problem behoben:** Zukünftige EXPIRED Trades haben korrekte PNL
✅ **Bestehende Daten korrigiert:** Alle EXPIRED Trades in DB werden automatisch korrigiert
✅ **Einmaligkeit garantiert:** Flag-System verhindert Doppelausführung
✅ **Wiederverwendbar:** Settings-Tabelle für zukünftige Features nutzbar
✅ **Sauber getestet:** Testskript validiert Funktion
✅ **Production-ready:** Automatisch beim nächsten Start

## Zukünftige Erweiterungen

Die Settings-Tabelle kann erweitert werden für:
- User Preferences im UI
- Feature Flags für A/B Testing
- System Konfiguration ohne Code-Änderung
- Maintenance Windows
- Rate Limiting Parameter
- etc.
