Richtungs-Pfeile im MT5 statt des Kegels (v1.32) + Handbuch-Muster ergaenzt

PFEILE (User: "anstatt des Trichters einen Pfeil, der die wahrscheinlichste
Kursentwicklung anzeigt"). Randbedingung: die FREIE Richtungsfrage ist
gemessen ein Muenzwurf (analyze_reversal.py, AUC 0,499-0,509 oos, in-sample
nur 0,52). Ein frei schwebender Prognose-Pfeil waere unbelegt - und
gefaehrlicher als der Kegel, weil er ueberzeugender aussieht. Deshalb DREI
Pfeile mit jeweils eigener, benannter Beleglage:
  L blau      naechstes Level, aus dem kalibrierten P(break)
              (AUC 0,65 oos, live 27 % vorhergesagt vs 28 % real)
  S neongruen Squeeze-Ausbruch - das EINZIGE validierte Richtungssignal
  K grau      Konsens der Module - NICHT kalibriert, heisst deshalb
              "Konsens" und nicht "Prognose"

L hat ein TOTBAND 45-55 %: dort waagerechter Pfeil "unentschieden", statt
aus einem Muenzwurf eine Richtung zu zeichnen.

MQL5 v1.32: OBJ_ARROWED_LINE + Label an der Spitze. Label heisst ALBL_* und
NICHT T* - sonst zieht RepositionLabels() es an den rechten Rand und loest
es von der Pfeilspitze.

Kegel bleibt im Code und in der Dashboard-Kachel; der Bot exportiert ihn nur
nicht mehr ins Chart ([trading] export_cone=false).

CHARTMUSTER: alle Handbuch-Muster ergaenzt - Dreifach-Top/-Boden, Flagge,
Wimpel, Rechteck, Steigender/Fallender Keil. ALLE mit measured=False, sie
tragen die Verdict-Stimme NICHT: das Gewicht 1,0 stammt aus einem
Kontrolltest, der nur die alten Typen abdeckte. engine._verdict waehlt jetzt
nur Muster mit measured=True.

Bug beim Bau gefunden: der fallende Keil feuerte in 20.000 Bars KEIN
EINZIGES MAL - die Bedingung stand auf dh > dl, bei einem fallenden Keil
faellt aber die OBERE Linie schneller (sonst konvergiert nichts). Beim
Spiegelbild (steigender Keil) stimmte es.

backtest_patterns_v2.py (NEU) misst die neuen Typen - mit dem ECHTEN
Detektor (core.patterns._detect statt einer Nachbildung) und dem
kanonischen Exit, plus Kontrollgruppe "generischer Swing-Bruch".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-07-31 19:26:11 +02:00
co-authored by Claude Opus 5
parent 365a0584e5
commit 81614a3128
4 changed files with 439 additions and 10 deletions
+67 -1
View File
@@ -12,7 +12,19 @@
//| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). |
//+------------------------------------------------------------------+
#property copyright "Oil Trading Bot"
#property version "1.31"
#property version "1.32"
// v1.32 (2026-07-31): RICHTUNGS-PFEILE (AR;<art>;<von>;<nach>;<text>) statt des
// Kegels (User-Wunsch). DREI Arten mit UNTERSCHIEDLICHER Beleglage:
// L blau = am naechsten Level, aus dem kalibrierten P(break)
// (AUC 0,65 oos, live kalibriert) - BEDINGTE Aussage
// S neongruen = Squeeze-Ausbruch, das EINZIGE 2-Stichproben-validierte
// Richtungssignal - erscheint nur bei `active`
// K grau = Konsens der Verdict-Module - NICHT kalibriert, heisst
// deshalb "Konsens" und nicht "Prognose"
// ⚠ KEINER ist eine freie Kursprognose: die ist im Projekt gemessen ein
// Muenzwurf (analyze_reversal.py, AUC 0,499-0,509 oos, in-sample 0,52).
// Der Kegel bleibt im Code (InpShowCone), der Bot exportiert ihn aber per
// Default nicht mehr ([trading] export_cone).
// v1.31 (2026-07-31): WAHRSCHEINLICHKEITS-KEGEL (CN;<minuten>;<lo>;<hi>) — zwei sich
// oeffnende, gepunktete Pfade vom aktuellen Bar ueber 30/60/120 min.
// ⚠ KEINE Richtungsprognose, sondern STREUUNG: wie weit der Kurs plausibel
@@ -156,6 +168,11 @@ input color InpConsolColor = C'88,166,255'; // Box-Farbe (blau)
input int InpConsolAlpha = 8; // Deckkraft in % (komprimiert: x2)
input int InpConsolBars = 10; // Box-Laenge in Bars (= _SQ_N im Bot)
input bool InpShowCone = true; // Wahrscheinlichkeits-Kegel (Streuung, NICHT Richtung)
input bool InpShowArrows = true; // Richtungs-Pfeile (Level / Squeeze / Konsens)
input color InpArrLevel = C'88,166,255'; // Pfeil am naechsten Level (P(break)) - blau
input color InpArrSqueeze = C'0,255,127'; // Squeeze-Ausbruch (validiert) - neongruen
input color InpArrConsensus = C'139,148,158'; // Konsens der Module (NICHT kalibriert) - grau
input int InpArrBars = 14; // Pfeil-Laenge in Bars (nach rechts)
input color InpConeColor = C'139,148,158'; // Kegel-Farbe (neutral grau - bewusst KEINE Richtungsfarbe)
input bool InpShowPnL = true; // G/V der offenen Position unter dem Kurs
input color InpPnLUpColor = C'0,255,127'; // G/V im Plus (neongruen)
@@ -720,6 +737,55 @@ void Redraw()
g_coneT = t1; g_coneLo = clo; g_coneHi = chi;
continue;
}
// RICHTUNGS-PFEILE: AR;<art>;<von>;<nach>;<text> art = L | S | K
// ⚠ KEINE freie Kursprognose (die ist gemessen ein Muenzwurf) - jede Art hat
// ihre eigene Beleglage, s. Versionshinweis oben.
if(typ == "AR")
{
if(k < 5) continue;
if(!InpShowArrows) continue;
string art = p[1];
double a_from = StringToDouble(p[2]);
double a_to = StringToDouble(p[3]);
string a_txt = p[4];
if(a_from <= 0 || a_to <= 0) continue;
color ac = (art == "S") ? InpArrSqueeze
: (art == "K") ? InpArrConsensus : InpArrLevel;
int aw = (art == "S") ? 3 : 2; // der validierte Pfeil dicker
datetime at0 = iTime(_Symbol, PERIOD_CURRENT, 0);
datetime at1 = at0 + (datetime)(PeriodSeconds() * InpArrBars);
string an = PFX + "ARR_" + art;
if(ObjectCreate(0, an, OBJ_ARROWED_LINE, 0, at0, a_from, at1, a_to))
{
ObjectSetInteger(0, an, OBJPROP_COLOR, ac);
ObjectSetInteger(0, an, OBJPROP_WIDTH, aw);
ObjectSetInteger(0, an, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, an, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, an, OBJPROP_BACK, false);
ObjectSetInteger(0, an, OBJPROP_SELECTABLE, false);
}
else
{
ObjectMove(0, an, 0, at0, a_from);
ObjectMove(0, an, 1, at1, a_to);
ObjectSetInteger(0, an, OBJPROP_COLOR, ac);
}
ObjectSetString(0, an, OBJPROP_TOOLTIP, a_txt);
// Beschriftung an der Pfeilspitze (rechtsbuendig wie alle anderen Labels)
string atn = PFX + "ALBL_" + art; // NICHT "T..." (s. RepositionLabels)
if(ObjectCreate(0, atn, OBJ_TEXT, 0, at1, a_to))
{
ObjectSetInteger(0, atn, OBJPROP_COLOR, ac);
ObjectSetInteger(0, atn, OBJPROP_FONTSIZE, InpLabelSize);
ObjectSetInteger(0, atn, OBJPROP_ANCHOR, ANCHOR_LEFT);
ObjectSetInteger(0, atn, OBJPROP_BACK, false);
ObjectSetInteger(0, atn, OBJPROP_SELECTABLE, false);
}
else
ObjectMove(0, atn, 0, at1, a_to);
ObjectSetString(0, atn, OBJPROP_TEXT, " " + a_txt);
continue;
}
// AKTUELLER KURS oben rechts, fett (User-Wunsch): PX;bid
if(typ == "PX")
{