Muster als gefuellte geometrische Formen im MT5-Chart (v1.47)
User-Vorgabe: Dreiecke/Rechtecke/Ellipsen ueber OBJ_* an den berechneten Swings verankern, mit leichtem Grauton gefuellt. PT-Zeile traegt jetzt die Geometrie: PT;<TF>;<name>;<dir>;<trigger>;<ziel>;<form>;<t1>;<p1>;<t2>;<p2>;... dreieck (3 Anker) -> OBJ_TRIANGLE Doppeltop/-boden, Dreiecke, Keile, Wimpel dreieck2 (5 Anker) -> 2x OBJ_TRIANGLE SKS, inv. SKS, Dreifach-Top/-Boden rechteck (2 Anker) -> OBJ_RECTANGLE Rechteck (Range), Flagge ellipse (3 Anker) -> OBJ_ELLIPSE Tasse+Henkel, inverse Tasse dreieck2 braucht ZWEI Objekte, weil OBJ_TRIANGLE nur drei Punkte kennt; die beiden Dreiecke (Schulter-Kopf, Kopf-Schulter) kacheln die Silhouette exakt. OBJPROP_FILL faerbt mit OBJPROP_COLOR - ein Objekt kann keine graue Flaeche UND einen farbigen Rand haben. Deshalb Flaeche neutral grau (InpMusterFill) und OBJPROP_BACK (hinter den Kerzen); die Richtungsaussage tragen Trigger- und Ziellinie darueber. Inhaltlich richtig: die Form ist eine Beobachtung, keine Richtungsprognose. Python (core/patterns.py): add() nimmt form + punkte, legt sie als form/anker in den Muster-dict. REIN ADDITIV - kein bestehender Schluessel aendert sich. Neuer Helfer _keil(): schneidet die beiden Linien und DECKELT den Apex auf last_idx+40 (ein fast paralleles Paar schneidet sich im Unendlichen); nach links begrenzt, damit der Apex nicht im Muster liegt. _anker() rechnet einen Index jenseits des letzten Bars ueber die Bar-Dauer hoch - sonst waere der Apex auf den letzten Bar geklemmt und jedes Dreieck haette einen senkrechten rechten Rand. Bar-Dauer aus den DATEN, nicht aus der TF-Konstante. Zeitstempel sind ROHE Broker-Zeit (rates["time"]) - genau das, was iTime() liefert. Keine Offset-Rechnung, gleiche Konvention wie EQ; und TR;. Vor dem Export wird geprueft, dass Form und Punktzahl zueinander passen - ein Dreieck mit zwei Punkten wuerde der Indikator still verwerfen. Abwaertsvertraeglich in beide Richtungen. Verifiziert: 6 synthetische Muster (Form, Punktzahl, aufsteigende Zeitstempel, Apex in der Zukunft) + live Snapshot patterns_tf.M5 form=dreieck anker=3 + CSV-Zeile mit Geometrie. Compile 0 errors, Pipeline gruen, deployt.
This commit is contained in:
@@ -9504,3 +9504,63 @@ Zeitebene.
|
|||||||
`.ex5` frisch, `0 errors`. **Nur das Ergebnis fehlte** — dieselbe Klasse wie die
|
`.ex5` frisch, `0 errors`. **Nur das Ergebnis fehlte** — dieselbe Klasse wie die
|
||||||
vier dokumentierten Fälle „Erfolg melden, wo nichts geprüft wurde".
|
vier dokumentierten Fälle „Erfolg melden, wo nichts geprüft wurde".
|
||||||
Abschaltbar: `InpShowMuster=false`; Farben `InpMusterBullColor`/`…BearColor`.
|
Abschaltbar: `InpShowMuster=false`; Farben `InpMusterBullColor`/`…BearColor`.
|
||||||
|
|
||||||
|
## ✅ MUSTER ALS GEFÜLLTE GEOMETRISCHE FORMEN IM MT5-CHART (2026-08-21, v1.47)
|
||||||
|
|
||||||
|
User-Vorgabe: Dreiecke/Rechtecke/Ellipsen über `OBJ_*` an den berechneten
|
||||||
|
Swings verankern, **„mit leichtem Grauton gefüllt"**.
|
||||||
|
|
||||||
|
**Die `PT;`-Zeile trägt jetzt die Geometrie mit:**
|
||||||
|
```
|
||||||
|
PT;<TF>;<name>;<dir>;<trigger>;<ziel>;<form>;<t1>;<p1>;<t2>;<p2>;…
|
||||||
|
```
|
||||||
|
| `form` | Anker | MT5-Objekt | Muster |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `dreieck` | 3 | `OBJ_TRIANGLE` | Doppeltop/-boden, Dreiecke, Keile, Wimpel |
|
||||||
|
| `dreieck2` | 5 | **2×** `OBJ_TRIANGLE` | SKS, inverse SKS, Dreifach-Top/-Boden |
|
||||||
|
| `rechteck` | 2 | `OBJ_RECTANGLE` | Rechteck (Range), Flagge |
|
||||||
|
| `ellipse` | 3 | `OBJ_ELLIPSE` | Tasse+Henkel, inverse Tasse |
|
||||||
|
|
||||||
|
⚠ **`dreieck2` braucht ZWEI Objekte**, weil `OBJ_TRIANGLE` nur drei Punkte
|
||||||
|
kennt. Die Dreiecke (Schulter–Kopf und Kopf–Schulter) kacheln die Silhouette
|
||||||
|
exakt — kein Annähern, keine Überdeckung.
|
||||||
|
|
||||||
|
⚠⚠ **Die Füllung kann KEINEN andersfarbigen Rand haben:** `OBJPROP_FILL`
|
||||||
|
färbt mit `OBJPROP_COLOR`. Deshalb ist die Fläche neutral grau
|
||||||
|
(`InpMusterFill`, `C'205,205,205'`) **und `OBJPROP_BACK`** — sie liegt hinter
|
||||||
|
den Kerzen; die Richtungsaussage tragen die farbige Trigger- und Ziellinie
|
||||||
|
darüber. Das ist auch inhaltlich richtig: die **Form** ist eine Beobachtung,
|
||||||
|
keine Richtungsprognose.
|
||||||
|
|
||||||
|
**Umsetzung Python** (`core/patterns.py`): `add()` nimmt `form` und `punkte`
|
||||||
|
(Bar-Index + Preis) und legt sie als `form`/`anker` in den Muster-dict — **rein
|
||||||
|
additiv**, kein bestehender Schlüssel ändert sich (das Verdict-Gewicht liest
|
||||||
|
ohnehin nur `type`/`dir`/`status`/`quality`).
|
||||||
|
⚠ Neuer Helfer **`_keil()`** für die konvergierenden Muster: er schneidet die
|
||||||
|
beiden Linien und **deckelt den Apex** auf `last_idx + 40` — ein fast
|
||||||
|
paralleles Linienpaar schneidet sich sonst im Unendlichen und spännte ein
|
||||||
|
Dreieck über den halben Chart. Nach links begrenzt auf einen Bar hinter dem
|
||||||
|
letzten Stützpunkt, sonst läge der Apex INNERHALB des Musters und die Form
|
||||||
|
würde sich selbst durchdringen.
|
||||||
|
⚠ `_anker()` rechnet einen Index **jenseits des letzten Bars** über die
|
||||||
|
Bar-Dauer hoch (`T` hat dafür keinen Eintrag). Ohne das wäre der Apex auf den
|
||||||
|
letzten Bar geklemmt und **jedes Dreieck hätte einen senkrechten rechten Rand**.
|
||||||
|
Die Bar-Dauer kommt aus den DATEN (`T[-1]-T[-2]`), nicht aus der TF-Konstante —
|
||||||
|
so stimmt sie auch, wenn der Broker Bars auslässt.
|
||||||
|
⚠ Die Zeitstempel sind **rohe Broker-Zeit** aus `rates["time"]` — genau das,
|
||||||
|
was `iTime()` liefert und was ein `OBJ_*`-Anker erwartet. **Keine
|
||||||
|
Offset-Rechnung**, gleiche Konvention wie `EQ;` und `TR;`.
|
||||||
|
|
||||||
|
✅ **Vor dem Export geprüft, dass Form und Punktzahl zueinander passen** — ein
|
||||||
|
Dreieck mit zwei Punkten würde der Indikator still verwerfen, und der Fehler
|
||||||
|
wäre von außen unsichtbar (dieselbe Klasse wie der `PERIOD_CURRENT`-Fall).
|
||||||
|
✅ **Abwärtsverträglich in beide Richtungen:** eine alte CSV ohne Geometrie
|
||||||
|
fällt still auf „nur Linien" zurück, ein alter Indikator ignoriert die
|
||||||
|
Zusatzfelder.
|
||||||
|
✅ **Gegenprobe an sechs synthetischen Mustern** (Doppeltop, Doppelboden, SKS,
|
||||||
|
Tasse, auf-/absteigendes Dreieck): Form, Punktzahl und aufsteigende Zeitstempel
|
||||||
|
stimmen; der Dreiecks-Apex landet korrekt in der Zukunft.
|
||||||
|
✅ **Live verifiziert:** Snapshot `patterns_tf.M5 = {form: dreieck, anker: 3}`,
|
||||||
|
CSV-Zeile
|
||||||
|
`PT;M5;Doppeltop;bear;87.384;86.814;dreieck;1787327400;87.954;1787328000;87.384;1787330100;87.914`.
|
||||||
|
Abschaltbar wie bisher `InpShowMuster=false`; Füllfarbe `InpMusterFill`.
|
||||||
|
|||||||
+26
-2
@@ -2989,6 +2989,10 @@ class TradingEngine:
|
|||||||
"target": best.get("target"),
|
"target": best.get("target"),
|
||||||
"height_atr": best.get("height_atr"),
|
"height_atr": best.get("height_atr"),
|
||||||
"bild": _PAT_BILD.get(best.get("type")),
|
"bild": _PAT_BILD.get(best.get("type")),
|
||||||
|
# Geometrie fuer den MT5-Export (User-Vorgabe 2026-08-21:
|
||||||
|
# die Muster als gefuellte Formen zeichnen).
|
||||||
|
"form": best.get("form"),
|
||||||
|
"anker": best.get("anker"),
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception:
|
||||||
out[lbl] = None
|
out[lbl] = None
|
||||||
@@ -3602,7 +3606,14 @@ class TradingEngine:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
# ── BESTAETIGTES CHARTMUSTER je Zeitebene (User-Wunsch 2026-08-21)
|
# ── BESTAETIGTES CHARTMUSTER je Zeitebene (User-Wunsch 2026-08-21)
|
||||||
# PT;<TF>;<name>;<dir>;<trigger>;<ziel>
|
# PT;<TF>;<name>;<dir>;<trigger>;<ziel>;<form>;<t1>;<p1>;<t2>;<p2>;…
|
||||||
|
# <form> = dreieck (3 Anker) | dreieck2 (5) | rechteck (2) |
|
||||||
|
# ellipse (3). Der Indikator zeichnet daraus das
|
||||||
|
# passende native OBJ_* und fuellt es grau.
|
||||||
|
# ⚠ Die Zeitstempel sind ROHE BROKER-Zeit (aus `rates["time"]`) —
|
||||||
|
# genau das, was `iTime()` liefert und was ein OBJ_*-Anker
|
||||||
|
# erwartet. KEINE Offset-Rechnung: die waere hier falsch (wie bei
|
||||||
|
# `EQ;`/`TR;`, die dieselbe Konvention nutzen).
|
||||||
# Der Indikator zeichnet NUR die Zeile, deren <TF> zu SEINEM Chart
|
# Der Indikator zeichnet NUR die Zeile, deren <TF> zu SEINEM Chart
|
||||||
# passt — so bekommt jedes Fenster (M1/M5/M15/H1) sein eigenes
|
# passt — so bekommt jedes Fenster (M1/M5/M15/H1) sein eigenes
|
||||||
# Muster, ohne dass fuenf Linien uebereinander liegen.
|
# Muster, ohne dass fuenf Linien uebereinander liegen.
|
||||||
@@ -3623,8 +3634,21 @@ class TradingEngine:
|
|||||||
if not _trg or not _zl:
|
if not _trg or not _zl:
|
||||||
continue
|
continue
|
||||||
_nm = str(_m.get("name") or "").replace(";", ",")[:28]
|
_nm = str(_m.get("name") or "").replace(";", ",")[:28]
|
||||||
|
_fm = str(_m.get("form") or "")
|
||||||
|
_ak = _m.get("anker") or []
|
||||||
|
# ⚠ Nur exportieren, wenn Form UND Punktzahl zueinander
|
||||||
|
# passen — ein Dreieck mit zwei Punkten wuerde der
|
||||||
|
# Indikator still verwerfen, und der Fehler waere von
|
||||||
|
# aussen unsichtbar (die Klasse "Erfolg melden, wo nichts
|
||||||
|
# geprueft wurde").
|
||||||
|
_soll = {"dreieck": 3, "dreieck2": 5, "rechteck": 2,
|
||||||
|
"ellipse": 3}.get(_fm, 0)
|
||||||
|
_geo = ""
|
||||||
|
if _soll and len(_ak) == _soll:
|
||||||
|
_geo = ";" + _fm + "".join(
|
||||||
|
f";{int(_pt[0])};{float(_pt[1]):.3f}" for _pt in _ak)
|
||||||
lines.append(f"PT;{_tf};{_nm};{_m.get('dir') or ''};"
|
lines.append(f"PT;{_tf};{_nm};{_m.get('dir') or ''};"
|
||||||
f"{float(_trg):.3f};{float(_zl):.3f}")
|
f"{float(_trg):.3f};{float(_zl):.3f}{_geo}")
|
||||||
except Exception as _pe:
|
except Exception as _pe:
|
||||||
log.debug(f"PT-Export: {_pe}")
|
log.debug(f"PT-Export: {_pe}")
|
||||||
|
|
||||||
|
|||||||
+98
-16
@@ -96,7 +96,32 @@ def _status(dir_, trigger, cur, extreme):
|
|||||||
return "forming"
|
return "forming"
|
||||||
|
|
||||||
|
|
||||||
def _detect(piv, cur, atr, last_idx):
|
def _keil(a1, a2, b1, b2, last_idx, max_extra=40):
|
||||||
|
"""Zwei konvergierende Linien -> DREIECK: linke Kante + Apex.
|
||||||
|
|
||||||
|
`a`/`b` je zwei (bar_index, preis). Der Apex ist der Schnittpunkt.
|
||||||
|
⚠ Er wird auf `last_idx + max_extra` GEDECKELT: ein fast paralleles
|
||||||
|
Linienpaar schneidet sich irgendwo im Unendlichen und wuerde sonst ein
|
||||||
|
Dreieck ueber den halben Chart aufspannen. Nach links begrenzt auf
|
||||||
|
mindestens einen Bar hinter dem letzten Stuetzpunkt, damit der Apex
|
||||||
|
nicht INNERHALB des Musters landet und die Form sich selbst durchdringt.
|
||||||
|
"""
|
||||||
|
(x1, y1), (x2, y2) = a1, a2
|
||||||
|
(x3, y3), (x4, y4) = b1, b2
|
||||||
|
ma = (y2 - y1) / (x2 - x1) if x2 != x1 else 0.0
|
||||||
|
mb = (y4 - y3) / (x4 - x3) if x4 != x3 else 0.0
|
||||||
|
x0 = min(x1, x3)
|
||||||
|
if abs(ma - mb) < 1e-12:
|
||||||
|
xa = last_idx + max_extra
|
||||||
|
else:
|
||||||
|
xa = (y3 - mb * x3 - y1 + ma * x1) / (ma - mb)
|
||||||
|
xa = max(min(xa, last_idx + max_extra), max(x2, x4) + 1)
|
||||||
|
return [(int(x0), y1 + ma * (x0 - x1)),
|
||||||
|
(int(x0), y3 + mb * (x0 - x3)),
|
||||||
|
(int(round(xa)), y1 + ma * (xa - x1))]
|
||||||
|
|
||||||
|
|
||||||
|
def _detect(piv, cur, atr, last_idx, T=None, bar_s=0):
|
||||||
"""Sucht Muster in den letzten Swings. → Liste Muster-dicts."""
|
"""Sucht Muster in den letzten Swings. → Liste Muster-dicts."""
|
||||||
out = []
|
out = []
|
||||||
P = piv[-_MAX_LOOKBACK:]
|
P = piv[-_MAX_LOOKBACK:]
|
||||||
@@ -104,7 +129,30 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
return out
|
return out
|
||||||
pr = [p[1] for p in P]; kd = [p[2] for p in P]; ix = [p[0] for p in P]
|
pr = [p[1] for p in P]; kd = [p[2] for p in P]; ix = [p[0] for p in P]
|
||||||
|
|
||||||
def add(typ, name, dir_, quality, trigger, extreme, note):
|
def _anker(punkte):
|
||||||
|
"""[(bar_index, preis)] -> [[epoch, preis]] fuer den MT5-Export.
|
||||||
|
|
||||||
|
⚠ Ein Index JENSEITS des letzten Bars (der Dreiecks-Apex liegt in
|
||||||
|
der Zukunft) wird ueber die Bar-Dauer hochgerechnet — `T` hat dafuer
|
||||||
|
keinen Eintrag. Ohne das waere der Apex auf den letzten Bar geklemmt
|
||||||
|
und jedes Dreieck haette einen senkrechten rechten Rand.
|
||||||
|
"""
|
||||||
|
if not T:
|
||||||
|
return None
|
||||||
|
aus = []
|
||||||
|
for i, pr_ in punkte:
|
||||||
|
i = int(i)
|
||||||
|
if 0 <= i < len(T):
|
||||||
|
t = int(T[i])
|
||||||
|
elif i >= len(T):
|
||||||
|
t = int(T[-1] + (i - len(T) + 1) * max(bar_s, 60))
|
||||||
|
else:
|
||||||
|
t = int(T[0])
|
||||||
|
aus.append([t, round(float(pr_), 3)])
|
||||||
|
return aus
|
||||||
|
|
||||||
|
def add(typ, name, dir_, quality, trigger, extreme, note,
|
||||||
|
form=None, punkte=None):
|
||||||
h = abs(extreme - trigger)
|
h = abs(extreme - trigger)
|
||||||
if h < _MIN_HEIGHT_ATR * atr: # zu flach = Rauschen
|
if h < _MIN_HEIGHT_ATR * atr: # zu flach = Rauschen
|
||||||
return
|
return
|
||||||
@@ -122,6 +170,12 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
# Projekts). Gemessen wurden: Doppeltop/-boden, Tasse/inv. Tasse,
|
# Projekts). Gemessen wurden: Doppeltop/-boden, Tasse/inv. Tasse,
|
||||||
# auf-/absteigendes Dreieck, SKS/inv. SKS.
|
# auf-/absteigendes Dreieck, SKS/inv. SKS.
|
||||||
"measured": typ in _MEASURED,
|
"measured": typ in _MEASURED,
|
||||||
|
# ⚠ Geometrie fuer den MT5-Export (User-Vorgabe 2026-08-21: die
|
||||||
|
# Muster als gefuellte Formen zeichnen). REIN ADDITIV — kein
|
||||||
|
# bestehender Schluessel aendert sich; das Verdict-Gewicht liest
|
||||||
|
# ohnehin nur type/dir/status/quality.
|
||||||
|
"form": form,
|
||||||
|
"anker": _anker(punkte) if punkte else None,
|
||||||
})
|
})
|
||||||
|
|
||||||
# über alle 3er/5er-Fenster am aktuellen Rand
|
# über alle 3er/5er-Fenster am aktuellen Rand
|
||||||
@@ -133,14 +187,16 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
q = _sim(Ha, Hb, atr)
|
q = _sim(Ha, Hb, atr)
|
||||||
if q > 0.35 and Lm < min(Ha, Hb):
|
if q > 0.35 and Lm < min(Ha, Hb):
|
||||||
add("double_top", "Doppeltop", "bear", q, Lm, max(Ha, Hb),
|
add("double_top", "Doppeltop", "bear", q, Lm, max(Ha, Hb),
|
||||||
f"zwei Hochs {Ha:.2f}/{Hb:.2f}, Nackenlinie {Lm:.2f}")
|
f"zwei Hochs {Ha:.2f}/{Hb:.2f}, Nackenlinie {Lm:.2f}",
|
||||||
|
"dreieck", [(w[0][2], Ha), (w[1][2], Lm), (w[2][2], Hb)])
|
||||||
# ── Doppelboden: L, H, L ──
|
# ── Doppelboden: L, H, L ──
|
||||||
if len(w) >= 3 and w[0][0] == "L" and w[1][0] == "H" and w[2][0] == "L":
|
if len(w) >= 3 and w[0][0] == "L" and w[1][0] == "H" and w[2][0] == "L":
|
||||||
La, Hm, Lb = w[0][1], w[1][1], w[2][1]
|
La, Hm, Lb = w[0][1], w[1][1], w[2][1]
|
||||||
q = _sim(La, Lb, atr)
|
q = _sim(La, Lb, atr)
|
||||||
if q > 0.35 and Hm > max(La, Lb):
|
if q > 0.35 and Hm > max(La, Lb):
|
||||||
add("double_bottom", "Doppelboden", "bull", q, Hm, min(La, Lb),
|
add("double_bottom", "Doppelboden", "bull", q, Hm, min(La, Lb),
|
||||||
f"zwei Tiefs {La:.2f}/{Lb:.2f}, Nackenlinie {Hm:.2f}")
|
f"zwei Tiefs {La:.2f}/{Lb:.2f}, Nackenlinie {Hm:.2f}",
|
||||||
|
"dreieck", [(w[0][2], La), (w[1][2], Hm), (w[2][2], Lb)])
|
||||||
# ── Kopf-Schulter (SKS): H, L, H, L, H (Kopf = mittleres Hoch am höchsten) ──
|
# ── Kopf-Schulter (SKS): H, L, H, L, H (Kopf = mittleres Hoch am höchsten) ──
|
||||||
if len(w) >= 5 and [x[0] for x in w[:5]] == ["H", "L", "H", "L", "H"]:
|
if len(w) >= 5 and [x[0] for x in w[:5]] == ["H", "L", "H", "L", "H"]:
|
||||||
ls, t1, head, t2, rs = (w[i][1] for i in range(5))
|
ls, t1, head, t2, rs = (w[i][1] for i in range(5))
|
||||||
@@ -149,7 +205,8 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
q = _sim(ls, rs, atr) * _sim(t1, t2, atr)
|
q = _sim(ls, rs, atr) * _sim(t1, t2, atr)
|
||||||
if q > 0.25 and abs(t1 - t2) < _NECK_TOL_ATR * atr:
|
if q > 0.25 and abs(t1 - t2) < _NECK_TOL_ATR * atr:
|
||||||
add("hs", "Kopf-Schulter", "bear", q, neck, head,
|
add("hs", "Kopf-Schulter", "bear", q, neck, head,
|
||||||
f"Kopf {head:.2f}, Schultern {ls:.2f}/{rs:.2f}, Nacken {neck:.2f}")
|
f"Kopf {head:.2f}, Schultern {ls:.2f}/{rs:.2f}, Nacken {neck:.2f}",
|
||||||
|
"dreieck2", [(w[i][2], w[i][1]) for i in range(5)])
|
||||||
# ── Inverse SKS: L, H, L, H, L ──
|
# ── Inverse SKS: L, H, L, H, L ──
|
||||||
if len(w) >= 5 and [x[0] for x in w[:5]] == ["L", "H", "L", "H", "L"]:
|
if len(w) >= 5 and [x[0] for x in w[:5]] == ["L", "H", "L", "H", "L"]:
|
||||||
ls, t1, head, t2, rs = (w[i][1] for i in range(5))
|
ls, t1, head, t2, rs = (w[i][1] for i in range(5))
|
||||||
@@ -158,7 +215,8 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
q = _sim(ls, rs, atr) * _sim(t1, t2, atr)
|
q = _sim(ls, rs, atr) * _sim(t1, t2, atr)
|
||||||
if q > 0.25 and abs(t1 - t2) < _NECK_TOL_ATR * atr:
|
if q > 0.25 and abs(t1 - t2) < _NECK_TOL_ATR * atr:
|
||||||
add("inv_hs", "Inverse SKS", "bull", q, neck, head,
|
add("inv_hs", "Inverse SKS", "bull", q, neck, head,
|
||||||
f"Kopf {head:.2f}, Schultern {ls:.2f}/{rs:.2f}, Nacken {neck:.2f}")
|
f"Kopf {head:.2f}, Schultern {ls:.2f}/{rs:.2f}, Nacken {neck:.2f}",
|
||||||
|
"dreieck2", [(w[i][2], w[i][1]) for i in range(5)])
|
||||||
# ── (Inverse) Tasse+Henkel (heuristisch): Rand-Extrema ~gleich, Boden/Top
|
# ── (Inverse) Tasse+Henkel (heuristisch): Rand-Extrema ~gleich, Boden/Top
|
||||||
# dazwischen, breit; Henkel = letzter kleiner Gegen-Swing. ──
|
# dazwischen, breit; Henkel = letzter kleiner Gegen-Swing. ──
|
||||||
if len(w) >= 3:
|
if len(w) >= 3:
|
||||||
@@ -168,13 +226,15 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
q = _sim(rim_l, rim_r, atr) * 0.9
|
q = _sim(rim_l, rim_r, atr) * 0.9
|
||||||
if q > 0.4 and top > max(rim_l, rim_r):
|
if q > 0.4 and top > max(rim_l, rim_r):
|
||||||
add("inv_cup", "Inverse Tasse+Henkel", "bear", q, min(rim_l, rim_r), top,
|
add("inv_cup", "Inverse Tasse+Henkel", "bear", q, min(rim_l, rim_r), top,
|
||||||
f"abgerundetes Top {top:.2f}, Rand ~{rim_r:.2f} (Henkel-Unterkante)")
|
f"abgerundetes Top {top:.2f}, Rand ~{rim_r:.2f} (Henkel-Unterkante)",
|
||||||
|
"ellipse", [(w[0][2], rim_l), (w[2][2], rim_r), (w[1][2], top)])
|
||||||
if w[0][0] == "H" and w[1][0] == "L" and w[2][0] == "H" and span >= 10:
|
if w[0][0] == "H" and w[1][0] == "L" and w[2][0] == "H" and span >= 10:
|
||||||
rim_l, bot, rim_r = w[0][1], w[1][1], w[2][1] # Tasse (abger. Boden)
|
rim_l, bot, rim_r = w[0][1], w[1][1], w[2][1] # Tasse (abger. Boden)
|
||||||
q = _sim(rim_l, rim_r, atr) * 0.9
|
q = _sim(rim_l, rim_r, atr) * 0.9
|
||||||
if q > 0.4 and bot < min(rim_l, rim_r):
|
if q > 0.4 and bot < min(rim_l, rim_r):
|
||||||
add("cup", "Tasse+Henkel", "bull", q, max(rim_l, rim_r), bot,
|
add("cup", "Tasse+Henkel", "bull", q, max(rim_l, rim_r), bot,
|
||||||
f"abgerundeter Boden {bot:.2f}, Rand ~{rim_r:.2f} (Henkel-Oberkante)")
|
f"abgerundeter Boden {bot:.2f}, Rand ~{rim_r:.2f} (Henkel-Oberkante)",
|
||||||
|
"ellipse", [(w[0][2], rim_l), (w[2][2], rim_r), (w[1][2], bot)])
|
||||||
|
|
||||||
# ══ HANDBUCH-MUSTER (ergänzt 2026-07-31, User-Vorgabe „alle Muster aus dem
|
# ══ HANDBUCH-MUSTER (ergänzt 2026-07-31, User-Vorgabe „alle Muster aus dem
|
||||||
# Handbuch") — ALLE REINE ANZEIGE (`measured=False`), sie tragen die
|
# Handbuch") — ALLE REINE ANZEIGE (`measured=False`), sie tragen die
|
||||||
@@ -190,14 +250,16 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
if q > 0.30 and h2 <= max(h1, h3) + 0.3 * atr: # kein Kopf → kein SKS
|
if q > 0.30 and h2 <= max(h1, h3) + 0.3 * atr: # kein Kopf → kein SKS
|
||||||
neck = min(t1, t2)
|
neck = min(t1, t2)
|
||||||
add("triple_top", "Dreifach-Top", "bear", q, neck, max(h1, h2, h3),
|
add("triple_top", "Dreifach-Top", "bear", q, neck, max(h1, h2, h3),
|
||||||
f"drei Hochs {h1:.2f}/{h2:.2f}/{h3:.2f}, Nacken {neck:.2f}")
|
f"drei Hochs {h1:.2f}/{h2:.2f}/{h3:.2f}, Nacken {neck:.2f}",
|
||||||
|
"dreieck2", [(w[i][2], w[i][1]) for i in range(5)])
|
||||||
if len(w) >= 5 and [x[0] for x in w[:5]] == ["L", "H", "L", "H", "L"]:
|
if len(w) >= 5 and [x[0] for x in w[:5]] == ["L", "H", "L", "H", "L"]:
|
||||||
l1, t1, l2, t2, l3 = (w[i][1] for i in range(5))
|
l1, t1, l2, t2, l3 = (w[i][1] for i in range(5))
|
||||||
q = _sim(l1, l2, atr) * _sim(l2, l3, atr)
|
q = _sim(l1, l2, atr) * _sim(l2, l3, atr)
|
||||||
if q > 0.30 and l2 >= min(l1, l3) - 0.3 * atr:
|
if q > 0.30 and l2 >= min(l1, l3) - 0.3 * atr:
|
||||||
neck = max(t1, t2)
|
neck = max(t1, t2)
|
||||||
add("triple_bottom", "Dreifach-Boden", "bull", q, neck, min(l1, l2, l3),
|
add("triple_bottom", "Dreifach-Boden", "bull", q, neck, min(l1, l2, l3),
|
||||||
f"drei Tiefs {l1:.2f}/{l2:.2f}/{l3:.2f}, Nacken {neck:.2f}")
|
f"drei Tiefs {l1:.2f}/{l2:.2f}/{l3:.2f}, Nacken {neck:.2f}",
|
||||||
|
"dreieck2", [(w[i][2], w[i][1]) for i in range(5)])
|
||||||
|
|
||||||
# ── Flagge / Wimpel (Fortsetzung): impulsive STANGE, danach eine kleine
|
# ── Flagge / Wimpel (Fortsetzung): impulsive STANGE, danach eine kleine
|
||||||
# Konsolidierung GEGEN die Stangenrichtung. Flagge = paralleler Kanal,
|
# Konsolidierung GEGEN die Stangenrichtung. Flagge = paralleler Kanal,
|
||||||
@@ -217,9 +279,16 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
ext = min(cons) if up else max(cons)
|
ext = min(cons) if up else max(cons)
|
||||||
typ = "pennant" if pennant else "flag"
|
typ = "pennant" if pennant else "flag"
|
||||||
nm = ("Wimpel" if pennant else "Flagge") + (" (bullisch)" if up else " (bärisch)")
|
nm = ("Wimpel" if pennant else "Flagge") + (" (bullisch)" if up else " (bärisch)")
|
||||||
|
_ci = [x[2] for x in w[1:5]]
|
||||||
|
# Wimpel = konvergierend -> Dreieck; Flagge = paralleler
|
||||||
|
# Kanal -> Rechteck (zwei diagonale Ecken).
|
||||||
|
_pk = ([(_ci[0], max(cons)), (_ci[0], min(cons)),
|
||||||
|
(_ci[-1], cons[-1])] if pennant
|
||||||
|
else [(_ci[0], max(cons)), (_ci[-1], min(cons))])
|
||||||
add(typ, nm, "bull" if up else "bear", 0.55, trig, ext,
|
add(typ, nm, "bull" if up else "bear", 0.55, trig, ext,
|
||||||
f"Stange {pole_h/atr:.1f}×ATR in {pole_bars} Bars, "
|
f"Stange {pole_h/atr:.1f}×ATR in {pole_bars} Bars, "
|
||||||
f"{'konvergierende' if pennant else 'flache'} Konsolidierung")
|
f"{'konvergierende' if pennant else 'flache'} Konsolidierung",
|
||||||
|
"dreieck" if pennant else "rechteck", _pk)
|
||||||
|
|
||||||
# ── Rechteck (Range): zwei ~flache Hochs UND zwei ~flache Tiefs. Das Handbuch
|
# ── Rechteck (Range): zwei ~flache Hochs UND zwei ~flache Tiefs. Das Handbuch
|
||||||
# führt es als Fortsetzung — die Ausbruchsrichtung ist aber offen, deshalb
|
# führt es als Fortsetzung — die Ausbruchsrichtung ist aber offen, deshalb
|
||||||
@@ -240,6 +309,8 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
"height_atr": round((top - bot) / atr, 1), "status": "forming",
|
"height_atr": round((top - bot) / atr, 1), "status": "forming",
|
||||||
"bars_ago": last_idx - ix[-1], "measured": False,
|
"bars_ago": last_idx - ix[-1], "measured": False,
|
||||||
"note": f"Range {bot:.2f}–{top:.2f} — Ausbruchsrichtung offen",
|
"note": f"Range {bot:.2f}–{top:.2f} — Ausbruchsrichtung offen",
|
||||||
|
"form": "rechteck",
|
||||||
|
"anker": _anker([(hh[0][0], top), (ll[1][0], bot)]),
|
||||||
})
|
})
|
||||||
# ── Keil: beide Linien in DIESELBE Richtung geneigt und konvergierend.
|
# ── Keil: beide Linien in DIESELBE Richtung geneigt und konvergierend.
|
||||||
# Steigender Keil = bärisch, fallender Keil = bullisch (Handbuch).
|
# Steigender Keil = bärisch, fallender Keil = bullisch (Handbuch).
|
||||||
@@ -249,7 +320,8 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
if conv and dh > 0.3 * atr and dl > 0.3 * atr and dl > dh:
|
if conv and dh > 0.3 * atr and dl > 0.3 * atr and dl > dh:
|
||||||
add("wedge_rise", "Steigender Keil", "bear", 0.5,
|
add("wedge_rise", "Steigender Keil", "bear", 0.5,
|
||||||
min(ll[0][1], ll[1][1]), max(hh[0][1], hh[1][1]),
|
min(ll[0][1], ll[1][1]), max(hh[0][1], hh[1][1]),
|
||||||
"beide Linien steigen, Tiefs schneller — Erschöpfung nach oben")
|
"beide Linien steigen, Tiefs schneller — Erschöpfung nach oben",
|
||||||
|
"dreieck", _keil(hh[0], hh[1], ll[0], ll[1], last_idx))
|
||||||
# ⚠ Bedingung korrigiert (2026-07-31): stand `dh > dl` — bei einem FALLENDEN
|
# ⚠ Bedingung korrigiert (2026-07-31): stand `dh > dl` — bei einem FALLENDEN
|
||||||
# Keil fällt aber die OBERE Linie schneller (sonst konvergiert nichts), also
|
# Keil fällt aber die OBERE Linie schneller (sonst konvergiert nichts), also
|
||||||
# `dh < dl`. Mit der alten Fassung war die Bedingung in sich widersprüchlich
|
# `dh < dl`. Mit der alten Fassung war die Bedingung in sich widersprüchlich
|
||||||
@@ -258,7 +330,8 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
if conv and dh < -0.3 * atr and dl < -0.3 * atr and dh < dl:
|
if conv and dh < -0.3 * atr and dl < -0.3 * atr and dh < dl:
|
||||||
add("wedge_fall", "Fallender Keil", "bull", 0.5,
|
add("wedge_fall", "Fallender Keil", "bull", 0.5,
|
||||||
max(hh[0][1], hh[1][1]), min(ll[0][1], ll[1][1]),
|
max(hh[0][1], hh[1][1]), min(ll[0][1], ll[1][1]),
|
||||||
"beide Linien fallen, Hochs schneller — Erschöpfung nach unten")
|
"beide Linien fallen, Hochs schneller — Erschöpfung nach unten",
|
||||||
|
"dreieck", _keil(hh[0], hh[1], ll[0], ll[1], last_idx))
|
||||||
|
|
||||||
# ── Dreiecke (Fortsetzung): letzte 2 Hochs + 2 Tiefs, Steigungen prüfen ──
|
# ── Dreiecke (Fortsetzung): letzte 2 Hochs + 2 Tiefs, Steigungen prüfen ──
|
||||||
highs = [(x[2], x[1]) for x in zip(kd, pr, ix) if x[0] == "H"][-2:]
|
highs = [(x[2], x[1]) for x in zip(kd, pr, ix) if x[0] == "H"][-2:]
|
||||||
@@ -275,11 +348,13 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
if flat_h and rising_l: # aufsteigendes Dreieck (bullisch)
|
if flat_h and rising_l: # aufsteigendes Dreieck (bullisch)
|
||||||
res_ = max(h1p, h2p)
|
res_ = max(h1p, h2p)
|
||||||
add("tri_asc", "Aufsteigendes Dreieck", "bull", 0.6, res_, min(l1p, l2p),
|
add("tri_asc", "Aufsteigendes Dreieck", "bull", 0.6, res_, min(l1p, l2p),
|
||||||
f"flacher Widerstand {res_:.2f}, steigende Tiefs")
|
f"flacher Widerstand {res_:.2f}, steigende Tiefs",
|
||||||
|
"dreieck", _keil(highs[0], highs[1], lows[0], lows[1], last_idx))
|
||||||
elif flat_l and falling_h: # absteigendes Dreieck (bärisch)
|
elif flat_l and falling_h: # absteigendes Dreieck (bärisch)
|
||||||
sup_ = min(l1p, l2p)
|
sup_ = min(l1p, l2p)
|
||||||
add("tri_desc", "Absteigendes Dreieck", "bear", 0.6, sup_, max(h1p, h2p),
|
add("tri_desc", "Absteigendes Dreieck", "bear", 0.6, sup_, max(h1p, h2p),
|
||||||
f"flacher Support {sup_:.2f}, fallende Hochs")
|
f"flacher Support {sup_:.2f}, fallende Hochs",
|
||||||
|
"dreieck", _keil(highs[0], highs[1], lows[0], lows[1], last_idx))
|
||||||
elif falling_h and rising_l: # symmetrisch → Ausbruch offen (nur Anzeige)
|
elif falling_h and rising_l: # symmetrisch → Ausbruch offen (nur Anzeige)
|
||||||
out.append({
|
out.append({
|
||||||
"type": "tri_sym", "name": "Symmetrisches Dreieck", "dir": "neutral",
|
"type": "tri_sym", "name": "Symmetrisches Dreieck", "dir": "neutral",
|
||||||
@@ -288,6 +363,9 @@ def _detect(piv, cur, atr, last_idx):
|
|||||||
"status": "forming", "bars_ago": last_idx - ix[-1],
|
"status": "forming", "bars_ago": last_idx - ix[-1],
|
||||||
"note": f"konvergierend (Hochs fallen, Tiefs steigen) — Ausbruchsrichtung offen",
|
"note": f"konvergierend (Hochs fallen, Tiefs steigen) — Ausbruchsrichtung offen",
|
||||||
"measured": False, # neutral, ohne Richtung → nie stimmberechtigt
|
"measured": False, # neutral, ohne Richtung → nie stimmberechtigt
|
||||||
|
"form": "dreieck",
|
||||||
|
"anker": _anker(_keil(highs[0], highs[1], lows[0], lows[1],
|
||||||
|
last_idx)),
|
||||||
})
|
})
|
||||||
|
|
||||||
# Duplikate (gleicher Typ+Trigger) zusammenfassen, beste Qualität behalten
|
# Duplikate (gleicher Typ+Trigger) zusammenfassen, beste Qualität behalten
|
||||||
@@ -376,8 +454,12 @@ class PatternDetector:
|
|||||||
atr = _atr(H, L, C)
|
atr = _atr(H, L, C)
|
||||||
if not atr or atr <= 0:
|
if not atr or atr <= 0:
|
||||||
return
|
return
|
||||||
|
T = [int(b["time"]) for b in bars]
|
||||||
|
# ⚠ Bar-Dauer aus den DATEN, nicht aus der TF-Konstante — so
|
||||||
|
# stimmt sie auch, wenn der Broker Bars auslaesst.
|
||||||
|
_bs = (T[-1] - T[-2]) if len(T) > 1 else 0
|
||||||
piv = _pivots(H, L, _PIVOT_K)
|
piv = _pivots(H, L, _PIVOT_K)
|
||||||
patterns = _detect(piv, C[-1], atr, len(H) - 1)
|
patterns = _detect(piv, C[-1], atr, len(H) - 1, T, _bs)
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._snap = {"patterns": patterns, "atr": round(atr, 4),
|
self._snap = {"patterns": patterns, "atr": round(atr, 4),
|
||||||
"cur": round(C[-1], 3), "ts": now,
|
"cur": round(C[-1], 3), "ts": now,
|
||||||
|
|||||||
+80
-1
@@ -12,7 +12,7 @@
|
|||||||
//| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). |
|
//| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
#property copyright "Oil Trading Bot"
|
#property copyright "Oil Trading Bot"
|
||||||
#property version "1.46"
|
#property version "1.47"
|
||||||
// v1.42 (2026-08-19): Y-Stapel oben rechts GEMESSEN statt geschaetzt. Der
|
// v1.42 (2026-08-19): Y-Stapel oben rechts GEMESSEN statt geschaetzt. Der
|
||||||
// Faktor 1,8 aus v1.41 war nur die naechste Schaetzung; jetzt liefert
|
// Faktor 1,8 aus v1.41 war nur die naechste Schaetzung; jetzt liefert
|
||||||
// TextGetSize die TATSAECHLICHE Pixelhoehe (LabelH). Ausserdem wird Y bei
|
// TextGetSize die TATSAECHLICHE Pixelhoehe (LabelH). Ausserdem wird Y bei
|
||||||
@@ -276,6 +276,9 @@ input color InpZoneSupColor = C'20,45,35'; // Support-Zone (dunkelgruen)
|
|||||||
input bool InpShowMuster = true; // bestaetigtes Chartmuster zeichnen
|
input bool InpShowMuster = true; // bestaetigtes Chartmuster zeichnen
|
||||||
input color InpMusterBullColor = C'70,180,100';// bullisch
|
input color InpMusterBullColor = C'70,180,100';// bullisch
|
||||||
input color InpMusterBearColor = C'220,90,80'; // baerisch
|
input color InpMusterBearColor = C'220,90,80'; // baerisch
|
||||||
|
// ⚠ "leichter Grauton" (User-Vorgabe 2026-08-21). Die Flaeche traegt KEINE
|
||||||
|
// Richtungsaussage — die steht in den farbigen Trigger-/Ziellinien darueber.
|
||||||
|
input color InpMusterFill = C'205,205,205';// Fuellung der Musterform
|
||||||
|
|
||||||
const string PFX = "SRB_"; // Präfix S/R-Linien (aus Datei)
|
const string PFX = "SRB_"; // Präfix S/R-Linien (aus Datei)
|
||||||
const string RPFX = "SRR_"; // Präfix dynamische Range (aus Chart)
|
const string RPFX = "SRR_"; // Präfix dynamische Range (aus Chart)
|
||||||
@@ -342,6 +345,33 @@ string TFName(ENUM_TIMEFRAMES tf)
|
|||||||
return EnumToString(tf);
|
return EnumToString(tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Gefuellte Muster-Form (User-Vorgabe 2026-08-21). |
|
||||||
|
//| ⚠⚠ OBJPROP_FILL faerbt mit OBJPROP_COLOR — ein Objekt kann NICHT |
|
||||||
|
//| gleichzeitig eine graue Flaeche und einen farbigen Rand haben. |
|
||||||
|
//| Deshalb: Flaeche grau und OBJPROP_BACK (hinter den Kerzen), die |
|
||||||
|
//| Richtungsaussage tragen Trigger- und Ziellinie darueber. |
|
||||||
|
//| ⚠ Kein Aufraeumen noetig: `ObjectsDeleteAll(0, PFX)` loescht bei |
|
||||||
|
//| jedem Redraw alle PFX-Objekte, es kann also keine Form aus einem|
|
||||||
|
//| vorherigen Muster stehenbleiben. |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void DrawMusterForm(string name, ENUM_OBJECT otyp,
|
||||||
|
datetime &t[], double &pz[], int n)
|
||||||
|
{
|
||||||
|
if(ObjectFind(0, name) >= 0) ObjectDelete(0, name);
|
||||||
|
bool ok = false;
|
||||||
|
if(n == 2)
|
||||||
|
ok = ObjectCreate(0, name, otyp, 0, t[0], pz[0], t[1], pz[1]);
|
||||||
|
else if(n == 3)
|
||||||
|
ok = ObjectCreate(0, name, otyp, 0, t[0], pz[0], t[1], pz[1], t[2], pz[2]);
|
||||||
|
if(!ok) return;
|
||||||
|
ObjectSetInteger(0, name, OBJPROP_COLOR, InpMusterFill);
|
||||||
|
ObjectSetInteger(0, name, OBJPROP_FILL, true);
|
||||||
|
ObjectSetInteger(0, name, OBJPROP_BACK, true);
|
||||||
|
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
|
||||||
|
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
|
||||||
|
}
|
||||||
|
|
||||||
//| ⚠ MT5 kann bei OBJ_RECTANGLE KEIN echtes Alpha (nur Canvas- |
|
//| ⚠ MT5 kann bei OBJ_RECTANGLE KEIN echtes Alpha (nur Canvas- |
|
||||||
//| Objekte könnten das). Da der Hintergrund bekannt und einfarbig |
|
//| Objekte könnten das). Da der Hintergrund bekannt und einfarbig |
|
||||||
//| ist, sieht die Mischung exakt aus wie eine transparente Füllung. |
|
//| ist, sieht die Mischung exakt aus wie eine transparente Füllung. |
|
||||||
@@ -1066,6 +1096,55 @@ void Redraw()
|
|||||||
+ DoubleToString(zl, (int)_Digits) + " (trifft 13-38 %)");
|
+ DoubleToString(zl, (int)_Digits) + " (trifft 13-38 %)");
|
||||||
ObjectSetInteger(0, plb, OBJPROP_COLOR, pc);
|
ObjectSetInteger(0, plb, OBJPROP_COLOR, pc);
|
||||||
ObjectMove(0, plb, 0, RightTime(), trg);
|
ObjectMove(0, plb, 0, RightTime(), trg);
|
||||||
|
// ── GEFUELLTE MUSTER-FORM (User-Vorgabe 2026-08-21) ──────────
|
||||||
|
// Feldlage: p[6]=form, danach je Anker t;preis.
|
||||||
|
// dreieck (3 Punkte) → OBJ_TRIANGLE · rechteck (2) →
|
||||||
|
// OBJ_RECTANGLE · ellipse (3) → OBJ_ELLIPSE · dreieck2 (5) →
|
||||||
|
// ZWEI Dreiecke, weil OBJ_TRIANGLE nur drei Punkte kennt.
|
||||||
|
// ⚠ Aeltere CSV ohne Geometrie faellt still auf "nur Linien"
|
||||||
|
// zurueck — der Indikator bleibt damit zu beiden Staenden
|
||||||
|
// vertraeglich.
|
||||||
|
if(k >= 9)
|
||||||
|
{
|
||||||
|
string form = p[6];
|
||||||
|
int need = 3;
|
||||||
|
if(form == "rechteck") need = 2;
|
||||||
|
else if(form == "dreieck2") need = 5;
|
||||||
|
if(k >= 7 + 2 * need)
|
||||||
|
{
|
||||||
|
datetime at[5]; double ap[5];
|
||||||
|
bool gut = true;
|
||||||
|
for(int q = 0; q < need; q++)
|
||||||
|
{
|
||||||
|
at[q] = (datetime)StringToInteger(p[7 + 2 * q]);
|
||||||
|
ap[q] = StringToDouble(p[8 + 2 * q]);
|
||||||
|
if(at[q] <= 0 || ap[q] <= 0) gut = false;
|
||||||
|
}
|
||||||
|
if(gut)
|
||||||
|
{
|
||||||
|
if(form == "rechteck")
|
||||||
|
DrawMusterForm(PFX + "MUST_F0", OBJ_RECTANGLE, at, ap, 2);
|
||||||
|
else if(form == "ellipse")
|
||||||
|
DrawMusterForm(PFX + "MUST_F0", OBJ_ELLIPSE, at, ap, 3);
|
||||||
|
else if(form == "dreieck")
|
||||||
|
DrawMusterForm(PFX + "MUST_F0", OBJ_TRIANGLE, at, ap, 3);
|
||||||
|
else if(form == "dreieck2")
|
||||||
|
{
|
||||||
|
// SKS / Dreifach-Top: fuenf Swings. Die beiden Dreiecke
|
||||||
|
// (Schulter..Kopf und Kopf..Schulter) kacheln genau die
|
||||||
|
// Silhouette — ein Dreieck allein koennte sie nicht fassen.
|
||||||
|
datetime a1[3], a2[3]; double b1[3], b2[3];
|
||||||
|
for(int q = 0; q < 3; q++)
|
||||||
|
{
|
||||||
|
a1[q] = at[q]; b1[q] = ap[q];
|
||||||
|
a2[q] = at[q + 2]; b2[q] = ap[q + 2];
|
||||||
|
}
|
||||||
|
DrawMusterForm(PFX + "MUST_F0", OBJ_TRIANGLE, a1, b1, 3);
|
||||||
|
DrawMusterForm(PFX + "MUST_F1", OBJ_TRIANGLE, a2, b2, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(typ == "RZ" || typ == "SZ")
|
if(typ == "RZ" || typ == "SZ")
|
||||||
|
|||||||
Reference in New Issue
Block a user