Modul-Audit: 5 Inkonsistenzen behoben + Secret-Luecke in .gitignore geschlossen

Systematische Pruefung aller Verdict-Module gegen die Regel "keine Aussage
-> Gewicht 0", dazu Config-, Frontend- und Level-Quellen.

(1) KI-COPILOT - der groesste Rest des Musters. Ein explizites "NEUTRAL"
zaehlte als echte Stimme mit Gewicht 1,0. Gemessen (verdict_votes, n=7.084):
das ist in 93,1 % der Faelle der Zustand (Elliott: 1,3 %) - also der
Normalzustand des Copiloten, kein abgewogenes Urteil. Damit hatte
ausgerechnet das Modul mit der schwaechsten Beleglage
(analyze_verdict_calibration.py: nicht robust praediktiv) den GROESSTEN
daempfenden Einfluss auf die Bias-Nadel.

(2) ELLIOTT analog: Gewicht nur bei gerichtetem Ziel.

Kumulierte Wirkung aller Gewichts-Fixes des Tages:
    Oe|bias|  0,370 -> 0,441 -> 0,569  (= 1,54x), betrifft 79,5 % der Zeilen
Live verifiziert: KI "NEUTRAL" -> Gewicht 0,00, bias 2,5/4,5 = 0,556
statt 2,5/5,5 = 0,455.

(3) STALE [zones] SPEISTEN DIE WELLEN-KONFIDENZ - entfernt. _sr_levels zog
beide Kanten jeder [zones]-Zone als S/R-Linien heran: 16 Kanten aus einem
~10 $ TIEFEREN Regime (72,90-77,00 bei Kurs 85,3). Aus dem Chart waren sie
am 14.07. schon entfernt worden, WEIL sie stale sind - in die Konfidenz
liefen sie weiter. Realer Audit-Fall: market.sr hatte gar keine
Widerstaende (M15-Cluster sind in frischen Trends oft leer) -> der
"naechste Widerstand" kam aus der fvg-Zone bei 88,00 (2,66 $ weg), der
echte lag bei 85,315 (0,03 $ weg). Der Abzug "dicht unter Widerstand"
(-12) greift nur innerhalb 0,5xATR und feuerte deshalb NIE.

(4) TOTE CONFIG entfernt: [trading] trail_timeframe (nirgends gelesen, Name
suggeriert faelschlich die Trailing-TF) und die komplette [setups]-Sektion
(11 Schluessel).

(5) raise StopIteration als Sprung in einem breiten except durch ein if
ersetzt - funktionierte, waere aber fragil sobald dort Logging dazukommt.

SICHERHEIT: beim Anlegen des Config-Backups fiel auf, dass .gitignore nur
"oil_widget_config.ini" abdeckt, NICHT "...ini.bak-<datum>". Das Backup lag
ungeschuetzt als untracked im Repo und enthaelt dieselben Live-Keys.
Muster ergaenzt. Gegenprobe: die .example-Datei enthaelt 10 secret-artige
Felder, davon 0 identisch mit der echten ini - alles Platzhalter.

Sauber geblieben: Frontend<->Backend (0 verwaiste Element-IDs), alle
uebrigen Verdict-Gewichte, alle anderen Config-Schluessel.

OFFEN (messpflichtig): die Wellen-Konfidenz aus _draw_levels speisen statt
aus dem Misch-Set - wuerde den -12-Abzug tatsaechlich ausloesen, also die
Konfidenz senken und das 55%-Gate verschieben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-07-31 15:26:15 +02:00
co-authored by Claude Opus 5
parent 23c68e8837
commit 367d70eb7a
3 changed files with 99 additions and 30 deletions
+5
View File
@@ -1,5 +1,10 @@
# ── SECRETS (NIEMALS committen) ───────────────────────────────────────────── # ── SECRETS (NIEMALS committen) ─────────────────────────────────────────────
oil_widget_config.ini oil_widget_config.ini
# ⚠ AUCH die Backups! `oil_widget_config.ini` allein deckt `…ini.bak-<datum>` NICHT
# ab — beim Modul-Audit 2026-07-31 lag ein solches Backup ungeschützt als untracked
# im Repo. Die Datei enthält dieselben Live-Keys/Token wie das Original.
oil_widget_config.ini.*
oil_widget_config.ini.bak*
API Key*.txt API Key*.txt
*.key *.key
.env .env
+35
View File
@@ -1385,7 +1385,42 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
`1.5 if vote != 0 else 0.0`; `others` filtert bereits auf `weight>0`, die `1.5 if vote != 0 else 0.0`; `others` filtert bereits auf `weight>0`, die
„x/y einig"-Zählung zieht mit. Live verifiziert: M30 „flach" → Gewicht 0,00, „x/y einig"-Zählung zieht mit. Live verifiziert: M30 „flach" → Gewicht 0,00,
bias 1,5/4,5 = **0,333** statt 1,5/6,0 = 0,250. REINE ANZEIGE. bias 1,5/4,5 = **0,333** statt 1,5/6,0 = 0,250. REINE ANZEIGE.
**MODUL-AUDIT 2026-07-31 (User: „überprüfe alle Module auf Inkonsistenzen"):**
systematisch alle Verdict-Module gegen die Regel „keine Aussage → Gewicht 0"
geprüft, dazu Config-, Frontend- und Level-Quellen. **5 Befunde, alle behoben:**
**(1) KI-Copilot — der größte Rest des Musters.** Ein explizites „NEUTRAL" zählte
als echte Stimme mit Gewicht 1,0. Gemessen (`verdict_votes`, n=7.084): das ist
**in 93,1 % der Fälle** der Zustand (Elliott: 1,3 %) — also der Normalzustand des
Copiloten, kein abgewogenes Urteil. Damit hatte ausgerechnet das Modul mit der
schwächsten Beleglage (`analyze_verdict_calibration.py`: nicht robust prädiktiv)
den GRÖSSTEN dämpfenden Einfluss. Jetzt `1.0 if av != 0 else 0.0`.
**(2) Elliott** analog: Gewicht nur bei gerichtetem Ziel (1,3 % der Zeilen).
**Kumulierte Wirkung aller Gewichts-Fixes des Tages: Ø|bias| 0,370 → 0,441 →
**0,569** (= 1,54×), betrifft 79,5 % der Zeilen.** Live verifiziert: KI „NEUTRAL"
→ Gewicht 0,00, bias 2,5/4,5 = **0,556** statt 2,5/5,5 = 0,455.
**(3) Stale `[zones]` speisten die Wellen-Konfidenz — entfernt.** `_sr_levels` zog
beide Kanten jeder `[zones]`-Zone als S/R-Linien heran: **16 Kanten aus einem ~10 $
TIEFEREN Regime** (72,9077,00 bei Kurs 85,3). Aus dem CHART waren sie am 14.07.
schon entfernt worden, WEIL sie stale sind — in die Konfidenz liefen sie weiter.
Realer Audit-Fall: `market.sr` hatte GAR KEINE Widerstände (M15-Cluster sind in
frischen Trends oft leer) → der „nächste Widerstand" kam aus der `fvg`-Zone bei
**88,00** (2,66 $ weg), der echte lag bei **85,315** (0,03 $ weg). Der Abzug „dicht
unter Widerstand" (12) greift nur innerhalb 0,5×ATR und feuerte deshalb **nie**.
Entfernen ist keine Strategieänderung, sondern das Streichen von Fremdregime-Daten;
`parse_zones` bleibt in `config.py`, die ini-Sektion bleibt (reaktivierbar).
**(4) Tote Config entfernt** (Backup `oil_widget_config.ini.bak-2026-07-31`):
`[trading] trail_timeframe = M1` (nirgends gelesen, Name suggeriert fälschlich, er
steuere die Trailing-TF) und die komplette **`[setups]`-Sektion** (11 Schlüssel,
vollständig tot).
**(5) `raise StopIteration`** als Sprung innerhalb eines breiten `except Exception`
(Trade-Marker-Export) durch ein `if` ersetzt — funktionierte, wäre aber fragil,
sobald dort jemand Logging ergänzt (Phantom-Fehler im ~5-s-Takt).
**Sauber:** Frontend↔Backend (0 verwaiste Element-IDs), alle übrigen
Verdict-Gewichte, alle anderen Config-Schlüssel.
**Offen (dokumentiert, nicht geändert):** **Offen (dokumentiert, nicht geändert):**
(0) **Wellen-Konfidenz aus `_draw_levels` speisen** statt aus dem Misch-Set — würde
den 12-Abzug tatsächlich auslösen, also Konfidenz senken und das 55%-Gate
verschieben. **Strategieänderung → messpflichtig.**
(a) **Drei divergierende Level-Quellen** seit der (a) **Drei divergierende Level-Quellen** seit der
M30-Umstellung: `_draw_levels` (M30 → Chart/S/R-Close), `pb_levels` (M5 → Entry- M30-Umstellung: `_draw_levels` (M30 → Chart/S/R-Close), `pb_levels` (M5 → Entry-
Raum-Gate), `_sr_levels` (Misch-Set → Wellen-Konfidenz); real wichen die Supports Raum-Gate), `_sr_levels` (Misch-Set → Wellen-Konfidenz); real wichen die Supports
+44 -15
View File
@@ -22,8 +22,11 @@ import MetaTrader5 as mt5
from core.config import ( from core.config import (
HISTORY_DB_FILE, MAGIC, load_config, set_margin_buffer, set_risk_per_trade, HISTORY_DB_FILE, MAGIC, load_config, set_margin_buffer, set_risk_per_trade,
parse_zones,
) )
# ⚠ `parse_zones` wurde am 2026-07-31 hier entfernt (letzter Nutzer war `_sr_levels`,
# s. dort): die `[zones]`-Config stammte aus einem ~10 $ tieferen Kursregime und
# lieferte der Wellen-Konfidenz Phantom-Level. Die Funktion bleibt in `core/config.py`
# und die `[zones]`-Sektion in der ini erhalten — reaktivierbar, falls je gewollt.
from core.logger import get_logger from core.logger import get_logger
from core.history import HistoryLogger from core.history import HistoryLogger
from core.mt5data import MT5Data from core.mt5data import MT5Data
@@ -1898,13 +1901,24 @@ class TradingEngine:
for s in (sr.get("supports") or []): for s in (sr.get("supports") or []):
p = s.get("price") p = s.get("price")
if p: (above if p > bid else below).append(p) if p: (above if p > bid else below).append(p)
# Stehende Zonen aus der Config (beide Kanten als Linien) # ⚠ [zones]-CONFIG ENTFERNT (2026-07-31, Modul-Audit). Vorher flossen hier
try: # beide Kanten jeder `[zones]`-Zone als S/R-Linien ein — 16 Kanten aus einem
for z in parse_zones(self.cfg): # ~10 $ TIEFEREN Kursregime (Zonen bei 72,9077,00 bei einem Kurs von 85,3).
for edge in (z["lo"], z["hi"]): # Aus dem CHART wurden sie schon am 2026-07-14 entfernt, WEIL sie stale sind;
(above if edge > bid else below).append(edge) # in die Wellen-Konfidenz liefen sie aber weiter.
except Exception: # Realer Fall beim Audit (Kurs 85,342): `market.sr` hatte GAR KEINE
pass # Widerstände (M15-Cluster sind in frischen Trends oft leer) → der nächste
# „Widerstand" kam aus der stale `fvg`-Zone bei **88,00** (2,66 $ weg),
# während der echte bei **85,315** lag (0,03 $ weg). Der Konfidenz-Abzug
# „dicht unter Widerstand" (12) greift nur innerhalb 0,5×ATR und feuerte
# deshalb NIE, obwohl er hätte feuern müssen.
# Entfernen ist KEINE Strategieänderung, sondern das Streichen von Daten aus
# einem anderen Preisregime: fehlt ein Level, gibt es weder Bonus noch Abzug —
# das ist ehrlicher als ein falsches Level.
# ⚠ OFFEN (messpflichtig, NICHT hier gemacht): die Wellen-Konfidenz stattdessen
# aus `_draw_levels` (M30, dieselbe Quelle wie Chart + S/R-Close) speisen. Das
# würde den 12-Abzug tatsächlich auslösen → Konfidenz sinkt → das 55%-Gate
# verschiebt sich. Strategieänderung, gehört gemessen.
# Tages-Level aus der Morgen-Recherche (Kontext) # Tages-Level aus der Morgen-Recherche (Kontext)
try: try:
for lv in self.daily.zone_lines(): for lv in self.daily.zone_lines():
@@ -2181,9 +2195,12 @@ class TradingEngine:
# für Trade open und close" — kurz nach dem Einbau wieder verworfen). # für Trade open und close" — kurz nach dem Einbau wieder verworfen).
# Code bleibt reaktivierbar via `[trading] export_trade_marks=true`; # Code bleibt reaktivierbar via `[trading] export_trade_marks=true`;
# spart im Aus-Zustand die DB-Abfrage im ~5-s-Export-Takt. # spart im Aus-Zustand die DB-Abfrage im ~5-s-Export-Takt.
# ⚠ Kein `raise StopIteration` mehr als Sprung (2026-07-31, Audit):
# StopIteration IST eine Exception und wurde vom breiten `except` unten
# gefangen — funktionierte, wäre aber sofort fragil, sobald dort jemand
# Logging ergänzt (Phantom-Fehler bei JEDEM Export-Takt).
if self._export_trade_marks:
try: try:
if not self._export_trade_marks:
raise StopIteration
boff = self.trader._broker_offset_s() boff = self.trader._broker_offset_s()
marks: list[tuple[str, int]] = [] marks: list[tuple[str, int]] = []
ps = self.trader.snapshot() ps = self.trader.snapshot()
@@ -2260,13 +2277,21 @@ class TradingEngine:
# lagt + nicht backtestbar + Standard-Indikator-Konfluenz = kein Edge. Bleibt # lagt + nicht backtestbar + Standard-Indikator-Konfluenz = kein Edge. Bleibt
# nur noch reine Anzeige (Snapshot `tu`), zählt NICHT mehr in Bias/Agree. # nur noch reine Anzeige (Snapshot `tu`), zählt NICHT mehr in Bias/Agree.
# 5) KI-Copilot — OHNE Aussage (kein advisory/bias, z. B. Agent aus) → Gewicht 0 # 5) KI-Copilot — Gewicht NUR bei gerichteter Aussage (LONG/SHORT).
# (stimmt nicht mit ab, Chip bleibt sichtbar). Explizites "NEUTRAL" = echte # ⚠ GEÄNDERT 2026-07-31 (Modul-Audit): vorher zählte ein explizites "NEUTRAL"
# Neutral-Stimme mit Gewicht. # als echte Stimme mit Gewicht 1,0. Gemessen an 7.084 Verdicts ist das aber
# **in 93,1 % der Fälle** der Zustand — also der Normalzustand des Copiloten,
# kein abgewogenes Urteil (Elliott zeigt dasselbe Muster nur in 1,3 %).
# Damit hatte ausgerechnet das Modul mit der SCHWÄCHSTEN Beleglage
# (`analyze_verdict_calibration.py`: nicht robust prädiktiv) den GRÖSSTEN
# dämpfenden Einfluss auf die Bias-Nadel. Wirkung der Angleichung:
# Ø|bias| 0,441 → 0,569 (Median-Verstärkung 1,25×, betrifft 79,5 % der Zeilen);
# kumuliert mit den Fixes von Welle/Squeeze/M30/H1: 0,370 → 0,569 = 1,54×.
# Der Chip bleibt sichtbar und zeigt „NEUTRAL", er stimmt nur nicht mehr mit ab.
adv = (agent or {}).get("advisory") or {} adv = (agent or {}).get("advisory") or {}
ab = adv.get("bias") ab = adv.get("bias")
av = 1 if ab == "LONG" else -1 if ab == "SHORT" else 0 av = 1 if ab == "LONG" else -1 if ab == "SHORT" else 0
add("KI-Copilot", av, 1.0 if ab else 0.0, add("KI-Copilot", av, 1.0 if av != 0 else 0.0,
f"{ab or ''} · {adv.get('confidence', 0)}%") f"{ab or ''} · {adv.get('confidence', 0)}%")
# 6) Elliott/FVG — nur stimmberechtigt, wenn ein Ziel existiert (sonst w=0) # 6) Elliott/FVG — nur stimmberechtigt, wenn ein Ziel existiert (sonst w=0)
@@ -2275,7 +2300,11 @@ class TradingEngine:
if tgt is not None and bid: if tgt is not None and bid:
ev = -1 if tgt < bid else 1 if tgt > bid else 0 ev = -1 if tgt < bid else 1 if tgt > bid else 0
edet = f"{(elliott or {}).get('wave', '')}{tgt:.3f}" edet = f"{(elliott or {}).get('wave', '')}{tgt:.3f}"
ew = 1.0 # ⚠ Gewicht nur bei GERICHTETEM Ziel (2026-07-31, Modul-Audit): liegt das
# Ziel exakt auf dem Kurs, ist ev=0 — das ist keine Aussage und darf die
# Nadel nicht dämpfen. Betraf 1,3 % der Zeilen (klein, aber dieselbe Regel
# wie bei Welle/Squeeze/M30/H1/KI — Konsistenz statt Sonderfall).
ew = 1.0 if ev != 0 else 0.0
add("Elliott", ev, ew, edet) add("Elliott", ev, ew, edet)
# 7) Squeeze-Breakout — Event-Signal: stimmt NUR bei `active` mit (dann 2,0, # 7) Squeeze-Breakout — Event-Signal: stimmt NUR bei `active` mit (dann 2,0,