News-Sentiment war gesaettigt — Beweismengen-Gewichtung eingebaut
Anlass: Frage nach X-Anbindung fuer den Copiloten. Vorher geprueft, ob der vorhandene Textstrom ueberhaupt traegt. Er trug nichts, weil der Score kaputt war. calc_news_sentiment bildete ein REINES VERHAELTNIS (bull-bear)/total, ohne Bezug zur Beweismenge. Eine einzige bullische Schlagzeile bei null baerischen ergab +1,00. Diagnose: - 173 von 173 Log-Eintraegen auf +/-1,00 gesaettigt (100 %) - in 100 % der Faelle eine Seite exakt 0 - Median-Beweismenge nur 2,8 gewichtete Headlines - ueber die DB (54.548 Zeilen): 63,9 % auf exakt +1,00 Real am 03.08.: +1,00 waehrend WTI -5,9 % stand. Der Wert trug ein Bit und loeste im Entry-Check dauerhaft falsche "News-Konflikt"-Warnungen aus. Die Keyword-Listen sind NICHT die Ursache (56/48, keine Ueberschneidung). Fix: Shrinkage score = raw * total/(total+4,0). Die 4,0 ist begruendet, nicht optimiert: bei der realen Median-Beweismenge 2,8 bleibt eine einseitige 3-Headline-Lage unter der 0,5-Warnschwelle, ~10 Headlines ergeben 0,71. Zusaetzlich raw_score und evidence im Rueckgabewert, damit unterscheidbar wird ob "ausgewogene Lage" oder "kaum Daten". Leer-Fall liefert dieselben Felder. 6 Szenarien getestet, live verifiziert: bei identischer Beweislage (bull=1.8, bear=0.0) +1,00 -> +0,31. EHRLICH: das repariert die Kalibrierung, nicht die Aussagekraft. Parallel gemessen (Forward-Return 120 min, 38.213 Paare, 84 Tage, 2 Haelften, gegen die Regime-Drift gelesen): der stark-bullische Bucket liegt in BEIDEN Haelften bei null bis negativ, der baerische kippt das Vorzeichen. News-Sentiment ist nicht robust praediktiv. Bleibt Kontext-Chip ohne Verdict-Stimme. Methodik-Falle dokumentiert: der erste Messlauf nutzte candles_m1 (nur ~14 Tage) -> bisect lieferte fuer aeltere Zeitstempel denselben Randwert, alle Forward-Returns exakt 0,0000. Erst der Lauf mit MT5-M5-Bars plus Deckungspruefung war gueltig. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fe7a1acb97
commit
94fbde1dba
@@ -2595,6 +2595,59 @@ konstant; (d) es gab **keine Telemetrie über die Entscheidung selbst**.
|
|||||||
in ~20 min gefunden; die Trefferquote spricht für weitere. `analyze_divergence.py`
|
in ~20 min gefunden; die Trefferquote spricht für weitere. `analyze_divergence.py`
|
||||||
regelmäßig laufen lassen (Kandidat für den Wochenreport).
|
regelmäßig laufen lassen (Kandidat für den Wochenreport).
|
||||||
|
|
||||||
|
## ⚠⚠ News-Sentiment war GESÄTTIGT — Fix 2026-08-03
|
||||||
|
|
||||||
|
**Anlass:** User-Frage „können wir den X-Account anbinden, um den Copiloten mit mehr
|
||||||
|
Daten zu versorgen?" → erst prüfen, ob der vorhandene Textstrom überhaupt trägt.
|
||||||
|
|
||||||
|
**Befund: er trug nichts, weil der Score kaputt war.** `calc_news_sentiment` bildete
|
||||||
|
ein **reines Verhältnis** `(bull−bear)/total` — **ohne jeden Bezug zur Beweismenge.**
|
||||||
|
Eine einzige bullische Schlagzeile bei null bearischen ergab damit **+1,00**.
|
||||||
|
| Diagnose | Wert |
|
||||||
|
|---|---|
|
||||||
|
| Log-Einträge auf ±1,00 gesättigt | **173 von 173 = 100 %** |
|
||||||
|
| davon mit einer Seite exakt 0 | **100 %** |
|
||||||
|
| Median-Beweismenge (bull+bear) | **2,8** gewichtete Headlines |
|
||||||
|
| DB gesamt (54.548 Zeilen) auf exakt +1,00 | **63,9 %** |
|
||||||
|
Real am 03.08.: Sentiment **+1,00** („bull=1.8, bear=0.0"), während WTI **−5,9 %**
|
||||||
|
stand. Der Wert trug faktisch **ein Bit** (das Vorzeichen) — und löste im Entry-Check
|
||||||
|
dauerhaft falsche „News-Konflikt"-Warnungen aus (Schwelle |s|≥0,5).
|
||||||
|
⚠ Die Keyword-Listen sind NICHT die Ursache (56 bullisch / 48 bärisch, keine
|
||||||
|
Überschneidung) — es war allein die Formel.
|
||||||
|
|
||||||
|
**Fix:** Shrinkage `score = raw × total/(total+_EVIDENCE_K)`, `_EVIDENCE_K=4,0`
|
||||||
|
(gewählt, weil die reale Median-Beweismenge 2,8 beträgt → eine typische einseitige
|
||||||
|
3-Headline-Lage bleibt UNTER der 0,5-Warnschwelle; ~10 Headlines ergeben 0,71).
|
||||||
|
Zusätzlich liefert der Rückgabewert jetzt `raw_score` und `evidence`, damit im
|
||||||
|
UI/Copilot unterscheidbar ist, ob ein schwacher Score „ausgewogene Lage" oder „kaum
|
||||||
|
Daten" bedeutet. Der Leer-Fall gibt dieselben Felder zurück (sonst KeyError genau im
|
||||||
|
„keine News"-Fall). Mit 6 Szenarien getestet, live verifiziert: bei identischer
|
||||||
|
Beweislage (bull=1.8, bear=0.0) **+1,00 → +0,31**.
|
||||||
|
|
||||||
|
⚠⚠ **EHRLICH: Das repariert die KALIBRIERUNG, nicht die Aussagekraft.**
|
||||||
|
Gemessen wurde parallel die Prädiktivität (Forward-Return 120 min, 38.213 Paare über
|
||||||
|
84 Tage, 2 Hälften, **gegen die Regime-Drift gelesen** — H1 +0,005 $, H2 −0,079 $):
|
||||||
|
| Bucket | H1 Überschuss | H2 Überschuss |
|
||||||
|
|---|---|---|
|
||||||
|
| bearisch ≤−0,5 | −0,029 ✓ | **+0,113 ✗ (Vorzeichen kippt)** |
|
||||||
|
| leicht bear | +0,118 ✗ | +0,031 ✗ |
|
||||||
|
| leicht bull | +0,106 ✓ | +0,044 ✓ |
|
||||||
|
| **bullisch ≥+0,5** (grösster Bucket) | −0,003 | **−0,023 ✗** |
|
||||||
|
Der stark-bullische Bucket (16.241 / 11.818 Zeilen) liegt in BEIDEN Hälften bei null
|
||||||
|
bis negativ, der bearische kippt das Vorzeichen. **News-Sentiment ist nicht robust
|
||||||
|
prädiktiv** — auch mit korrigierter Skala. Es bleibt Kontext-Chip ohne Verdict-Stimme.
|
||||||
|
⚠ **Methodik-Falle beim Messen selbst:** der erste Lauf nutzte `candles_m1` (deckt nur
|
||||||
|
~14 Tage), wodurch `bisect` für alle älteren Zeitstempel denselben Randwert lieferte →
|
||||||
|
alle Forward-Returns exakt 0,0000. Erst der Lauf mit MT5-M5-Bars (Jan–Aug) und einer
|
||||||
|
Deckungsprüfung (|Δt| ≤ 15 min) war gültig.
|
||||||
|
|
||||||
|
**Konsequenz für die X-Anbindung:** einen ZWEITEN Textstrom in eine Pipeline zu legen,
|
||||||
|
deren erster gemessen nichts vorhersagt, ist nicht begründbar — zumal X seit 2023
|
||||||
|
**keinen kostenlosen Lesezugang** mehr hat (Basic ≈ 200 $/Monat, Pro ≈ 5.000 $/Monat;
|
||||||
|
Scraping = ToS-Verstoß). Bei ~800 € Konto wären das ~25 % des Kontos pro Monat für
|
||||||
|
einen unvalidierten Input. Erst müsste der reparierte Score über ein paar Wochen
|
||||||
|
zeigen, dass Textdaten hier überhaupt etwas beitragen.
|
||||||
|
|
||||||
## KI-Copilot: warum er neutral ist, und was 2026-08-02 repariert wurde
|
## KI-Copilot: warum er neutral ist, und was 2026-08-02 repariert wurde
|
||||||
|
|
||||||
**User-Frage:** „Der Bias ist fast immer neutral — können wir konkretere Empfehlungen
|
**User-Frage:** „Der Bias ist fast immer neutral — können wir konkretere Empfehlungen
|
||||||
|
|||||||
+39
-2
@@ -39,6 +39,13 @@ NEWS_BEARISH_KW = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Wie viele gewichtete Headlines es braucht, damit der Score seinen Rohwert
|
||||||
|
# annähernd erreicht (Shrinkage-Konstante, s. Begründung in `calc_news_sentiment`).
|
||||||
|
# 4,0 gewählt, weil die reale Median-Beweismenge bei 2,8 liegt: damit bleibt eine
|
||||||
|
# typische, einseitige 3-Headline-Lage UNTER der 0,5-Warnschwelle des Entry-Checks.
|
||||||
|
_EVIDENCE_K = 4.0
|
||||||
|
|
||||||
|
|
||||||
def calc_news_sentiment(headlines: list, half_life_hours: float = 8.0) -> dict:
|
def calc_news_sentiment(headlines: list, half_life_hours: float = 8.0) -> dict:
|
||||||
"""
|
"""
|
||||||
Bewertet Headlines per Keyword-Matching mit altersgewichtetem Decay.
|
Bewertet Headlines per Keyword-Matching mit altersgewichtetem Decay.
|
||||||
@@ -46,7 +53,10 @@ def calc_news_sentiment(headlines: list, half_life_hours: float = 8.0) -> dict:
|
|||||||
"""
|
"""
|
||||||
import time as _time
|
import time as _time
|
||||||
if not headlines:
|
if not headlines:
|
||||||
return {"score": 0.0, "n_bull": 0.0, "n_bear": 0.0, "samples": []}
|
# Felder identisch zum Normalfall halten — sonst wirft ein Konsument, der
|
||||||
|
# `raw_score`/`evidence` liest, ausgerechnet im „keine News"-Fall.
|
||||||
|
return {"score": 0.0, "n_bull": 0.0, "n_bear": 0.0,
|
||||||
|
"raw_score": 0.0, "evidence": 0.0, "samples": []}
|
||||||
|
|
||||||
now = _time.time()
|
now = _time.time()
|
||||||
bull_w = bear_w = 0.0
|
bull_w = bear_w = 0.0
|
||||||
@@ -67,10 +77,37 @@ def calc_news_sentiment(headlines: list, half_life_hours: float = 8.0) -> dict:
|
|||||||
samples.append(("bear", h.get("title", "")[:70]))
|
samples.append(("bear", h.get("title", "")[:70]))
|
||||||
|
|
||||||
total = bull_w + bear_w
|
total = bull_w + bear_w
|
||||||
score = 0.0 if total < 0.1 else (bull_w - bear_w) / total
|
raw = 0.0 if total < 0.1 else (bull_w - bear_w) / total
|
||||||
|
# ── BEWEISMENGEN-GEWICHTUNG (Fix 2026-08-03) ─────────────────────────────
|
||||||
|
# ⚠ Vorher war der Score ein REINES VERHÄLTNIS: `(bull-bear)/total`. Eine
|
||||||
|
# einzige bullische Schlagzeile bei null bearischen ergab damit +1,00 —
|
||||||
|
# maximale Überzeugung aus EINEM Treffer. Gemessen an 173 Log-Einträgen:
|
||||||
|
# **100 % standen auf ±1,00**, und in **100 %** der Fälle war eine Seite
|
||||||
|
# exakt 0; die Median-Beweismenge betrug **2,8** gewichtete Headlines.
|
||||||
|
# Über die gesamte DB (54.548 Zeilen) klebten **63,9 % auf exakt +1,00**.
|
||||||
|
# Real am 03.08.: Sentiment +1,00 („bull=1.8, bear=0.0"), während WTI
|
||||||
|
# −5,9 % stand. Der Wert trug damit faktisch EIN Bit (das Vorzeichen) und
|
||||||
|
# löste im Entry-Check dauerhaft falsche „News-Konflikt"-Warnungen aus.
|
||||||
|
# Korrektur: zur Null schrumpfen, solange die Beweislage dünn ist
|
||||||
|
# (klassische Shrinkage). Bei der Median-Beweismenge 2,8 wird aus 1,00
|
||||||
|
# noch 0,41 — unter der 0,5-Warnschwelle des Entry-Checks; erst ~10
|
||||||
|
# gewichtete Headlines ergeben 0,71.
|
||||||
|
# ⚠ EHRLICH: Das repariert die KALIBRIERUNG, nicht die Aussagekraft. Der
|
||||||
|
# Score bleibt das Vorzeichen weniger Keyword-Treffer, und dessen
|
||||||
|
# Prädiktivität ist gemessen NICHT robust (Forward-Return über 38k Paare,
|
||||||
|
# 2 Hälften: der bearische Bucket kippt das Vorzeichen, der stark-bullische
|
||||||
|
# liegt in BEIDEN Hälften bei null bis negativ). `k` ist eine begründete
|
||||||
|
# Setzung, kein optimierter Wert — es gibt hier nichts zu optimieren,
|
||||||
|
# solange das Signal selbst nichts vorhersagt.
|
||||||
|
conf = total / (total + _EVIDENCE_K) if total > 0 else 0.0
|
||||||
|
score = raw * conf
|
||||||
return {
|
return {
|
||||||
"score": max(-1.0, min(1.0, score)),
|
"score": max(-1.0, min(1.0, score)),
|
||||||
"n_bull": round(bull_w, 1),
|
"n_bull": round(bull_w, 1),
|
||||||
"n_bear": round(bear_w, 1),
|
"n_bear": round(bear_w, 1),
|
||||||
|
# Rohwert + Beweismenge mitliefern: so ist im UI/Copilot erkennbar, ob
|
||||||
|
# ein schwacher Score „ausgewogene Nachrichtenlage" oder „kaum Daten" heißt.
|
||||||
|
"raw_score": round(max(-1.0, min(1.0, raw)), 3),
|
||||||
|
"evidence": round(total, 2),
|
||||||
"samples": samples[:5],
|
"samples": samples[:5],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user