# PLAN_LEGACY_PAPER_BUY_LOG_LABELS **Status:** planned (backlog, awaits operator GO) **Priority:** P2 **Erstellt:** 2026-05-17 23:55 UTC **Quelle:** Operator-Screenshot 2026-05-17 23:44 UTC — Trading-Log zeigt im selben Zeitfenster „PAPER BUY T1 [OPPORTUNISTIC]: XAUT/USDT" **und** „TESTNET BUY: 11164.0 BABY/USDT" **Roadmap-ID:** LEGACY-PAPER-BUY-LOG-LABELS **Voraussetzung:** Monitoring-Fenster abgeschlossen; bundle-fähig mit anderen Bot-Touches. --- ## 1. Bug-Beschreibung Im laufenden Bot tauchen im `bot_stdout.log` (Dashboard „Trading Log (Live)") nebeneinander zwei verschiedene Buy-Labels auf: ``` 23:44:51 main | INFO | 📈 PAPER BUY T1 [OPPORTUNISTIC]: XAUT/USDT @ 4536.31 | 211.12 USDT (40%) 23:44:52 execution.live_trade | INFO | 📈 TESTNET BUY: 11164.0 BABY/USDT @ 0.018900 USDT (Cost: 211.00 + Fee: 0.2110) position_id=pos_... ``` Operator-Verwirrung berechtigt: das **klingt** als würde der Bot teils papertraden und teils live testnet traden. Tatsächlich tradet er **immer** Binance Testnet (LiveTrader, BINANCE_TESTNET=true) — das ist seit Phase L (`EXEC-MODE-LABEL-1` 2026-05-10) der Default und seit Phase L+2 (`EXEC-MODE-LABEL-2` 2026-05-16 `a58f9a1`) auch in DB-Telemetrie korrekt mit `mode='testnet'` gelabelt. Was übrig blieb: **die plain `logger.info(...)`-Strings** in `main.py` und `paper_trade.py` tragen noch das alte „PAPER"-Wording aus der Paper-Trading-Ära des Bots. ## 2. Code-Inventar (verifiziert) ### 2.1 Aktive Paper-Strings (main.py — werden bei jedem Buy gefeuert) | Zeile | Quelle | Log-String | |---|---|---| | `main.py:931` | Scanner approved-BUY | `f" 📈 PAPER BUY T1 [{sized['tier']}]: {symbol} ..."` | | `main.py:1078` | Web-Scraper Channel | `f" 📈 PAPER BUY T1 (Web Signal) [{sized['tier']}]: ..."` | | `main.py:1201` | Telegram-Bot Channel | `f" 📈 PAPER BUY T1 (Bot Signal) [{sized['tier']}]: ..."` | | `main.py:515` | Fear & Greed Bias-Label | `fg_label = 'Extreme Fear -> PAPER TEST (Threshold 6.0)'` | | `main.py:517` | Fear & Greed Bias-Label | `fg_label = 'Fear -> PAPER TEST (Threshold 6.0)'` | ### 2.2 Dormante Paper-Strings (paper_trade.py — wird heute nicht ausgeführt weil LiveTrader aktiv) | Zeile | Quelle | Log-String | |---|---|---| | `paper_trade.py:512` | execute_buy (DCA-Pfad) | `f"📈 PAPER DCA/PYRAMID: ..."` | | `paper_trade.py:546` | execute_buy (First-Buy) | `f"📈 PAPER BUY: ..."` | | `paper_trade.py:684` | execute_sell | `f"{emoji} PAPER SELL: ..."` | ### 2.3 Wahre Anzeige (live_trade.py — was tatsächlich passiert) | Zeile | Quelle | Log-String | |---|---|---| | `live_trade.py:622` | execute_buy (DCA) | `f"📈 {self._label} DCA/PYRAMID: ..."` | | `live_trade.py:650` | execute_buy (First-Buy) | `f"📈 {self._label} BUY: ..."` | `self._label` ist beim LiveTrader-Init dynamisch: - `"TESTNET"` wenn `BINANCE_TESTNET=true` - `"LIVE"` wenn auf Mainnet (derzeit verboten) ## 3. Warum entstand die Inkonsistenz * `paper_trade.py` und `main.py` wurden in der Paper-Trading-Ära geschrieben — alle Log-Strings waren „PAPER ..." * Phase L (2026-05-10) führte LiveTrader für Binance Testnet ein → `live_trade.py:650` bekam das dynamische `self._label` * Die übergeordneten Wrapper-Logs in `main.py` wurden **nicht mitgezogen** * `EXEC-MODE-LABEL-2` (2026-05-16) hat die `mode`-Spalte in DB-Emits gefixt — aber `logger.info`-Strings sind nicht in DB-Emits enthalten, daher unangetastet geblieben ## 4. Fix-Strategie ### 4.1 Konsistenz mit `_G61_MODE` `main.py` definiert seit Phase L (line 55): ```python _G61_MODE = "testnet" if _G61_TESTNET else "live" ``` → Buy-Logs in `main.py` benutzen denselben Mode-String wie die DB: ```python # main.py:931 (Scanner) logger.info(f" 📈 {_G61_MODE.upper()} BUY T1 [{sized['tier']}]: ...") # main.py:1078 (Web) logger.info(f" 📈 {_G61_MODE.upper()} BUY T1 (Web Signal) [...]: ...") # main.py:1201 (Telegram) logger.info(f" 📈 {_G61_MODE.upper()} BUY T1 (Bot Signal) [...]: ...") ``` Ergebnis im Log: ``` 📈 TESTNET BUY T1 [OPPORTUNISTIC]: XAUT/USDT @ 4536.31 ``` → matched mit `live_trade.py:650` Format „📈 TESTNET BUY: ..." — Operator sieht **eine** Sprache. ### 4.2 Fear & Greed Labels (main.py:515, 517) Operator-facing Bias-String. Plan v3.4 ist Testnet-Mode. „PAPER TEST" ist kein technisch falsches Label (Testnet-Trading ist semantisch Paper-Trading mit echtem Routing), aber inkonsistent. Vorschlag: ```python # main.py:515 fg_label = 'Extreme Fear -> TESTNET BIAS (Threshold 6.0)' # main.py:517 fg_label = 'Fear -> TESTNET BIAS (Threshold 6.0)' ``` Oder `_G61_MODE.upper()`-basiert analog 4.1. ### 4.3 Dormante paper_trade.py-Strings (512, 546, 684) Da `paper_trade.PaperTrader` heute nicht aktiv ausgeführt wird (LiveTrader hat das Routing), sind diese Strings nicht sichtbar. Trotzdem aufräumen für Forensik / falls künftig wieder benutzt: - Replace `"PAPER BUY"` → `f"{self._label_for_log()} BUY"` mit Default „PAPER" wenn Klasse PaperTrader (Real-Paper) ist und „TESTNET" für LiveTrader-Subclass (LiveTrader erbt von PaperTrader laut Memory) Oder einfacher: in `paper_trade.py` lassen wie es ist, Kommentar drüber dass die Strings nur sichtbar werden wenn der Code-Pfad reaktiviert wird. **Empfehlung Phase 1 Scope**: Nur die 3 + 2 main.py-Strings fixen. paper_trade.py separat in Phase 2 wenn der Code-Pfad reaktiviert wird. ## 5. Scope (Phase 1, minimaler Diff) | Datei | Change | |---|---| | `trading/main.py:931` | `"PAPER BUY T1"` → `f"{_G61_MODE.upper()} BUY T1"` | | `trading/main.py:1078` | analog | | `trading/main.py:1201` | analog | | `trading/main.py:515` | `'Extreme Fear -> PAPER TEST'` → `f'Extreme Fear -> {_G61_MODE.upper()} BIAS'` oder konstant `"TESTNET BIAS"` | | `trading/main.py:517` | analog | **Diff < 10 Zeilen**. Pure Display-Strings, kein Trading-Logic-Touch. ## 6. Boundaries * **Bot-Touch ja** (Cutover SOT-1d) * 0× Trading-Logik * 0× State-Touch * 0× DB-Migration * 0× Strategieparameter * 0× Mainnet * 0× CommandBus-v6 * 0× Worker-Recreate * 0× Push ohne GO ## 7. Bundle-Empfehlung LEGACY-PAPER-BUY-LOG-LABELS hat sehr kleinen Code-Footprint und ist Display-only. **Sinnvoll bündeln mit anderen Bot-Touches**: ``` Bundle-Cutover Bot-Touch (nach 12h-Monitor): 1. EXTERNAL-CHANNEL-CAP-ALIGN P1 (regime_cap durchschleifen) 2. SNAPSHOT-EMIT-COMPLETENESS P2 (decision_id/opened_at) 3. LEGACY-PAPER-BUY-LOG-LABELS P2 (Wording-Korrektur) → ein Build, ein Recreate, ~30s Downtime ``` ## 8. Cutover-Plan (SOT-1d, bundle-Version) 1. Pre-cutover snapshot (HEAD, container PID, env-flags). 2. Watchdog freeze `CUTOVER_FREEZE_BUNDLE_POST_MONITOR`. 3. `docker compose build clawbot`. 4. Container-Test im neuen Image: alle bundle-Tests grün. 5. `docker compose up -d --force-recreate --no-deps clawbot`. 6. 3-Way MD5 OK für alle bundle-Files. 7. Bot spawn + healthcheck + 0 Tracebacks. 8. Live-Verify (Container): nächster Buy emittiert `TESTNET BUY T1 ...`, kein `PAPER BUY` mehr im stdout. 9. Watchdog re-enable. 10. Roadmap-Update LEGACY-PAPER-BUY-LOG-LABELS → done. ## 9. Tests `trading/tests/test_legacy_paper_buy_log_labels.py` (neu): * AST-Guard: `main.py` enthält **kein** `"PAPER BUY"` Literal außerhalb von Kommentaren oder dem unreachable archive-block. * AST-Guard: `main.py` enthält **kein** `'PAPER TEST'` in fg_label-Strings. * Smoke: bei `_G61_MODE = "testnet"` produziert der Mode-String „TESTNET" (nicht „PAPER"). * Regression: `paper_trade.py` strings dürfen für Phase 1 unverändert bleiben (separate Doku-Kommentar). ## 10. Acceptance Criteria - Operator sieht im Bot-Log **eine** konsistente Sprache: alle Buy/Sell-Wrapper-Strings zeigen denselben Mode wie der Trader-Layer (`TESTNET BUY` everywhere). - Fear & Greed Labels zeigen ebenfalls den aktuellen Mode oder neutrales Wording. - `paper_trade.py` Strings bleiben dormant aber dokumentiert. - 0 Bot-Verhaltensänderung — kein Trade-Logic-Touch. ## 11. Risk | Risiko | Severity | Mitigation | |---|---|---| | Reporter/Notifier liest "PAPER BUY" als Trigger | niedrig | Reporter-Code-Suche nach String-Trigger (kein bekannter Konsument) | | Telegram-Nachrichten-Templates haben „PAPER" hardcoded | niedrig | `reporter.py` durchsuchen, separat fixen falls Treffer | | Operator-Filter / -Searches auf „PAPER BUY" | niedrig | Operator-Hinweis im Closure: Suche jetzt auf „TESTNET BUY" umstellen | | Test bricht ältere Snapshot-Logs | niedrig | AST-Guard scope-limitiert auf reachable code paths | ## 12. STOP Kein Code vor: - Monitoring-Fenster abgeschlossen - Operator-`GO LEGACY-PAPER-BUY-LOG-LABELS` (bevorzugt als Bundle-GO) Bis dahin: - Bot-Log bleibt mit der „PAPER BUY" / „TESTNET BUY" Doppelsprache - Operator weiß jetzt dass beide derselbe Trade sind — der untere live_trade-Log ist der Beleg, der obere main-Log der Wrapper mit Legacy-Wording - Keine Verhaltensänderung erforderlich für Daten-Integrität (PnL/SL/State sind alle korrekt aus dem live_trade-Pfad)