Dokumentation Modul-04-Market-Regime (Regime-Engine, market_regime, E2E freigegeben) (Rain Ocampo, 20.08.2026)
This commit is contained in:
parent
cb207f95e9
commit
3cc710030c
1 changed files with 152 additions and 0 deletions
152
modul-04-market-regime.md
Normal file
152
modul-04-market-regime.md
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# Modul-04-Market-Regime — Betriebsdokumentation
|
||||
|
||||
> Erstellt: 20.08.2026 (Rain Ocampo) · Status: ✅ Freigegeben (E2E bestanden)
|
||||
|
||||
## Zweck
|
||||
Erster **Consumer** der Market-Data-Events von Modul-03. Pipeline:
|
||||
`MARKET_DATA_READY / MARKET_CANDLE_CLOSED (Modul-03) → Regime-Berechnung → PostgreSQL (market_regime) → MARKET_REGIME_READY`
|
||||
**Deterministische, regelbasierte Engine — bewusst OHNE KI/ML.**
|
||||
|
||||
## Container
|
||||
| Attribut | Wert |
|
||||
|----------|------|
|
||||
| Name | `Modul-04-Market-Regime` |
|
||||
| Image | `market-regime:1.0.0` (lokal gebaut) |
|
||||
| Port | **55004** — **NUR intern** (`expose`, nicht öffentlich) |
|
||||
| Netzwerk | `trading-modules` (bridge) |
|
||||
| Build-Context | `/opt/trading-modules/modul04-market-regime/` |
|
||||
| Restart | `unless-stopped` |
|
||||
| Healthcheck | ✅ `healthy` |
|
||||
|
||||
## Deployment
|
||||
```bash
|
||||
cd /opt/trading-modules
|
||||
docker compose build modul-04-market-regime
|
||||
docker compose up -d --no-deps --force-recreate modul-04-market-regime
|
||||
```
|
||||
|
||||
## Environment Variables (Compose)
|
||||
| Variable | Wert (Default) | Zweck |
|
||||
|----------|---------------|-------|
|
||||
| `PG_HOST` | `Modul-01-PostgreSQL` | Docker-interner Servicename |
|
||||
| `PG_PORT` | `5432` | intern (Host: 55432) |
|
||||
| `PG_USER/PASSWORD/DB` | `trading` | aus `.env`-Defaults |
|
||||
| `RABBITMQ_HOST` | `Modul-02-RabbitMQ` | Docker-interner Servicename |
|
||||
| `RABBITMQ_PORT` | `5672` | intern (Host: 55672) |
|
||||
| `RABBITMQ_USER/PASSWORD/VHOST` | `trading` | **vhost `trading`** |
|
||||
| `LOG_LEVEL` | `INFO` | Strukturiertes Logging |
|
||||
|
||||
Keine festen IPs — nur Docker-interne Hostnamen. Creds via Compose env + Defaults.
|
||||
|
||||
## Architektur
|
||||
```
|
||||
Modul-03 ──market.data.ready / market.data.candle.closed──▶ RegimeConsumer
|
||||
│ (bindet beide Routing-Keys)
|
||||
▼
|
||||
RegimeEngine (deterministisch)
|
||||
EMA / ADX / ATR / Slope / Preisstruktur
|
||||
│
|
||||
┌───────────┴───────────┐
|
||||
▼ ▼
|
||||
market_regime (PG) MARKET_REGIME_READY
|
||||
(16 Spalten) → market.regime.ready
|
||||
```
|
||||
|
||||
- **Consumer** (`app/consumer/consumer.py`): bindet `market.data.ready` + `market.data.candle.closed`; durable Queue `market-regime.input`; manuelles Ack; Reconnect mit Backoff; **schließt alte Verbindung beim Reconnect** (verhindert Consumer-Leak/Nachrichtenverlust).
|
||||
- **Engine** (`app/regime/engine.py`): deterministisch, ohne KI.
|
||||
- **Storage** (`app/storage/storage.py`): idempotent via partiellen Unique-Index.
|
||||
- **Publisher** (`app/publisher/publisher.py`): publiziert `MARKET_REGIME_READY` auf `market.regime` (Routing `market.regime.ready`).
|
||||
- **History-Client** (`app/marketdata/client.py`): liest OHLCV über interne FastAPI Modul-03 (`http://Modul-03-Market-Data:55003/history/{symbol}`).
|
||||
|
||||
## Regime-Engine (`app/regime/engine.py`)
|
||||
Deterministische Regel-Engine (Version `1.0.0`), 7 Regime:
|
||||
`TREND_UP, TREND_DOWN, RANGE, HIGH_VOLATILITY, LOW_VOLATILITY, TRANSITION, UNKNOWN`
|
||||
|
||||
**Indikatoren & Metriken:**
|
||||
| Indikator | Fenster/Param | Zweck |
|
||||
|-----------|---------------|-------|
|
||||
| EMA fast/slow | 10 / 30 | Trendrichtung (EMA-Flanken-Differenz) |
|
||||
| ADX | 14 | Trendstärke (≥20 = echter Trend) |
|
||||
| ATR | 14 | Volatilität (absolut + Ratio + Perzentil) |
|
||||
| Slope | 20 | normierte Steigung der Close-Linie |
|
||||
| Preisstruktur | — | higher_highs / lower_lows / range |
|
||||
|
||||
**Zentrale Schwellenwerte** (`app/config.py`, env-overridable):
|
||||
| Parameter | Default | Bedeutung |
|
||||
|-----------|---------|-----------|
|
||||
| `min_candles_required` | 30 | UNKNOWN, wenn weniger Daten |
|
||||
| `regime_lookback` | 60 | max. Kerzen für Berechnung |
|
||||
| `trend_min_ema_gap` | 0.02 | |EMA_fast-EMA_slow|/close ≥ → Trend |
|
||||
| `adx_trend_threshold` | 20.0 | ADX ≥ → echter Trend |
|
||||
| `slope_up/down_threshold` | 0.05 / -0.05 | normierte Steigung |
|
||||
| `range_atr_ratio` | 0.02 | ATR/close darunter = Range |
|
||||
| `atr_high_vol_multiplier` | 1.5 | ATR jetzt > hist_mean × → HIGH_VOL |
|
||||
| `atr_low_vol_multiplier` | 0.6 | ATR jetzt < hist_mean × → LOW_VOL |
|
||||
| `high_vol_atr_ratio` | 0.03 | ATR/close ≥ → starke Vol |
|
||||
| `low_vol_atr_ratio` | 0.008 | ATR/close ≤ → geringe Vol |
|
||||
| `slope_threshold` | 0.01 | |Slope| darunter = seitwärts |
|
||||
| `transition_min_events` | 3 | Events für TRANSITION |
|
||||
|
||||
## Datenbank (Modul-01-PostgreSQL)
|
||||
Tabelle `public.market_regime` (16 Spalten, eigene Tabelle — bestehende unangetastet):
|
||||
```sql
|
||||
symbol TEXT, asset_class TEXT, timeframe TEXT, provider TEXT,
|
||||
regime TEXT, confidence INTEGER (0-100),
|
||||
trend_strength DOUBLE PRECISION, volatility_state TEXT,
|
||||
timestamp TIMESTAMPTZ, indicators_json JSONB,
|
||||
candles_used INTEGER, version TEXT,
|
||||
source_event_id TEXT, correlation_id TEXT,
|
||||
data_ts TIMESTAMPTZ, data_ts_end TIMESTAMPTZ
|
||||
```
|
||||
- **Unique (partiell):** `uq_market_regime_src` auf `(symbol, timeframe, source_event_id)` **WHERE source_event_id IS NOT NULL** → Idempotenz.
|
||||
- Migration: `migrations/001_market_regime.sql` (idempotent, löscht nichts).
|
||||
|
||||
## RabbitMQ (Modul-02)
|
||||
| Exchange | Typ | Routing | Event |
|
||||
|----------|-----|---------|-------|
|
||||
| `market.data` | topic | `market.data.ready` (eingang) | MARKET_DATA_READY |
|
||||
| `market.data` | topic | `market.data.candle.closed` (eingang) | MARKET_CANDLE_CLOSED |
|
||||
| `market.regime` | topic | `market.regime.ready` (**ausgang**) | MARKET_REGIME_READY |
|
||||
|
||||
## Interne API
|
||||
| Endpoint | Zweck |
|
||||
|----------|-------|
|
||||
| `GET /health` | Liveness (200 immer) + Komponentenstatus im Body |
|
||||
| `GET /health/ready` | Readiness (503 wenn PG/RabbitMQ/Modul-03 down) |
|
||||
| `GET /regime/{symbol}` | Regime-Einträge abfragen |
|
||||
| `GET /regime/latest/{symbol}` | Letztes Regime eines Symbols |
|
||||
|
||||
## End-to-End-Test (20.08.2026, final, nach Rebuild) ✅
|
||||
Kette verifiziert: Modul-03 Ingest → `market.data.ready` → Modul-04 Consumer → RegimeEngine → `market_regime` → `MARKET_REGIME_READY` auf `market.regime.ready`.
|
||||
|
||||
| Fall | Regime | Conf | candles | version | Event | DB |
|
||||
|------|--------|------|---------|---------|-------|----|
|
||||
| M4TREND_UP (40) | TREND_UP | 100 | 40 | 1.0.0 | genau 1 | ✅ |
|
||||
| M4TREND_DN (40) | TREND_DOWN | 100 | 40 | 1.0.0 | genau 1 | ✅ |
|
||||
| M4RANGE (40) | LOW_VOLATILITY (Range) | 60 | 40 | 1.0.0 | genau 1 | ✅ |
|
||||
| M4HIGHVOL (40) | HIGH_VOLATILITY | 75 | 40 | 1.0.0 | genau 1 | ✅ |
|
||||
| M4UNKNOWN (5) | UNKNOWN | 20 | 5 | 1.0.0 | genau 1 | ✅ |
|
||||
| M4IDEMPOT (40) | TREND_UP | 100 | 40 | 1.0.0 | genau 1 | ✅ |
|
||||
|
||||
**Idempotenz:** dasselbe Quell-Event (`source_event_id`) erneut → **kein zweiter Datensatz**, kein Doppel-Event. ✅
|
||||
**Logs:** keine Errors/Tracebacks. Health `{postgresql:true, rabbitmq:true, market_data_ready:true}`. ✅
|
||||
|
||||
## Bugs behoben während E2E (20.08.2026)
|
||||
| Bug | Fix |
|
||||
|-----|-----|
|
||||
| `can't adapt type 'dict'` (JSONB) | `json.dumps(ind.model_dump(mode="json"))` |
|
||||
| `tuple index out of range` (16/15) | `version` in INSERT-VALUES ergänzt |
|
||||
| `ON CONFLICT` + partieller Index Fehler | `WHERE source_event_id IS NOT NULL` in Klausel |
|
||||
| `model_dump(default=...)` TypeError | `default`-Kwarg entfernt (`model_dump(mode="json")`) |
|
||||
| Consumer-Verbindungs-Leak | `conn.close()` bei Reconnect → kein Message-Leak |
|
||||
|
||||
## Offene Punkte
|
||||
- Consumer-Downstream für `market.regime.ready` (Modul-05+)
|
||||
- Bestätigte TRANSITION-Detektion mit echten Folgedaten
|
||||
|
||||
---
|
||||
```
|
||||
Geändert von: Rain Ocampo
|
||||
Datum: 20.08.2026
|
||||
Grund: Modul-04-Dokumentation angelegt (Regime-Engine, market_regime-Schema, Events, E2E freigegeben).
|
||||
```
|
||||
Loading…
Reference in a new issue