Files
AH-Oil-Trader/core/hl_walls.py
T
Axel HocksandClaude Opus 4.8 06b37a1474 Liquiditaets-Waende: Richtungs-Pfeil + pinke Liquiditaets-Trendlinie (v1.13)
User-Wunsch: "Kennzeiche die Liquiditaetslinie mit einem Pfeil in welche richtung
die linie den Kurs treibt. Zeichne mir eine Trendlnie in pink im mt5 auf basis
der liquiditaet ein".

(a) Pfeil je Wand in Wirkrichtung (Lesart "die Wand haelt": Nachfrage stuetzt hoch,
    Angebot deckelt runter); groessere Wand dicker + "<<". CSV-Format erweitert:
    LQ;<B|A>;preis;size;<U|D>;<1|0>.
    WICHTIG: Pfeilrichtung ist INTERPRETATION, nicht gemessen -- die Gegenthese
    ("Liquidity Grab", Kurs laeuft ZUR Wand) ist genauso verbreitet. Klaert
    analyze_bookflow.py Frage 3.

(b) Pinke Liquiditaets-Trendlinie LT;t1;p1;t2;p2;<U|D>: Regression ueber den
    VOLUMENGEWICHTETEN Wand-Schwerpunkt der letzten 60 min. Zeigt, wohin das
    Gewicht der RUHENDEN Orders wandert -- nicht der gehandelte Kurs.
    Zeiten im Bot in Broker-Zeit umgerechnet, Preise basis-korrigiert.

HL /api/walls liefert jetzt arrow_bid/arrow_ask/dominant/trend.
Verifiziert: LQ;B;84.182;2441;U;1 / LQ;A;84.223;2441;D;0 /
LT;1785427175;84.135;1785430664;83.978;D in sr_levels.csv. Indikator kompiliert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 15:58:50 +02:00

91 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""core/hl_walls.py — ECHTE Liquiditäts-Wände von Hyperliquid für den MT5-Chart.
Holt vom HL-Dashboard (Port 8001, `GET /api/walls`) das größte L2-Orderbuch-Level je
Seite — **basis-korrigiert auf das Pepperstone-Preisniveau** — und stellt es dem
Level-Export (`engine._write_levels_file` → `sr_levels.csv` → `SR_Levels.mq5`) bereit.
WARUM (User-Wunsch 2026-07-30): Alle S/R-Linien im Projekt sind aus **Pivots
geschätzt** („wo war mal ein Docht"). Das hier ist die einzige Quelle mit
**tatsächlich ruhenden Orders** — Pepperstone ist Market Maker und liefert kein
Orderbuch, Hyperliquid schon (20 Levels je Seite).
⚠ Zwei Dinge im Blick behalten:
1. **Basis-Differenz**: HL `xyz:CL` notiert ~0,45 $ unter dem CFD (anderer
Kontrakt/Contango). Die Umrechnung passiert SERVERSEITIG im HL-Projekt
(Median über die letzten 60 Snapshots) — hier kommt schon `bid_mt5`/`ask_mt5`
an. Fehlt die Basis (zu wenige Snapshots), wird NICHT gezeichnet.
2. **Anzeige, KEIN Signal.** Ob HL-Orderbuch-Signale auf den CFD übertragbar sind,
ist eine offene Frage und wird gerade gemessen (`analyze_bookflow.py` im
HL-Projekt). Bis dahin fließt hier nichts in Empfehlung/Trade ein.
Fail-safe: kurzer Timeout, Ergebnis gecacht; ist der HL-Server aus, liefert
`walls()` einfach None und der Chart bleibt unverändert.
"""
from __future__ import annotations
import json
import threading
import time
import urllib.request
from core.logger import get_logger
log = get_logger("hlwalls")
_TIMEOUT_S = 2.0 # der MT5-Loop darf nicht am HTTP hängen
_TTL_S = 10.0 # Cache — die Wände wandern langsamer als der Export-Takt (~5 s)
_MAX_AGE_S = 60.0 # älter = HL-Feed steht → nicht mehr zeichnen
class HLWalls:
def __init__(self, url: str = "http://127.0.0.1:8001/api/walls",
enabled: bool = False):
self.url = url
self.enabled = bool(enabled)
self._lock = threading.Lock()
self._cache: dict | None = None
self._cache_ts = 0.0
self._fail_logged = False
def walls(self) -> dict | None:
"""{'bid','bid_sz','ask','ask_sz','basis','imb5'} auf MT5-Preisniveau —
oder None (aus / HL nicht erreichbar / Basis unbekannt / Daten zu alt)."""
if not self.enabled:
return None
now = time.time()
with self._lock:
if self._cache is not None and now - self._cache_ts < _TTL_S:
return self._cache
data = None
try:
with urllib.request.urlopen(self.url, timeout=_TIMEOUT_S) as r:
d = json.loads(r.read().decode())
if d.get("ok") and d.get("bid_mt5") and d.get("ask_mt5"):
# Feed-Alter prüfen: ein stehengebliebenes Buch darf nicht als
# aktuelle Liquidität gezeichnet werden.
age = now - float(d.get("ts") or 0)
if age <= _MAX_AGE_S:
data = {"bid": float(d["bid_mt5"]), "ask": float(d["ask_mt5"]),
"bid_sz": float(d.get("bid_sz") or 0),
"ask_sz": float(d.get("ask_sz") or 0),
"basis": d.get("basis"), "imb5": d.get("imb5"),
# Wirkrichtung je Wand (Pfeil im Chart) + größere Wand.
# ⚠ Lesart „die Wand hält" — INTERPRETATION, nicht gemessen.
"arrow_bid": d.get("arrow_bid") or "up",
"arrow_ask": d.get("arrow_ask") or "down",
"dominant": d.get("dominant"),
# Liquiditäts-Trendlinie (Regression über den volumen-
# gewichteten Wand-Schwerpunkt): {t1,p1,t2,p2,dir,slope_per_h}
# — Zeiten sind LOKALE Epoch, der Aufrufer rechnet sie in
# Broker-Zeit um (MT5-Charts brauchen Broker-Zeit).
"trend": d.get("trend")}
self._fail_logged = False
except Exception as e:
if not self._fail_logged: # nur 1× melden, nicht jeden Tick
log.info(f"HL-Wände nicht abrufbar ({e}) — Chart bleibt ohne "
f"Liquiditätslinien (HL-Dashboard auf 8001 läuft nicht?)")
self._fail_logged = True
with self._lock:
self._cache = data
self._cache_ts = now
return data