# Trade Groups Feature - Implementierung

## Übersicht

Das Trade Groups Feature ermöglicht es, zusammengehörige Trades (z.B. Rollover-Ketten) für Auswertungen zu gruppieren. Jeder Trade erhält eine `trade_group_id`, die bei Rollovern automatisch weitergegeben wird.

## Implementierte Änderungen

### 1. Datenmodell (`models.py`)

Drei neue Felder in der `Trade` Tabelle:

```python
class Trade(Base):
    trade_group_id = Column(String, nullable=True)  # Gruppiert zusammengehörige Trades
    openDate = Column(TIMESTAMP, nullable=True)     # Wann wurde der Trade eröffnet
    closeDate = Column(TIMESTAMP, nullable=True)    # Wann wurde der Trade geschlossen
```

**Migration:** `a1b2c3d4e5f6_add_trade_group_and_dates.py`
- Wird automatisch beim nächsten OptraBot-Start durch `updateDatabase()` ausgeführt

### 2. TradeManager (`trademanager.py`)

#### openDate setzen beim Öffnen:
```python
# In _onOrderStatusChanged(), wenn Entry Order gefüllt wird:
managedTrade.trade.openDate = datetime.datetime.now(pytz.UTC)
```

#### closeDate setzen beim Schließen:
```python
# Neue Hilfsmethode _close_trade():
def _close_trade(self, managedTrade: ManagedTrade):
    managedTrade.status = 'CLOSED'
    managedTrade.trade.status = 'CLOSED'
    managedTrade.trade.closeDate = datetime.datetime.now(pytz.UTC)
    # ... DB update
```

Ersetzt 3 Stellen, wo Trades geschlossen werden:
- Take Profit Order gefüllt
- Stop Loss Order gefüllt
- Closing Order gefüllt

#### trade_group_id setzen beim Öffnen:
```python
# In openTrade():
if hasattr(template, 'trade_group_id') and template.trade_group_id:
    # Von Flow Engine via Template übergeben (Rollover)
    newTrade.trade_group_id = template.trade_group_id
else:
    # Neuer Standalone Trade - generiere neue Group ID
    newTrade.trade_group_id = str(uuid.uuid4())
```

### 3. Template (`templatefactory.py`)

Neues temporäres Feld für Flow Engine:

```python
class Template:
    def __init__(self, name: str) -> None:
        # ... existing fields
        self.trade_group_id = None  # Trade group ID (set by Flow Engine for rollovers)
```

### 4. Flow Engine Events (`flowevent.py`)

#### FlowEventData erweitert:
```python
@dataclass
class FlowEventData:
    # ... existing fields
    trade_group_id: Optional[str] = None  # Trade group ID for grouping related trades
    
    def get_variables(self) -> dict:
        return {
            # ... existing variables
            'EVENT_TRADE_GROUP_ID': self.trade_group_id,
        }
```

#### Event-Erzeugung im TradeManager:
```python
# Bei allen Exit-Events (early_exit, stop_loss_hit, take_profit_hit):
event_data = EarlyExitEventData(
    # ... existing fields
    trade_group_id=managed_trade.trade.trade_group_id,  # NEU
    # ...
)
```

### 5. Flow Engine Logik (`flowengine.py`)

Automatische Weitergabe der `trade_group_id`:

```python
# In _execute_process_template():
# Pass trade_group_id from triggering trade to new trade
if 'EVENT_TRADE_GROUP_ID' in variables and variables['EVENT_TRADE_GROUP_ID']:
    template_copy.trade_group_id = variables['EVENT_TRADE_GROUP_ID']
    logger.info(f'Propagating trade_group_id: {template_copy.trade_group_id}')
```

### 6. Alembic Environment (`alembic/env.py`)

Fix für Auto-Generation:

```python
from optrabot.database import Base
target_metadata = Base.metadata  # War vorher: None
```

## Verwendung

### Automatisches Verhalten

**Rollover-Kette (via Flow Engine):**
1. Trade 1 (0DTEIC100Income) wird eröffnet → erhält `trade_group_id = "abc-123-..."`
2. Trade 1 erreicht Early Exit → löst Flow aus
3. Flow erstellt Trade 2 (1DTEIC100Income) → erbt `trade_group_id = "abc-123-..."`
4. Trade 2 erreicht Early Exit → löst Flow aus
5. Flow erstellt Trade 3 (FINALIC100Income) → erbt `trade_group_id = "abc-123-..."`

**Standalone Trade:**
- Trade ohne Flow → erhält neue `trade_group_id = str(uuid.uuid4())`

### Auswertung

#### Alle Trades einer Gruppe:
```python
from optrabot.database import SessionLocal, get_db_engine
from optrabot.models import Trade
from sqlalchemy.orm import Session

def get_trade_group(trade_group_id: str):
    with Session(get_db_engine()) as session:
        return session.query(Trade)\
            .filter(Trade.trade_group_id == trade_group_id)\
            .order_by(Trade.openDate)\
            .all()
```

#### Gruppen-Statistiken:
```python
def get_group_statistics(trade_group_id: str):
    trades = get_trade_group(trade_group_id)
    
    if not trades:
        return None
    
    return {
        'trade_group_id': trade_group_id,
        'trade_count': len(trades),
        'total_pnl': sum(t.realizedPNL for t in trades),
        'first_opened': trades[0].openDate,
        'last_closed': trades[-1].closeDate,
        'total_duration': trades[-1].closeDate - trades[0].openDate,
        'trades': [
            {
                'trade_id': t.id,
                'strategy': t.strategy,
                'opened': t.openDate,
                'closed': t.closeDate,
                'duration': t.closeDate - t.openDate if t.closeDate else None,
                'pnl': t.realizedPNL
            }
            for t in trades
        ]
    }
```

#### Rollover-Historie:
```python
# Chronologische Abfolge der Trades in einer Gruppe
trades = get_trade_group("abc-123-...")

for i, trade in enumerate(trades, 1):
    print(f"Rollover {i}: {trade.strategy}")
    print(f"  Opened: {trade.openDate}")
    print(f"  Closed: {trade.closeDate}")
    print(f"  P&L: ${trade.realizedPNL}")
    print()
```

## Beispiel-Konfiguration

Keine Änderungen an `config.yaml` nötig! Die Flows funktionieren automatisch:

```yaml
flows:
  iic_rollover1:
    name: "1. Roll of 0DTE IC 100 Income to 1DTE IC 100 Income"
    enabled: true
    event:
      type: early_exit
      template: 0DTEIC100Income
    actions:
      - process_template:
          template: 1DTEIC100Income
          amount: $EVENT_TRADE_AMOUNT * 2
          premium: 0.65
          # trade_group_id wird automatisch weitergegeben!
```

## Datenbank-Migration

Die Migration wird automatisch beim nächsten OptraBot-Start ausgeführt:

```bash
# Logs zeigen:
2025-10-23 17:00:00.000 | DEBUG | optrabot.database:updateDatabase:25 - Enter updateDatabase()
2025-10-23 17:00:00.001 | INFO  | alembic.runtime.migration - Running upgrade cc3c6f4d83dc -> a1b2c3d4e5f6, Add trade_group_id, openDate and closeDate to trades table
```

Bei Bedarf manuell ausführen (aus dem `optrabot/` Unterverzeichnis):

```bash
cd optrabot
python -m alembic upgrade head
```

## Vorteile

1. **Automatische Gruppierung:** Keine manuelle Konfiguration nötig
2. **Rollover-Transparenz:** Vollständige Historie nachvollziehbar
3. **Flexible Auswertung:** SQL-Queries über trade_group_id
4. **Zeitbasierte Analyse:** openDate und closeDate für Duration-Berechnungen
5. **Abwärtskompatibel:** Bestehende Trades funktionieren weiter (nullable Felder)

## Technische Details

- **trade_group_id:** UUID v4 String (z.B. "550e8400-e29b-41d4-a716-446655440000")
- **openDate/closeDate:** UTC Timestamps (TIMESTAMP Spalte)
- **Weitergabe:** Automatisch via Flow Engine Variable `$EVENT_TRADE_GROUP_ID`
- **Standalone Trades:** Erhalten eigene trade_group_id (jeder Trade ist mindestens eine 1-Trade-Gruppe)

## Testing

Nach dem Update:
1. OptraBot starten → Migration läuft automatisch
2. Neuen Trade öffnen → openDate wird gesetzt, trade_group_id generiert
3. Rollover auslösen → trade_group_id wird weitergegeben
4. Trade schließen → closeDate wird gesetzt
5. Datenbank prüfen: `SELECT * FROM trades ORDER BY openDate DESC LIMIT 10;`
