Hyperliquid-Kurs neben dem Broker-Kurs + G/V-Schaetzung bei geschlossenem Markt

User: "wenn Pepperstone closed ist trotzdem Kurs und Liquiditaet von
Hyperliquid einbinden" -> nachgeschaerft zu "blende den HL-Kurs NEBEN den
Pepperstone-Kurs ein" (ehrlicher als ein stiller Tausch) -> plus "bei
geschlossenem Markt auch den G/V mit HL berechnen".

Snapshot: hl_live {mid_mt5, hl_mid, basis, age_s, bid/ask, bid_sz/ask_sz,
imb5, trend, slope_per_h, vs_mt5} - IMMER befuellt. mid_mt5 = HL-Mid +
gemessene Basis, also direkt mit dem Broker-Kurs vergleichbar. Dazu
market_closed, tick_age_s, pnl_hl.
core/hl_walls.py liefert jetzt zusaetzlich hl_mid/mid_mt5/age_s.

Dashboard v=129: eigene Header-Box "HL" neben KURS mit Tooltip (Rohkurs,
Basis, Alter, Abweichung). Bei geschlossenem Markt: Label "KURS · ZU",
Session-Zeile "MARKT ZU", und das G/V wechselt auf die HL-Schaetzung, mit
"≈" markiert.

MT5 v1.34: HL;<mt5_aequiv>;<alter>;<bid>;<ask>;<U|D|-> -> bernsteinfarbenes
Label unter Kurs und G/V (InpShowHL/InpHLColor).

DREI SACKGASSEN dokumentiert, damit sie niemand wiederholt:
1) tick_local_ts ist die ABHOLZEIT, nicht das Tick-Alter.
2) tick_server_ts minus _broker_offset_s() ist ZIRKULAER - die
   Offset-Funktion leitet den Versatz selbst aus dem letzten Tick ab und
   misst bei geschlossenem Markt die Veraltung (-7,41 h statt +3 h); das
   Alter hebt sich auf (-347 s).
3) pnl / Kursbewegung als EUR-je-Punkt ergab 155 statt ~86, weil
   trader.pnl den Wochenend-Swap enthaelt.

Verwendet wird stattdessen: Markt zu = der Kurs hat sich seit 180 s nicht
BEWEGT (_last_bid/_last_bid_move_ts). Und der G/V nutzt die vorhandene,
korrekte trader.live_pnl(bid, ask) mit dem HL-Kurs +- halbem Spread.

Live verifiziert: market_closed=True nach 198 s, Broker 86.333 eingefroren,
HL 86.349 (7 s alt), Broker-P&L -15,02 -> HL-Schaetzung -14,37 EUR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-01 09:31:01 +02:00
co-authored by Claude Opus 5
parent 35f9b567c8
commit 7427c36922
7 changed files with 264 additions and 9 deletions
+42
View File
@@ -2139,6 +2139,48 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
+ Chart-`fontSize` in `app.js`. Bei künftigen globalen Font-Änderungen die + Chart-`fontSize` in `app.js`. Bei künftigen globalen Font-Änderungen die
Shorthand nicht vergessen. Shorthand nicht vergessen.
## Hyperliquid-Kurs neben dem Broker-Kurs (2026-08-01)
**User-Wunsch:** „wenn Pepperstone geschlossen ist trotzdem den aktuellen Kurs und die
Liquidität von Hyperliquid einbinden" → nachgeschärft zu „blende den HL-Kurs **neben**
den Pepperstone-Kurs ein" (ehrlicher: man sieht die Abweichung, statt dass still
getauscht wird) → plus „bei geschlossenem Markt auch den **G/V** mit HL berechnen".
- **Snapshot:** `hl_live {mid_mt5, hl_mid, basis, age_s, bid, ask, bid_sz, ask_sz,
imb5, trend, slope_per_h, vs_mt5}` — IMMER befüllt, nicht nur am Wochenende.
`mid_mt5` = HL-Mid + gemessene Basis (HL `xyz:CL` notiert wegen anderem Kontrakt
~0,45 $ unter dem CFD; die Basis kommt serverseitig aus dem HL-Projekt als Median
über 60 Snapshots) → direkt mit dem Broker-Kurs vergleichbar.
Dazu `market_closed`, `tick_age_s`, `pnl_hl`.
- **Dashboard (v=129):** eigene Header-Box **HL** neben KURS; Tooltip nennt HL-Rohkurs,
Basis, Alter und Abweichung. Bei geschlossenem Markt heißt das Kurs-Label
„KURS · ZU", die Session-Zeile zeigt „🔒 MARKT ZU", und das **G/V wechselt auf die
HL-Schätzung** (mit `` markiert, Tooltip nennt den eingefrorenen Broker-Wert).
- **MT5 (Indikator v1.34):** `HL;<mt5_aequiv>;<alter_s>;<bid>;<ask>;<U|D|->` →
bernsteinfarbenes Label unter Kurs und G/V (`InpShowHL`/`InpHLColor`).
⚠ **DREI Sackgassen bei der „Markt zu"-Erkennung — dokumentiert, damit sie niemand
wiederholt:**
1. **`tick_local_ts`** ist die lokale **ABHOLZEIT**, nicht das Tick-Alter — sie
erneuert sich bei jedem Abruf, auch wenn der Broker denselben alten Tick liefert.
2. **`tick_server_ts` `trader._broker_offset_s()`** ist **ZIRKULÄR**: die
Offset-Funktion leitet den Zeitzonen-Versatz selbst aus dem letzten Tick ab
(`off = tick.time now`). Bei geschlossenem Markt misst sie die Tick-Veraltung
statt der Zeitzone (real **7,41 h** statt +3 h) — das Alter hebt sich rechnerisch
auf (Ergebnis: **347 s**).
3. **`pnl / Kursbewegung`** als EUR-je-Punkt-Faktor ergab **155 statt ~86 EUR** je
1,00 und Lot, weil `trader.pnl = profit + swap` den über das Wochenende
aufgelaufenen Swap enthält.
**Verwendet wird stattdessen:** Markt zu = **der Kurs hat sich seit `_TICK_STALE_S`
(180 s) nicht BEWEGT** (`_last_bid`/`_last_bid_move_ts`) — kein Zeitzonen-, Kalender-
oder Feiertagswissen nötig, deckt Wochenende, Feiertag und Broker-Ausfall gleich ab.
Und der G/V nutzt die vorhandene, korrekte Umrechnung **`trader.live_pnl(bid, ask)`**
(`tick_size`/`tick_value` inkl. Swap und Währung), gefüttert mit dem HL-Kurs ± halbem
Spread. ⚠ Bleibt eine **Schätzung** (anderer Kontrakt, Montags-Open-Spread unbekannt) —
deshalb das `` in der Anzeige.
⚠ Nach einem Server-Neustart braucht die Erkennung 180 s, bis sie greift (der
Bewegungs-Zeitstempel startet beim ersten Snapshot).
## Web-API (server.py) ## Web-API (server.py)
`GET /api/snapshot` (inkl. `verdict`-Aggregat) `/api/health` `/api/logs` `/api/stats` `/api/news` `/api/bars?tf=&n=` (Charts, read-only) `/api/squeeze_monitor` (B4-Monitor, read-only, Engine-Cache 60 s) · `WS /ws` · `GET /api/snapshot` (inkl. `verdict`-Aggregat) `/api/health` `/api/logs` `/api/stats` `/api/news` `/api/bars?tf=&n=` (Charts, read-only) `/api/squeeze_monitor` (B4-Monitor, read-only, Engine-Cache 60 s) · `WS /ws` ·
`POST /api/order|auto|trail|emergency|takeprofit|sltp|srclose|srclose_min|autosqueeze|autosignal|auth/check`. `POST /api/order|auto|trail|emergency|takeprofit|sltp|srclose|srclose_min|autosqueeze|autosignal|auth/check`.
+104
View File
@@ -81,6 +81,9 @@ _SQUEEZE_REENTRY_COOLDOWN_S = 180.0 # nach JEDEM Close eines Trades (Notfall/SL
# gegen die Open→Instant-Close-Kaskade bei zu engem Stop # gegen die Open→Instant-Close-Kaskade bei zu engem Stop
# (real 2026-07-27 15:39: 3-€-Stop killte Entry #1 in 16 s, # (real 2026-07-27 15:39: 3-€-Stop killte Entry #1 in 16 s,
# Squeeze noch aktiv → sofortiger Re-Entry; 2026-07-28) # Squeeze noch aktiv → sofortiger Re-Entry; 2026-07-28)
_TICK_STALE_S = 180 # kein Tick seit X s → Markt gilt als geschlossen.
# Absichtlich tick-basiert statt kalenderbasiert: deckt
# Wochenende, Feiertage UND Broker-Ausfall mit einer Regel.
_TRADE_MARKS = 6 # so viele letzte Trades im MQL5-Chart markieren _TRADE_MARKS = 6 # so viele letzte Trades im MQL5-Chart markieren
# (Kerze umranden: Eröffnung hellgrün, Close dunkelgrün) # (Kerze umranden: Eröffnung hellgrün, Close dunkelgrün)
_STARTUP_GRACE_S = 60.0 # nach Bot-Start schließt der Bot 60 s lang KEINEN _STARTUP_GRACE_S = 60.0 # nach Bot-Start schließt der Bot 60 s lang KEINEN
@@ -321,6 +324,10 @@ class TradingEngine:
self._open_pos_dir = None # Richtung der aktuell offenen Position (LONG/SHORT) self._open_pos_dir = None # Richtung der aktuell offenen Position (LONG/SHORT)
self._pos_close_ts = 0.0 # Zeit + Richtung des letzten Positions-Close (JEDE self._pos_close_ts = 0.0 # Zeit + Richtung des letzten Positions-Close (JEDE
self._news_block_logged = None # Dedup für die News-Blackout-Logzeile self._news_block_logged = None # Dedup für die News-Blackout-Logzeile
# Markt-zu-Erkennung über die letzte KURSBEWEGUNG (s. `snapshot`) — die
# Tick-Zeitstempel taugen dafür nicht (Abholzeit bzw. zirkulärer Offset).
self._last_bid = None
self._last_bid_move_ts = 0.0
# Auto-Flip-Close (User-Wunsch 2026-07-31) — ⚠ GEMESSEN NEGATIV in beiden # Auto-Flip-Close (User-Wunsch 2026-07-31) — ⚠ GEMESSEN NEGATIV in beiden
# Hälften (`backtest_flipclose2.py`), s. `_check_flip_close`. Default-Schwelle # Hälften (`backtest_flipclose2.py`), s. `_check_flip_close`. Default-Schwelle
# 0,5×ATR = die mildeste der gemessenen Varianten. # 0,5×ATR = die mildeste der gemessenen Varianten.
@@ -2367,6 +2374,20 @@ class TradingEngine:
f"Konsens {_b:+.2f}") f"Konsens {_b:+.2f}")
except Exception: except Exception:
pass pass
# ── HYPERLIQUID-ERSATZKURS bei geschlossenem Markt (User 2026-08-01):
# HL;<mt5_aequivalent>;<alter_s>;<bid>;<ask>;<trend U|D|-> — der Indikator
# zeigt ihn UNTER dem (eingefrorenen) MT5-Kurs, sobald kein Tick mehr
# kommt. HL (`xyz:CL`) handelt 24/7, Pepperstone nicht; ohne das sieht man
# am Wochenende einen Freitags-Kurs und merkt es nicht.
try:
_w = self.hl_walls.walls()
if _w and _w.get("mid_mt5") is not None:
_tr = (_w.get("trend") or {}).get("dir")
lines.append(f"HL;{_w['mid_mt5']:.3f};{float(_w.get('age_s') or 0):.0f};"
f"{_w.get('bid')};{_w.get('ask')};"
f"{'U' if _tr == 'up' else 'D' if _tr == 'down' else '-'}")
except Exception:
pass
# G/V der offenen Position, direkt unter dem Kurs (User-Wunsch 2026-07-30): # G/V der offenen Position, direkt unter dem Kurs (User-Wunsch 2026-07-30):
# PL;wert;waehrung. **NETTO** wie im Dashboard — bei Gewinn abzüglich der # PL;wert;waehrung. **NETTO** wie im Dashboard — bei Gewinn abzüglich der
# WHT-Quellensteuer, die der Broker einbehält (`[trading] wht_pct`); bei # WHT-Quellensteuer, die der Broker einbehält (`[trading] wht_pct`); bei
@@ -2999,6 +3020,74 @@ class TradingEngine:
stop_approach = self._stop_approach_hint(market, position, wave_snap) stop_approach = self._stop_approach_hint(market, position, wave_snap)
# einmal holen — Verdict-Stimme UND Snapshot-Feld nutzen dasselbe Objekt # einmal holen — Verdict-Stimme UND Snapshot-Feld nutzen dasselbe Objekt
_pat_snap = self.patterns.snapshot() _pat_snap = self.patterns.snapshot()
# ── Marktstatus + Hyperliquid-Kurs (User 2026-08-01) ─────────────────
# ⚠ ZWEI Sackgassen bei der Markt-zu-Erkennung, beide verworfen:
# (1) `tick_local_ts` ist die lokale ABHOLZEIT — erneuert sich bei jedem
# Abruf, auch wenn der Broker denselben alten Tick liefert.
# (2) `tick_server_ts` minus `trader._broker_offset_s()` ist ZIRKULÄR: die
# Offset-Funktion leitet den Zeitzonen-Versatz selbst aus dem letzten
# Tick ab (`off = tick.time - now`). Bei geschlossenem Markt misst sie
# damit die Tick-Veraltung statt der Zeitzone (real 7,41 h statt +3 h)
# und das Alter hebt sich rechnerisch auf (Ergebnis: 347 s).
# Verwendet wird daher der direkte Beleg: **wann hat sich der Kurs zuletzt
# BEWEGT?** Kein Zeitzonen-, Kalender- oder Feiertagswissen nötig.
_now = time.time()
try:
_b = (market or {}).get("bid")
if _b is not None:
if self._last_bid is None or abs(float(_b) - self._last_bid) > 1e-9:
self._last_bid = float(_b)
self._last_bid_move_ts = _now
except Exception:
pass
_tick_age = (round(_now - self._last_bid_move_ts)
if self._last_bid_move_ts else None)
_mkt_closed = bool(_tick_age is not None and _tick_age > _TICK_STALE_S)
# HL-Kurs IMMER mitliefern (User: „blende den Hyperliquid-Kurs NEBEN den
# Pepperstone-Kurs ein") — nicht nur bei geschlossenem Markt. So sieht man
# laufend die Abweichung; am Wochenende ist es der einzige lebende Kurs.
_hl_live = None
try:
_w = self.hl_walls.walls()
if _w and _w.get("mid_mt5") is not None:
_hl_live = {
"mid_mt5": _w["mid_mt5"], "hl_mid": _w.get("hl_mid"),
"basis": _w.get("basis"), "age_s": _w.get("age_s"),
"bid": _w.get("bid"), "ask": _w.get("ask"),
"bid_sz": _w.get("bid_sz"), "ask_sz": _w.get("ask_sz"),
"imb5": _w.get("imb5"),
"trend": (_w.get("trend") or {}).get("dir"),
"slope_per_h": (_w.get("trend") or {}).get("slope_per_h"),
"vs_mt5": (round(_w["mid_mt5"] - float(market["bid"]), 3)
if (market or {}).get("bid") else None),
}
except Exception:
pass
# ── G/V mit HL-Kurs, wenn der Broker eingefroren ist (User 2026-08-01) ──
# Bei geschlossenem Markt steht `position.pnl` still. Die Schätzung setzt den
# HL-Kurs (basis-korrigiert, also MT5-Niveau) in `trader.live_pnl()` ein — die
# BEREITS VORHANDENE, korrekte Umrechnung über `tick_size`/`tick_value` inkl.
# Swap und Währungsumrechnung.
# ⚠ Erster Versuch leitete den EUR-je-Punkt-Faktor aus `pnl / Kursbewegung`
# ab — das ergab 155 statt ~86 EUR je 1,00 und Lot, weil `pnl` den über das
# Wochenende aufgelaufenen SWAP enthält. Eine Kennzahl aus einer anderen
# Kennzahl zurückzurechnen ist hier schlicht falsch, wenn zusätzliche Terme
# drinstecken.
# ⚠ Bleibt eine SCHÄTZUNG: HL ist ein anderer Kontrakt (Basis herausgerechnet,
# aber nicht exakt), und der Spread am Montags-Open ist unbekannt.
_pnl_hl = None
try:
if _mkt_closed and _hl_live and position and position.get("ticket"):
_mid = float(_hl_live["mid_mt5"])
_sp = float((market or {}).get("spread") or 0.0)
_v = self.trader.live_pnl(_mid - _sp / 2.0, _mid + _sp / 2.0)
if _v is not None:
_pnl_hl = round(_v, 2)
except Exception:
pass
snap = { snap = {
"ts": time.time(), "ts": time.time(),
"connected": self._connected, "connected": self._connected,
@@ -3085,6 +3174,21 @@ class TradingEngine:
# Wirtschaftskalender: {blackout, next, enabled, n} — Anzeige + Grund, # Wirtschaftskalender: {blackout, next, enabled, n} — Anzeige + Grund,
# warum der Bot gerade keine autonome Order eröffnet. # warum der Bot gerade keine autonome Order eröffnet.
"calendar": self.calendar.snapshot(), "calendar": self.calendar.snapshot(),
# ── MARKT ZU + HYPERLIQUID-ERSATZKURS (User-Wunsch 2026-08-01) ──────
# Pepperstone handelt WTI nicht am Wochenende; der Snapshot zeigt dann
# den EINGEFRORENEN Freitags-Kurs, ohne dass man es sieht (der grüne
# Punkt im Header ist die VERBINDUNG, nicht der Marktstatus). Hyperliquid
# (`xyz:CL`) läuft dagegen 24/7 weiter.
# `market_closed` wird NICHT aus dem Kalender abgeleitet, sondern aus dem
# ALTER DES LETZTEN TICKS — das deckt Wochenende, Feiertage und
# Broker-Ausfälle mit derselben Regel ab, ohne Kalenderpflege.
# `hl_live.mid_mt5` = HL-Mid + gemessene Basis (HL notiert ~0,45 $ unter
# dem CFD, anderer Kontrakt) → direkt mit dem MT5-Kurs vergleichbar.
"market_closed": _mkt_closed,
"tick_age_s": _tick_age,
"hl_live": _hl_live,
# G/V-Schaetzung auf HL-Basis, nur bei geschlossenem Markt (sonst None)
"pnl_hl": _pnl_hl,
} }
# ── Entry-Checkliste je Richtung (User-Vorgabe 2026-07-30: „blende einen # ── Entry-Checkliste je Richtung (User-Vorgabe 2026-07-30: „blende einen
# Hinweis ein, wenn die Checkliste gegen meine Eröffnung ist"). Wird im # Hinweis ein, wenn die Checkliste gegen meine Eröffnung ist"). Wird im
+15 -1
View File
@@ -79,7 +79,21 @@ class HLWalls:
# gewichteten Wand-Schwerpunkt): {t1,p1,t2,p2,dir,slope_per_h} # gewichteten Wand-Schwerpunkt): {t1,p1,t2,p2,dir,slope_per_h}
# — Zeiten sind LOKALE Epoch, der Aufrufer rechnet sie in # — Zeiten sind LOKALE Epoch, der Aufrufer rechnet sie in
# Broker-Zeit um (MT5-Charts brauchen Broker-Zeit). # Broker-Zeit um (MT5-Charts brauchen Broker-Zeit).
"trend": d.get("trend")} "trend": d.get("trend"),
# ── Ergänzt 2026-08-01 (User: „blende den Hyperliquid-
# Kurs neben den Pepperstone-Kurs ein"): der HL-MITTELKURS
# auf MT5-Niveau. HL `xyz:CL` notiert wegen anderem
# Kontrakt/Contango ~0,45 $ unter dem CFD — `basis` ist die
# serverseitig gemessene Differenz (Median über 60
# Snapshots), `mid_mt5` also direkt mit dem Broker-Kurs
# vergleichbar. Nützlich vor allem am Wochenende: HL
# handelt 24/7, Pepperstone nicht.
"hl_mid": (float(d["hl_mid"])
if d.get("hl_mid") is not None else None),
"mid_mt5": (round(float(d["hl_mid"])
+ float(d.get("basis") or 0.0), 3)
if d.get("hl_mid") is not None else None),
"age_s": round(age, 1)}
self._fail_logged = False self._fail_logged = False
except Exception as e: except Exception as e:
if not self._fail_logged: # nur 1× melden, nicht jeden Tick if not self._fail_logged: # nur 1× melden, nicht jeden Tick
+41 -1
View File
@@ -12,7 +12,11 @@
//| 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.33" #property version "1.34"
// v1.34 (2026-08-01): HYPERLIQUID-KURS (HL;...) unter Kurs und G/V oben rechts,
// bernstein. HL handelt 24/7, Pepperstone nicht - am Wochenende der einzige
// lebende Kurs; die Basis (~0,45 $ Kontrakt-Differenz) ist herausgerechnet,
// der Wert also direkt mit dem Broker-Kurs vergleichbar. InpShowHL/InpHLColor.
// v1.33 (2026-07-31): Konsens-Pfeil (K) per Default AUS + Pfeile kuerzer (8 statt // v1.33 (2026-07-31): Konsens-Pfeil (K) per Default AUS + Pfeile kuerzer (8 statt
// 14 Bars). Grund: L und K starten am selben Punkt und zeigten oft in // 14 Bars). Grund: L und K starten am selben Punkt und zeigten oft in
// ENTGEGENGESETZTE Richtungen - zwei divergierende Linien aus einem Punkt // ENTGEGENGESETZTE Richtungen - zwei divergierende Linien aus einem Punkt
@@ -185,6 +189,8 @@ input color InpArrConsensus = C'139,148,158'; // Konsens der Module (NICHT kali
input bool InpShowConsensus = false; // Konsens-Pfeil zusaetzlich zeichnen input bool InpShowConsensus = false; // Konsens-Pfeil zusaetzlich zeichnen
input int InpArrBars = 8; // Pfeil-Laenge in Bars (kuerzer = Spitze sichtbar) input int InpArrBars = 8; // Pfeil-Laenge in Bars (kuerzer = Spitze sichtbar)
input color InpConeColor = C'139,148,158'; // Kegel-Farbe (neutral grau - bewusst KEINE Richtungsfarbe) input color InpConeColor = C'139,148,158'; // Kegel-Farbe (neutral grau - bewusst KEINE Richtungsfarbe)
input bool InpShowHL = true; // Hyperliquid-Kurs unter dem Broker-Kurs
input color InpHLColor = C'232,160,0'; // HL-Kurs (bernstein, klar unterscheidbar)
input bool InpShowPnL = true; // G/V der offenen Position unter dem Kurs input bool InpShowPnL = true; // G/V der offenen Position unter dem Kurs
input color InpPnLUpColor = C'0,255,127'; // G/V im Plus (neongruen) input color InpPnLUpColor = C'0,255,127'; // G/V im Plus (neongruen)
input color InpPnLDownColor = C'255,69,0'; // G/V im Minus (rot) input color InpPnLDownColor = C'255,69,0'; // G/V im Minus (rot)
@@ -798,6 +804,40 @@ void Redraw()
ObjectSetString(0, atn, OBJPROP_TEXT, " " + a_txt); ObjectSetString(0, atn, OBJPROP_TEXT, " " + a_txt);
continue; continue;
} }
// HYPERLIQUID-KURS unter dem Broker-Kurs: HL;<mt5_aequiv>;<alter_s>;<bid>;<ask>;<U|D|->
// HL (`xyz:CL`) handelt 24/7, Pepperstone nicht - am Wochenende der einzige
// lebende Kurs. Bereits basis-korrigiert, also direkt vergleichbar.
if(typ == "HL")
{
if(k < 6) continue;
if(!InpShowHL) continue;
double hlp = StringToDouble(p[1]);
if(hlp <= 0) continue;
int hage = (int)StringToInteger(p[2]);
string htr = p[5];
string hn = PFX + "HLPX";
if(ObjectFind(0, hn) < 0)
{
ObjectCreate(0, hn, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, hn, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, hn, OBJPROP_XDISTANCE, 12);
// unter Kurs (14) und G/V (14+PriceSize+6) einreihen
ObjectSetInteger(0, hn, OBJPROP_YDISTANCE, 14 + InpPriceSize + 6 + InpPriceSize - 4);
ObjectSetInteger(0, hn, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetInteger(0, hn, OBJPROP_SELECTABLE, false);
ObjectSetString (0, hn, OBJPROP_FONT, "Arial");
}
ObjectSetInteger(0, hn, OBJPROP_FONTSIZE, (int)MathMax(10, InpPriceSize - 7));
ObjectSetInteger(0, hn, OBJPROP_COLOR, InpHLColor);
ObjectSetString (0, hn, OBJPROP_TEXT,
"HL " + DoubleToString(hlp, (int)_Digits)
+ (htr == "U" ? " ^" : htr == "D" ? " v" : ""));
ObjectSetString (0, hn, OBJPROP_TOOLTIP,
"Hyperliquid xyz:CL, basis-korrigiert auf MT5-Niveau - "
+ IntegerToString(hage) + " s alt. Waende "
+ p[3] + " / " + p[4]);
continue;
}
// AKTUELLER KURS oben rechts, fett (User-Wunsch): PX;bid // AKTUELLER KURS oben rechts, fett (User-Wunsch): PX;bid
if(typ == "PX") if(typ == "PX")
{ {
+50 -4
View File
@@ -429,9 +429,15 @@ function render(d) {
const storm = (d.news_storm || {}).level; const storm = (d.news_storm || {}).level;
if (storm === "storm") stxt = `📰 NEWS-STURM · ${stxt}`; if (storm === "storm") stxt = `📰 NEWS-STURM · ${stxt}`;
else if (storm === "elevated") stxt = `📰 viele News · ${stxt}`; else if (storm === "elevated") stxt = `📰 viele News · ${stxt}`;
// Marktstatus VOR die Session-Zeile: bei geschlossenem Markt ist die Phase
// ("Wochenende") allein zu leise — der eingefrorene Kurs sah live aus.
if (d.market_closed) {
stxt = `🔒 MARKT ZU · ${stxt}`; // HL-Kurs steht jetzt im Header
}
$("session").textContent = stxt; $("session").textContent = stxt;
$("session").className = "session-line " + $("session").className = "session-line " +
(storm === "storm" ? "warn" (d.market_closed ? "warn"
: storm === "storm" ? "warn"
: (_h === 21 || _h === 22) ? "warn" : (_h === 21 || _h === 22) ? "warn"
: ses.just_opened ? "warn" : (ses.active && ses.active.length) ? "ok" : "dim"); : ses.just_opened ? "warn" : (ses.active && ses.active.length) ? "ok" : "dim");
@@ -464,16 +470,56 @@ function render(d) {
} }
// ── Header: Kurs (färbt sich nahe S/R) + G/V der offenen Position (netto) ── // ── Header: Kurs (färbt sich nahe S/R) + G/V der offenen Position (netto) ──
// ⚠ MARKT ZU (User 2026-08-01): Pepperstone handelt WTI nicht am Wochenende, der
// Kurs friert dann auf dem Freitags-Stand ein — sichtbar war das NICHT (der grüne
// Punkt im Header ist die VERBINDUNG, nicht der Marktstatus). Hyperliquid läuft
// 24/7 weiter, also zeigen wir dessen Kurs (basis-korrigiert = MT5-vergleichbar)
// statt des eingefrorenen — deutlich als „HL" gekennzeichnet, damit niemand ihn
// für einen Broker-Kurs hält.
// ⚠ Der BROKER-Kurs bleibt der Hauptkurs (erster Entwurf ersetzte ihn bei
// geschlossenem Markt durch den HL-Kurs — der User wollte stattdessen BEIDE
// nebeneinander, was ehrlicher ist: man sieht die Abweichung statt einer
// stillen Vertauschung).
$("hdr-price").textContent = m.bid != null ? fmt(m.bid) : "—"; $("hdr-price").textContent = m.bid != null ? fmt(m.bid) : "—";
$("hdr-price").className = priceCls; $("hdr-price").className = priceCls;
$("hdr-price-lbl").textContent = d.market_closed ? "KURS · ZU" : "KURS";
$("hdr-price-lbl").title = d.market_closed
? `Pepperstone geschlossen — letzter Tick vor ${Math.round((d.tick_age_s || 0) / 60)} min`
: "";
// Hyperliquid daneben: basis-korrigiert (= MT5-Niveau), mit Abweichung im Tooltip.
const hl = d.hl_live || null;
const hlEl = $("hdr-hl");
if (hl && hl.mid_mt5 != null) {
const arr = hl.trend === "up" ? "▲" : hl.trend === "down" ? "▼" : "";
hlEl.textContent = fmt(hl.mid_mt5) + (arr ? " " + arr : "");
const dv = hl.vs_mt5;
hlEl.className = d.market_closed ? "hl-price"
: (dv != null && Math.abs(dv) >= 0.15) ? "hl-price" : "";
hlEl.title = `Hyperliquid xyz:CL ${fmt(hl.hl_mid)} + gemessene Basis `
+ `${hl.basis >= 0 ? "+" : ""}${fmt(hl.basis, 3)} = ${fmt(hl.mid_mt5)} · `
+ `${fmt(hl.age_s, 0)} s alt`
+ (dv != null ? ` · ggü. Broker ${dv >= 0 ? "+" : ""}${fmt(dv, 3)}` : "");
} else {
hlEl.textContent = "—"; hlEl.className = ""; hlEl.title = "";
}
const hpos = d.position || {}; const hpos = d.position || {};
if (hpos.ticket) { if (hpos.ticket) {
const wht = d.wht_pct || 0; const wht = d.wht_pct || 0;
const raw = hpos.pnl || 0; // ⚠ Bei geschlossenem Markt steht der Broker-P&L still (der Kurs ist eingefroren).
// Dann die HL-SCHÄTZUNG zeigen (User 2026-08-01) — klar als Schätzung markiert:
// Swap/Kommission der Wochenendtage fehlen und HL ist ein anderer Kontrakt.
const useHl = d.market_closed && d.pnl_hl != null;
const raw = useHl ? d.pnl_hl : (hpos.pnl || 0);
const netHdr = raw > 0 ? raw * (1 - wht / 100) : raw; const netHdr = raw > 0 ? raw * (1 - wht / 100) : raw;
$("hdr-pnl").textContent = (netHdr >= 0 ? "+" : "") + cs + fmt(netHdr, 2); $("hdr-pnl").textContent = (useHl ? "≈" : "") + (netHdr >= 0 ? "+" : "") + cs + fmt(netHdr, 2);
$("hdr-pnl").className = netHdr > 0 ? "up" : netHdr < 0 ? "down" : ""; $("hdr-pnl").className = netHdr > 0 ? "up" : netHdr < 0 ? "down" : "";
} else { $("hdr-pnl").textContent = "—"; $("hdr-pnl").className = ""; } $("hdr-pnl").title = useHl
? `Schätzung auf Basis des Hyperliquid-Kurses — der Broker-Kurs ist eingefroren `
+ `(Broker-P&L ${fmt(hpos.pnl || 0, 2)} ${cs}). Ohne Swap/Kommission des Wochenendes.`
: "";
} else { $("hdr-pnl").textContent = "—"; $("hdr-pnl").className = ""; $("hdr-pnl").title = ""; }
// ── S/R-Annäherungs-Warnung (Position-Kachel) — NUR wenn kein reicherer // ── S/R-Annäherungs-Warnung (Position-Kachel) — NUR wenn kein reicherer
// Positions-Hint (pos-srhint) läuft, sonst doppeltes „nähert sich Widerstand". // Positions-Hint (pos-srhint) läuft, sonst doppeltes „nähert sich Widerstand".
+7 -3
View File
@@ -6,7 +6,7 @@
<meta name="theme-color" content="#0d1117"> <meta name="theme-color" content="#0d1117">
<title>Oil · MT5</title> <title>Oil · MT5</title>
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
<link rel="stylesheet" href="style.css?v=126"> <link rel="stylesheet" href="style.css?v=129">
</head> </head>
<body> <body>
<!-- Modul-Menü (ganz oben) --> <!-- Modul-Menü (ganz oben) -->
@@ -34,7 +34,11 @@
<div class="px"><label>BALANCE</label><span id="balance"></span></div> <div class="px"><label>BALANCE</label><span id="balance"></span></div>
<div class="px"><label>TAG P/L</label><span id="day-pl"></span></div> <div class="px"><label>TAG P/L</label><span id="day-pl"></span></div>
<div class="px"><label>EQUITY</label><span id="equity"></span></div> <div class="px"><label>EQUITY</label><span id="equity"></span></div>
<div class="px"><label>KURS</label><span id="hdr-price"></span></div> <div class="px"><label id="hdr-price-lbl">KURS</label><span id="hdr-price"></span></div>
<!-- Hyperliquid-Kurs NEBEN dem Broker-Kurs (User 2026-08-01). HL handelt 24/7,
Pepperstone nicht — am Wochenende der einzige lebende Kurs. Basis-korrigiert,
also direkt vergleichbar. -->
<div class="px" id="px-hl"><label>HL</label><span id="hdr-hl"></span></div>
<div class="px"><label>G/V</label><span id="hdr-pnl"></span></div> <div class="px"><label>G/V</label><span id="hdr-pnl"></span></div>
</div> </div>
</header> </header>
@@ -244,6 +248,6 @@
<div id="toast" class="toast hidden"></div> <div id="toast" class="toast hidden"></div>
<script src="lightweight-charts.standalone.production.js?v=114"></script> <script src="lightweight-charts.standalone.production.js?v=114"></script>
<script src="app.js?v=126"></script> <script src="app.js?v=129"></script>
</body> </body>
</html> </html>
+5
View File
@@ -484,3 +484,8 @@ main{padding-bottom:74px} /* Platz für die fixe Leiste */
.sqm-row b.up{ color:var(--up); } .sqm-row b.down{ color:var(--down); } .sqm-row b.up{ color:var(--up); } .sqm-row b.down{ color:var(--down); }
.sqm-exp{ font-size:15px; color:var(--dim); margin-top:6px; } .sqm-exp{ font-size:15px; color:var(--dim); margin-top:6px; }
.sqm-note{ font-size:16px; color:var(--dim); margin-top:8px; line-height:1.4; } .sqm-note{ font-size:16px; color:var(--dim); margin-top:8px; line-height:1.4; }
/* Kurs aus Hyperliquid (Markt bei Pepperstone geschlossen) - bewusst ANDERS
gefaerbt als der Broker-Kurs, damit man ihn nicht verwechselt. */
#hdr-price.hl-price{color:var(--accent)}
#hdr-price-lbl{letter-spacing:.3px}