336 lines
18 KiB
Markdown
336 lines
18 KiB
Markdown
---
|
||
type: Trading-Modul-System
|
||
_organized: true
|
||
---
|
||
|
||
# Design-Vorschlag: Modul-15 → Modul-09 Anbindung (Safety-/Trading-Control)
|
||
|
||
**Status: NUR DESIGN-VORSCHLAG — keine Implementierung.**
|
||
**Datum:** 20.08.2026 · **Autor:** Rain Ocampo (Hermes)
|
||
**Gilt für:** Modul-09-Execution-Service (FREIGEGEBEN, Order-Pfad) ↔ Modul-15-Monitoring-Control (IMPLEMENTIERT + E2E-verifiziert, **noch nicht freigegeben**)
|
||
|
||
> **Scope-Regeln (verbindlich):**
|
||
> - M09 wird **nicht** verändert, bis dieser Vorschlag vom Nutzer freigegeben wurde.
|
||
> - M15 bleibt **nicht freigegeben** bis Nutzer-Freigabe.
|
||
> - M16 wird **nicht** begonnen.
|
||
> - Dieser Vorschlag ist **Architektur/Pseudoflow**, kein Code.
|
||
|
||
---
|
||
|
||
## 1. Ziel
|
||
|
||
**Modul-15** wird die **autoritative Safety-/Trading-Control-Instanz** für den Order-Durchstich.
|
||
**Modul-09** darf neue Orders **nur senden, wenn M15 dies eindeutig erlaubt**.
|
||
|
||
Kernauftrag: kein OPEN/INCREASE, solange M15 nicht *eindeutig* ENABLED bestätigt. Gleichzeitig darf ein HALT **niemals** Risikoreduktion / Position-Schließen verhindern (Exit-Pfade bleiben immer frei).
|
||
|
||
---
|
||
|
||
## 2. Ist-Zustand in M09 (Kontext für den Vorschlag)
|
||
|
||
Der Order-Pfad in `app/core/service.py::_on_event` ist heute:
|
||
|
||
```
|
||
TRADE_APPROVED (Modul-08)
|
||
→ 1) Idempotenz (already_processed)
|
||
→ 2) Harte Validierung validate_trade_approved (FAIL-CLOSED)
|
||
→ 3) Broker-Bereitschaft validate_broker_ready (FAIL-CLOSED)
|
||
→ 4) Order atomar in DB anlegen (Advisory Lock + Transaktion, PENDING)
|
||
→ 5) _submit_and_track → BrokerAdapter.submit_order
|
||
```
|
||
|
||
**Heutiger Kill-Switch:** rein konfigurativ `TRADING_ENABLED=false` (Default, sicher für LIVE).
|
||
Es existiert **keine** externe Echtzeit-Control-Schnittstelle im Order-Pfad.
|
||
|
||
**Einbau-Punkt (Vorschlag):** zwischen Schritt 4 (Order angelegt) und Schritt 5 (Broker-Submit)
|
||
— d. h. **unmittelbar vor `submit_order`**. Alternativ als zusätzlicher Check in Schritt 2.
|
||
Empfehlung: als eigener Schritt zwischen 4 und 5, weil dort die Order bereits idempotent in der DB
|
||
liegt und wir den Final-Check „direkt vor dem Senden" platzieren (Race-Window minimal).
|
||
|
||
---
|
||
|
||
## 3. Trading-States & Regelwerk
|
||
|
||
### 3.1 Globale Trading-States (autoritativ: M15)
|
||
|
||
| State | Bedeutung | neue OPEN/INCREASE | REDUCE | CLOSE/CANCEL |
|
||
|-------|-----------|--------------------|--------|--------------|
|
||
| `ENABLED` | Alle krit. Dienste gesund, aktuelle Market-Data, Trading erlaubt | **ERLAUBT** | erlaubt | erlaubt |
|
||
| `PAUSED` | Nicht-krit. Störung (Analytics/Notification), Risiko-umfeld unklar | **VERBOTEN** | **ERLAUBT** | **ERLAUBT** |
|
||
| `HALTED` | Krit. Ausfall (PG/RMQ/Execution/Market-Data/UNKNOWN) | **VERBOTEN** | **ERLAUBT** | **ERLAUBT** |
|
||
| `UNKNOWN` / M15 nicht erreichbar / Status veraltet | Unklarheit | **VERBOTEN (FAIL-CLOSED)** | **ERLAUBT** (konservativ) | **ERLAUBT** |
|
||
|
||
**Kernregel:** Nur `ENABLED` erlaubt neue Positionen (OPEN) oder Aufstockung (INCREASE).
|
||
**Alles andere** (PAUSED/HALTED/UNKNOWN/nicht erreichbar/veraltet) blockiert OPEN/INCREASE.
|
||
**REDUCE/CLOSE** (Risikoreduktion/Position schließen) sind **immer** erlaubt — unabhängig vom State.
|
||
|
||
### 3.2 Order-Kategorien (Einordnung)
|
||
|
||
| Aktion | Bedeutung | Regel bei PAUSED/HALTED/UNKNOWN |
|
||
|---|---|---|
|
||
| `OPEN` | Neue Position eröffnen | **BLOCKIEREN** |
|
||
| `INCREASE` | Bestehende Position aufstocken | **BLOCKIEREN** (Neue-Position-Logik, Risiko wächst) |
|
||
| `REDUCE` | Position verkleinern | **ERLAUBT** (Risiko sinkt) |
|
||
| `CLOSE` | Position schließen | **ERLAUBT** (Risiko eliminieren) |
|
||
| `CANCEL` | Offene/geplante Order stornieren | **ERLAUBT** (kein neues Risiko) |
|
||
|
||
> Begründung INCREASE blockiert: Aufstocken fügt neues Marktrisiko hinzu — bei HALT/Unklarheit
|
||
> unerlaubt. REDUCE/CLOSE/CANCEL sind per Definition risikoreduzierend → immer frei.
|
||
|
||
---
|
||
|
||
## 4. Vergleich der Anbindungs-Varianten
|
||
|
||
### Variante A — synchroner HTTP-Check vor jeder Order
|
||
|
||
M09 ruft vor jedem Submit `GET /control/trading-state` auf M15 (Docker-intern) auf.
|
||
|
||
| Kriterium | Bewertung |
|
||
|---|---|
|
||
| **Sicherheit** | Sehr hoch — liest immer den frischesten autoritativen Zustand. FAIL-CLOSED bei Timeout. |
|
||
| **Latenz** | Pro Order +1 Round-Trip (ms-Bereich, Docker-Netz). Bei vielen Orders spürbar, aber Orders sind selten. |
|
||
| **Ausfallsicherheit** | M15-down → HTTP-Time out → FAIL-CLOSED (blockieren). Sicher, aber **M15 wird Single Point of Failure für OPEN**. |
|
||
| **Race Conditions** | M15 könnte direkt nach Antwort auf HALTED wechseln → Race trotz Check (siehe §7). Final-Check nur minimal schmaler. |
|
||
| **Single Point of Failure** | **Ja** — M15 ist für OPEN/INCREASE zwingend. Bei M15-down wird der Execution-Service sonst blind blockiert. |
|
||
| **Bei RabbitMQ-Ausfall** | HTTP bleibt funktionsfähig (separater Kanal) → Check ok; aber M15 meldet RABBITMQ_UNREACHABLE→HALTED → korrekt blockiert. |
|
||
| **Bei M15-Ausfall** | Timeout → FAIL-CLOSED → OPEN/INCREASE blockiert (gewünscht). REDUCE/CLOSE müssen **ausgenommen** werden, sonst kann Position nicht geschlossen werden. |
|
||
| **Komplexität** | Gering — ein HTTP-Call, kein Cache, kein Subscription. |
|
||
| **Nachvollziehbarkeit/Audit** | M15 protokolliert jede Anfrage; M09 loggt Check + Ergebnis. Gut, aber hochfrequent (jede Order). |
|
||
|
||
### Variante B — Event-basierter Status-Cache (publish/subscribe)
|
||
|
||
M15 publiziert Statusänderungen auf `market.control`; M09 subscribt und hält ein lokales State-Modell.
|
||
|
||
| Kriterium | Bewertung |
|
||
|---|---|
|
||
| **Sicherheit** | Mittel — Status nur so frisch wie das letzte Event + Cache-TTL; **riskant ohne TTL/Herzschlag**. |
|
||
| **Latenz** | Sehr gering — kein HTTP im kritischen Pfad, Cache-Lookp. |
|
||
| **Ausfallsicherheit** | Schlecht — RabbitMQ-Ausfall ⇒ keine Events mehr; Cache wird **stale**. Ohne TTL würde M09 mit veraltetem ENABLED weiter traden. **Gefahr.** |
|
||
| **Race Conditions** | Stale-Cache ist die größte Race-Quelle. Event-Reihenfolge/Lag. |
|
||
| **Single Point of Failure** | RabbitMQ als Event-Bus ist der SPOF für den Status-Transport. |
|
||
| **Bei RabbitMQ-Ausfall** | Events stoppen → Cache veraltet → **genau das Risiko**, das wir vermeiden wollen. Muss über Cache-TTL + Fail-CLOSED gelöst werden. |
|
||
| **Bei M15-Ausfall** | Keine neuen Events → Cache veraltet. Ohne TTL gefährlich (weiter OPEN). |
|
||
| **Komplexität** | Mittel — Subscription, Cache-Update, TTL-Reinigung, RabbitMQ-Reconnect im M09. |
|
||
| **Nachvollziehbarkeit/Audit** | Gut — Event-Stream ist Append-Log; aber Cache-Echo im M09 ist ein zweites Modell (Konsistenzpflege). |
|
||
|
||
### Variante C — Kombination: Event-Cache + synchroner Final-Check (EMPFEHLUNG)
|
||
|
||
**Event-Cache als schnelle Vorfilterung**, **synchroner HTTP-Final-Check unmittelbar vor dem
|
||
Broker-Submit** als harte Bestätigung. Nur wer beide klar "ENABLED" liefert, darf OPEN/INCREASE.
|
||
|
||
| Kriterium | Bewertung |
|
||
|---|---|
|
||
| **Sicherheit** | **Sehr hoch** — zweistufig. Cache als Bauraus/Performance, HTTP-Final als Autorität. |
|
||
| **Latenz** | Fast so gering wie B im Common-Case, da Vorfilter die meiste Zeit per Cache durchläuft; **aber** der obligatorische Final-Check ist der Latenzdominante Teil (immer +1 HTTP). |In Praxis Orders selten → akzeptabel. |
|
||
| **Ausfallsicherheit** | Beste — Cache kann "PAUSED/HALTED/UNKNOWN" sofort blockieren; HTTP- Ausfall ⇒ FAIL-CLOSED. Zwei unabhängige Quellen. |
|
||
| **Race Conditions** | Der synchronier Final-Check (TTL = kurz, unmittelbar vor dem Submit) minimiert die Chance, dass M15 direkt danach HALTED setzt. Plus `control_version`-Bump (§7) zum harten Ausschluss. |
|
||
| **Single Point of Failure** | M15 bleibt SPOF für OPEN/INCREASE (unvermeidbar, da autoritativ). REDUCE/CLOSE ausgenommen. |
|
||
| **Bei RabbitMQ-Ausfall** | Cache veraltet → aber Cache-Logik blockiert bei "veraltet/UNKNOWN"; HTTP-Final ist unabhängig vom Bus → liefert korrekte M15-Sicht (die selbst RMQ-Ausfall als HALTED sieht). |
|
||
| **Bei M15-Ausfall** | HTTP-Final-Check schlägt fehl → FAIL-CLOSED, OPEN/INCREASE blockiert. REDUCE/CLOSE frei. |
|
||
| **Komplexität** | Höher (beides). Aber gut beherrschbar; Cache als reiner nicht-kritischer Vorfilter, Autorität liegt klar beim HTTP. |
|
||
| **Nachvollziehbarkeit/Audit** | Exzellent — Final-Check liefert `state_version` + `timestamp` + `audit_id` pro Order; Cache-Zustand separat auditierbar. |
|
||
|
||
### Zusammenfassung der Varianten
|
||
|
||
| | A (HTTP) | B (Event-Cache) | C (Kombi) |
|
||
|---|---|---|---|
|
||
| Sicherheit | hoch | mittel | **sehr hoch** |
|
||
| Latenz | +HTTP | **sehr gering** | gering (HTTP-Final) |
|
||
| Ausfallsicherheit | ok (SPOF M15) | **schwach** (RMQ SPOF) | **beste** |
|
||
| Race-Risiko | minimiert (kurz) | **hoch (stale)** | **minimiert** |
|
||
| RMQ-Ausfall | korrekt (HALTED) | **risiko (stale)** | korrekt |
|
||
| M15-Ausfall | FAIL-CLOSED | **risiko (stale)** | FAIL-CLOSED |
|
||
| Komplexität | gering | mittel | **höher** |
|
||
| Audit | gut | zweites Modell | **exzellent** |
|
||
|
||
**Empfehlung: Variante C** (Event-Cache als Vorfilter + synchroner Final-Check).
|
||
|
||
---
|
||
|
||
## 5. Race Condition & Lösung
|
||
|
||
**Problem:** M09 prüft `ENABLED`, M15 wechselt sofort danach auf `HALTED` — bevor M09 die Order gesendet hat.
|
||
|
||
**Lösung (Kombination):**
|
||
1. **Final-Check unmittelbar vor `submit_order`** — minimales Zeitfenster (ms) zwischen Check und Send.
|
||
2. **TTL auf der HTTP-Antwort:** `expires_at` (z. B. `now + 500 ms`). Ist die Antwort beim Senden abgelaufen
|
||
(Fenster überschritten), NICHT senden → Order nach `FAILED/REJECTED` mit `CONTROL_STATE_STALE` markieren.
|
||
3. **`state_version`** (Monoton aufsteigend, von M15 je Status-Änderung). M09 übernimmt die im Final-Check
|
||
gesehene Version. Beim Broker-Submit trägt die Order die `control_version`; die Audit-Kette verbindet
|
||
genau die Version, die gegolten hat, mit dem Versand.
|
||
4. **Bestätigtes Einverständnis:** Der Check liefert `trading_status=ENABLED` **und** `state_version` **und**
|
||
`expires_at`. Nur wenn beides vorliegt und innerhalb der TTL ist, darf OPEN/INCREASE durchgehen.
|
||
5. **Audit-ID / Correlation:** M09 erzeugt `control_audit_id`, M15 protokolliert die Bestätigung. Damit ist
|
||
der „wir haben im ENABLED-Zustand gesendet" Moment exakt nachvollziehbar.
|
||
|
||
**Kein "Senden dann hoffen":** Ist das Fenster überschritten oder Status unklar → `FAILED` mit
|
||
`CONTROL_STATE_UNKNOWN/CONTROL_STATE_STALE`, **niemals** blind erneut senden (konsistent zum bestehenden
|
||
M09-Time-out-Handling: erst Status beim Broker klären, dann entscheiden).
|
||
|
||
---
|
||
|
||
## 6. API-Vertrag M15 → M09
|
||
|
||
### 6.1 `GET /control/trading-state` (von M09 im Final-Check)
|
||
|
||
**Request:** keiner (oder optional `?action=OPEN` / `?for_action=OPEN` zur Kontext-Auditierung)
|
||
|
||
**Response 200 (ENABLED):**
|
||
```json
|
||
{
|
||
"trading_status": "ENABLED", // ENABLED|PAUSED|HALTED|UNKNOWN
|
||
"system_status": "HEALTHY", // Kontext
|
||
"state_version": 42, // monoton, von M15 je Änderung
|
||
"timestamp": "2026-08-20T15:30:00Z", // Erzeugzeit (UTC, ISO 8601)
|
||
"expires_at": "2026-08-20T15:30:00.5Z", // TTL-Horizont (Server), z. B. now+500ms
|
||
"ttl_seconds": 0.5,
|
||
"audit_id": "ctl-..." // M15-interne Audit-Kennung der Bestätigung
|
||
}
|
||
```
|
||
**Nur** dieses Objekt mit `trading_status=ENABLED` und `expires_at` in der Zukunft gilt als "eindeutige Erlaubnis".
|
||
|
||
**Response (blockiert):** gleiches Schema, aber `trading_status` = `PAUSED`/`HALTED`/`UNKNOWN`.
|
||
|
||
**Fehler/Timeouts:**
|
||
- HTTP 503 → M15 selbst nicht Ready/unbekannt → **FAIL-CLOSED** (als HALTED/unbekannt behandeln).
|
||
- Timeout/5xx/netz → **FAIL-CLOSED**, als `UNKNOWN` behandeln.
|
||
- Alle nicht-`ENABLED`-Antworten → OPEN/INCREASE **verweigert**.
|
||
|
||
### 6.2 Empfehlung der aktuellen API-Form
|
||
|
||
M15 hat aktuell `GET /control/trading-state` (liefert `trading_status` + `system_status`). Für M09-Anbindung
|
||
empfehle ich die obige **Erweiterung** um `state_version`, `timestamp`, `expires_at`, `audit_id` — dies ist ein
|
||
**additiver API-Vertrag** (kein Breaking Change). Das ist im Vorschlag berücksichtigt; die konkrete
|
||
Umsetzung erfolgt erst nach Freigabe.
|
||
|
||
---
|
||
|
||
## 7. Event-Schema für Status-Änderungen (market.control)
|
||
|
||
M15 publiziert auf Exchange `market.control`, Routing `trading.state` — **nur bei Status-Änderung** (keine Schleife).
|
||
|
||
```json
|
||
{
|
||
"event_id": "evt-...",
|
||
"event_type": "trading.state",
|
||
"timestamp": "2026-08-20T17:30:00Z",
|
||
"version": 1,
|
||
"payload": {
|
||
"trading_status": "HALTED", // ENABLED|PAUSED|HALTED|UNKNOWN
|
||
"system_status": "UNHEALTHY",
|
||
"state_version": 43,
|
||
"reason_codes": ["POSTGRESQL_UNREACHABLE", "PERSISTENCE_FAILURE"],
|
||
"changed_at": "2026-08-20T17:30:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Im Cache (Variante C):**
|
||
- M09 hält `last_state` (trading_status + state_version + received_at).
|
||
- **TTL (z. B. 5 s):** ist `received_at` älter als TTL → Cache behandelt als `UNKNOWN/veraltet` → OPEN/INCREASE
|
||
**blockiert** (auch wenn letztes Event `ENABLED` war).
|
||
- Ein Event `state_version` älter als bereits gesehen → ignorieren (kein Regress).
|
||
|
||
---
|
||
|
||
## 8. Verhalten nach Recovery
|
||
|
||
- **Kein automatisches RESUME:** M15 nimmt nach Behebung der Ursache Status selbst neu (z. B. HALTED→HEALTHY→ENABLED)
|
||
**nur durch den regulären Monitoring-Zyklus** (Ursache wirklich erneut geprüft). Es gibt kein verstecktes Auto-Resume.
|
||
- M09 wartet darauf: erst wenn ein **neues Event mit `trading_status=ENABLED` und neuer `state_version`** oder
|
||
ein **HTTP-Final-Check mit `ENABLED`** vorliegt, sind OPEN/INCREASE wieder möglich.
|
||
- Ein `PAUSED→ENABLED`-Übergang verlangt, dass M15 nachweislich die früheren HALT-Gründe entfernt hat
|
||
(keine Reason-Codes mehr). Dies wird durch die bestehende FAIL-CLOSED-Regel + idempotentes Event sichergestellt.
|
||
- **Cache-TTL-Disziplin:** Nach einem HALTED/PAUSED-Ereignis bleibt M09 vorsichtig: Es traut dem Cache erst
|
||
wieder, wenn ein neues `ENABLED`-Event (hohe Version) eingegangen ist — niemals basierend auf Zeitablauf der
|
||
Sperre, sondern auf **bestätigter Freigabe**.
|
||
|
||
---
|
||
|
||
## 9. Audit in M09 (zusätzlich zu M15-Audit)
|
||
|
||
Für jede Order-Entscheidung (im M09-Storage bzw. `execution_event`):
|
||
- `control_status`: Ergebnis des Final-Checks (`ENABLED`/`PAUSED`/...)
|
||
- `control_state_version`: Version, die beim Send gegolten hat
|
||
- `control_expires_at` / `control_ttl`: TTL-Horizont
|
||
- `control_audit_id`: vom Final-Check zugeordnet
|
||
- `control_check_source`: `final_http` (und optional `cache`)
|
||
|
||
Damit ist jede Order exakt dem autoritativen Zustand zum Sendzeitpunkt zugeordnet (Audit-Kette vollständig).
|
||
|
||
---
|
||
|
||
## 10. Zusammenfassung Architektur-Empfehlung
|
||
|
||
**Variante C**: Event-Cache (mark-to-control, TTL, state_version) als **nicht-kritischen Vorfilter** im M09 +
|
||
**synchronier HTTP-Final-Check** (`GET /control/trading-state`, mit `expires_at`+`state_version`+`audit_id`)
|
||
unmittelbar vor `submit_order`. Beide müssen `ENABLED` und frisch sein; sonst OPEN/INCREASE blockiert
|
||
(FAIL-CLOSED). REDUCE/CLOSE/CANCEL sind von der Control-Regel ausgenommen und laufen immer.
|
||
|
||
- **Zustand, der OPEN/INCREASE erlaubt:** Cache == `ENABLED` (frisch) UND Final-Check == `ENABLED` (frisch).
|
||
- **Sonst alles:** blockiert OPEN/INCREASE; REDUCE/CLOSE/CANCEL frei.
|
||
- **FAIL-CLOSED:** M15 nicht erreichbar, Timeout, Cache veraltet, `UNKNOWN` → OPEN/INCREASE verweigert.
|
||
- **M15 bleibt SPOF nur für OPEN/INCREASE** (unvermeidbar, autoritativ). Exit/Close bleibt immer möglich.
|
||
|
||
---
|
||
|
||
## 11. Pseudoflow (Order-Durchstich M09)
|
||
|
||
```
|
||
TRADE_APPROVED (Modul-08)
|
||
│
|
||
▼
|
||
1. Kategorisiere Aktion: OPEN | INCREASE | REDUCE | CLOSE | CANCEL
|
||
│
|
||
├─ action ∈ {REDUCE, CLOSE, CANCEL} → ERLANG DURCHSTICH (kein Control-Check)
|
||
│ └─→ weiter zum bestehenden Submit-Pfad
|
||
│
|
||
└─ action ∈ {OPEN, INCREASE}
|
||
│
|
||
▼
|
||
2. [Cache-Vorfilter] local_state = cache.get()
|
||
├─ local_state ist stale (age > TTL) → → zum Final-Check (unten) aber NICHT aus Cache ableiten
|
||
└─ local_state.trading_status != ENABLED → BLOCKIERT (markiere FAILED/REJECTED, CONTROL_STATE_*)
|
||
│
|
||
▼
|
||
3. [Final-Check] resp = M15 GET /control/trading-state (Time out: 800ms, Retry: 1×)
|
||
├─ Timeout/5xx → FAIL-CLOSED → BLOCKIERT (FAILED, CONTROL_STATE_UNKNOWN)
|
||
└─ resp.trading_status != ENABLED → BLOCKIERT (FAILED, CONTROL_STATE_*)
|
||
└─ resp.expires_at <= now → BLOCKIERT (FAILED, CONTROL_STATE_STALE)
|
||
▼
|
||
4. Zustand grün (ENABLED, frisch, version=resp.state_version)
|
||
→ Order in DB (PENDING, CONTROL_FIELDS: version, audit_id, expires)
|
||
▼
|
||
5. unmittelbar danach: broker.submit_order(request) ← nur zwischen 4 und 5 minimales Fenster
|
||
▼
|
||
6. Ergebnis verarbeiten (FILLED/REJECTED/FAILED), Audit-Event mit control_* schreiben
|
||
```
|
||
|
||
### Zeit-/Retry-Parameter (Vorschlag)
|
||
- Final-Check-HTTP-Timeout: **500 ms** (Docker-intern, schnell); Retry: **max 1** sofort.
|
||
- `expires_at`-TTL (M15): **500 ms** (Server-seitig gesetzt).
|
||
- Nach Timeout/unklar: **nicht senden**; Order als `FAILED`/`REJECTED` mit `CONTROL_STATE_UNKNOWN/STALE`.
|
||
- **Kein Auto-Resume**, kein "dann schicken wir eben ohne Check".
|
||
|
||
### Warum REDUCE/CLOSE/CANCEL durchlaufen
|
||
- Ziel des Control ist **Risiko-Management**. Ein HALT darf Risiko niemals einfrieren — im Gegenteil,
|
||
muss das System bei Problemen schneller in der Lage sein, Positionen abzubauen.
|
||
- `REDUCE`/`CLOSE`/`CANCEL` senken/eliminieren Risiko → **immer erlaubt**, unabhängig von M15-Status.
|
||
|
||
---
|
||
|
||
## 12. Offene Punkte für die Nutzer-Freigabe
|
||
|
||
1. **API-Vertrag erweitern** (`state_version`, `expires_at`, `ttl_seconds`, `audit_id`) in M15 (additiv).
|
||
2. **M09-Check-Position:** zwischen Schritt 4 (Order in DB) und 5 (Broker-Submit) — bestätigen.
|
||
3. **TTL-Wert** (`expires_at`-Fenster) festschreiben (Vorschlag 500 ms).
|
||
4. **Kategorisierung** der Order-Aktion in M09 (OPEN/INCREASE/REDUCE/CLOSE/CANCEL) ableiten — M09 muss
|
||
aus dem TRADE_APPROVED die Aktion bestimmen (Vorschlag: über `direction`/Kanten-Art der Entscheidung).
|
||
5. **M03–M06-Klassifikation** (Market-Data-Pipeline): ob Einzel-Ausfall dieser Module wirklich HALTED
|
||
auslösen soll, oder nur deren Daten-Staleness — zu finalisieren, beeinflusst WEN oft HALTED greift.
|
||
6. **SPOF-Akzeptanz:** M15 ist für OPEN/INCREASE zwingend (autoritativ). Exit-Pfad bleibt frei.
|
||
7. M15 weiterhin **nicht freigeben**, M16 **nicht beginnen** bis Nutzer-Entscheid.
|
||
|
||
---
|
||
|
||
*Dies ist ein Design-Vorschlag. Es wurde kein Code geändert. M15 nicht freigegeben. M16 nicht begonnen.*
|