# OptraBot Release Notes - v0.18.0a14

## Release Date: 30. Oktober 2025

## 🎯 Major Changes

### OTB-253: Per-Broker Trade Recovery
**Problem:** Trade Recovery wartete auf alle konfigurierten Broker. Wenn ein Broker nicht verbinden konnte, wurde Recovery für **keinen** Broker ausgeführt.

**Lösung:**
- ✅ **Unabhängige Broker-Recovery**: Jeder Broker führt Recovery nur für seine eigenen Accounts aus
- ✅ **Keine Abhängigkeiten**: Wenn ein Broker fehlt, laufen andere trotzdem
- ✅ **Expired Trades Settlement**: Läuft nur einmal beim ersten Broker (globale Operation)
- ✅ **Besseres Logging**: Zeigt genau welcher Broker welche Trades recovered

**Änderungen:**
- `brokerfactory.py`: Per-Broker Recovery statt globaler Recovery
- `traderecovery.py`: Neue `recover_for_broker(broker_id, account_ids)` Methode

**Erwartetes Verhalten:**
```
16:32:10 | TASTY connected → Recovery für TASTY Accounts
16:32:15 | IBTWS connected → Recovery für IBTWS Accounts
```

### OTB-236: Shutdown RecursionError Fix
**Problem:** Beim Shutdown (Ctrl+C) mit Tastytrade-Verbindung traten schwerwiegende Fehler auf:
- `RecursionError: maximum recursion depth exceeded` (494 Ebenen!)
- `RuntimeError: no running event loop`
- `RuntimeWarning: coroutine was never awaited`

**Root Cause:**
- `_on_streamer_disconnect()` Callback rief `_disconnect_internal()` auf
- `_disconnect_internal()` rief `streamer.close()` auf
- `streamer.close()` rief wieder `_on_streamer_disconnect()` auf
- → Infinite Recursion Loop!
- Zusätzlich: Tastytrade Library rief Callbacks nach Event Loop Shutdown auf

**Lösung:**
- ✅ **Event Loop Status Check**: Prüft ob Event Loop noch läuft
- ✅ **Kein rekursiver close()**: Callback ruft nicht mehr `_disconnect_internal()` auf
- ✅ **Manueller Cleanup**: Tasks werden direkt gecancelt, keine Library-Calls
- ✅ **Early Return**: Ignoriert Callbacks während aktivem Disconnect

**Änderungen:**
- `tastytradeconnector.py`: `_on_streamer_disconnect()` komplett überarbeitet

**Erwartetes Verhalten:**
```
02:27:41 | Disconnecting from broker TASTY
02:27:41 | Streamer disconnect callback triggered
02:27:41 | Already disconnecting, ignoring callback
02:27:42 | OptraBot shutdown completed
✅ Keine Exceptions mehr!
```

### OTB-253 Ergänzung: Symbol Data vor Recovery
**Problem:** Nach Änderung "Recovery vor requestTickerData()" trat KeyError auf:
- `prepareOrder()` benötigt `self._symbolData['SPX']`
- Diese Daten werden in `requestTickerData()` erstellt
- Wenn Recovery zuerst läuft: KeyError!

**Betroffen:** IBTWS und Tastytrade

**Lösung:**
1. **BrokerFactory**: Recovery läuft NACH `requestTickerData()` (Symbol-Daten vorhanden)
2. **Tastytrade-Optimierung**: Streaming-Subscriptions laufen im Background
   - Alte Implementierung: `await self._subscribe_data()` blockierte 2+ Sekunden
   - Neue Implementierung: `asyncio.create_task(self._start_streaming_async())` → non-blocking
   - Symbol-Daten sofort verfügbar, Streaming im Hintergrund

**Änderungen:**
- `brokerfactory.py`: `requestTickerData()` vor Recovery
- `tastytradeconnector.py`: Neue `_start_streaming_async()` Methode

**Performance-Verbesserung:**
- TASTY Recovery startet nach **160ms** statt 2360ms (2+ Sekunden schneller!)
- IBTWS unverändert schnell (~200ms)

## 🐛 Bug Fixes

- Fixed RecursionError during Tastytrade shutdown (OTB-236)
- Fixed RuntimeError "no running event loop" during shutdown (OTB-236)
- Fixed KeyError 'SPX' during trade recovery (OTB-253)
- Fixed broker recovery dependency issues (OTB-253)

## 📝 Documentation

- Added `OTB-236-fix-summary.md` - Detailed shutdown fix documentation with test plan
- Added `OTB-253-symbol-data-fix.md` - Symbol data loading optimization documentation

## 🔧 Technical Details

### Modified Files:
- `optrabot/broker/brokerfactory.py`
  - Per-broker recovery logic
  - Recovery after requestTickerData()
  - Removed global broker waiting logic

- `optrabot/broker/tastytradeconnector.py`
  - Fixed `_on_streamer_disconnect()` recursion
  - Added `_start_streaming_async()` for background streaming
  - Event loop status checks

- `optrabot/traderecovery.py`
  - New `recover_for_broker(broker_id, account_ids)` method
  - Per-broker trade filtering by account IDs
  - Improved logging

### Testing Recommendations:

**OTB-253:**
1. Test with single broker (IBTWS or TASTY)
2. Test with both brokers connected
3. Test with one broker failing to connect
4. Verify trade recovery logs show correct broker and accounts

**OTB-236:**
1. Start OptraBot with Tastytrade
2. Let it run for a few minutes
3. Press Ctrl+C to shutdown
4. Verify no RecursionError, RuntimeError, or warnings
5. Check clean shutdown sequence in logs

**OTB-253 Symbol Data:**
1. Verify no KeyError during recovery
2. Check TASTY recovery timing (should be < 200ms after connection)
3. Verify streaming starts in background
4. Check prepareOrder() works correctly during recovery

## ⚠️ Breaking Changes

None. All changes are backwards compatible.

## 🚀 Performance Improvements

- ✅ Tastytrade recovery **2+ seconds faster** (160ms vs 2360ms)
- ✅ Streaming subscriptions don't block recovery anymore
- ✅ Independent broker recovery reduces startup time

## 📊 Metrics

- Lines of code changed: ~200
- Files modified: 3
- New methods added: 2
- Bug fixes: 4
- Performance improvements: 2+s for TASTY recovery

## 🔗 Related Issues

- OTB-253: Trade Recovery Architecture
- OTB-236: Tastytrade Shutdown Errors
- OTB-254: EOD Settlement (not affected)
- OTB-256: TWS Version Check (not affected)

## 👥 Contributors

- Heiko Hänsel (QuantX GmbH)

---

**Full Changelog**: https://bitbucket.org/quantx/optrabot/compare/v0.18.0a14..v0.18.0a13
