docs(tolaria): canonicalize modul-09 system documentation
This commit is contained in:
parent
e8a9804f8e
commit
47f80bc34d
1 changed files with 60 additions and 4 deletions
|
|
@ -50,10 +50,65 @@ RabbitMQPublisher (market.execution)
|
|||
`submit_order()`, `get_order_status()`
|
||||
- `PaperBrokerAdapter` (app/broker/paper.py): V1, simuliert realistischen
|
||||
Lifecycle (SUBMITTED → FILLED, Partial Fill, Reject, Timeout) für Tests
|
||||
- `IgDemoAdapter` (app/broker/ig_demo.py): IG-Markets-Demo-Broker (IG_DEMO-Modus),
|
||||
echter externer Broker-Adapter. Liest/schreibt über IG REST API (demo-api.ig.com).
|
||||
- `BrokerRegistry` (app/broker/registry.py): wählt Adapter anhand
|
||||
`DEFAULT_BROKER` (V1: paper). Echte Broker-Adapter später austauschbar,
|
||||
keine Brokerlogik im Core-Code.
|
||||
|
||||
## IG-Demo-Adapter (IG_DEMO-Modus, 21.08.2026)
|
||||
|
||||
**Status: FREIGEGEBEN / PRODUKTIV VERIFIZIERT** — erster echter externer Broker-Adapter.
|
||||
|
||||
- **Eigener Modus `IG_DEMO`** (nicht LIVE+Gate); PAPER/IG_DEMO/LIVE strikt getrennt.
|
||||
- **Demo-Basis-URL erzwungen** (`demo-api.ig.com`), LIVE-Endpunkt (`api.ig.com`)
|
||||
technisch blockiert, kein IG_DEMO→LIVE-Autowechsel.
|
||||
- **Credentials ausschließlich VPS-Secret/ENV** (`.env.ig`, chmod 600/root-only);
|
||||
nie in Code/Forgejo/Tolaria/DB/Logs.
|
||||
- **Mengen instrumentabhängig** über `broker_mapping` (PostgreSQL); kein globales 1:1.
|
||||
- **Epic-Mapping produktiv in PostgreSQL `broker_mapping`**; Forgejo nur Schema/Doku/Beispiele.
|
||||
|
||||
### Order-Aktions-Auswertung (CLOSE-Pfad-Fix, 21.08.2026)
|
||||
`BrokerOrderRequest` trägt `action_type` (Default `OPEN`) + `broker_order_id`.
|
||||
Der Service reicht beides durch; der Adapter wertet `action_type` aus:
|
||||
|
||||
| action_type | IG-Pfad |
|
||||
|-------------|---------|
|
||||
| `OPEN` / `INCREASE` | `POST /positions/otc` (create_position) |
|
||||
| `CLOSE` / `REDUCE` | `POST /positions/otc` mit `_method:DELETE` (close_position) |
|
||||
| unbekannt/ungültig | **FAIL-CLOSED** (`IG_UNSUPPORTED_ACTION`) |
|
||||
|
||||
**CLOSE-Direction korrekt umkehren:** CLOSE einer LONG/BUY-Position muss mit
|
||||
**SELL** erfolgen (Gegenseite), nicht mit der Positionsrichtung. `_close_direction()`:
|
||||
LONG→SELL, SHORT→BUY.
|
||||
|
||||
**broker_order_id/dealId sauber durchreichen:** `broker_order_id` wird vom Service
|
||||
in die Order übernommen und an den Adapter durchgereicht; IG `dealId` wird als
|
||||
`broker_order_id` persistiert.
|
||||
|
||||
**Unbekannte/ungültige Aktionen FAIL-CLOSED:** `_derive_action_type()` setzt
|
||||
unbekannte Aktionen NICHT mehr auf OPEN zurück, sondern reicht sie durch →
|
||||
Control blockt mit `UNKNOWN_ACTION_TYPE`, Adapter mit `IG_UNSUPPORTED_ACTION`.
|
||||
|
||||
### IG-Adapter-Tests (6/6 grün)
|
||||
1. `test_unsupported_action_fail_closed` — unbekannte Aktion → FAIL-CLOSED
|
||||
2. `test_close_direction_inverted` — CLOSE einer BUY-Position → SELL
|
||||
3. `test_open_uses_create_position` — OPEN → create_position
|
||||
4. `test_close_uses_close_position` — CLOSE → close_position mit `_method:DELETE`
|
||||
5. `test_broker_order_id_passthrough` — broker_order_id/dealId durchgereicht
|
||||
6. `test_fail_closed_without_credentials` — ohne Credentials → nicht konfiguriert
|
||||
|
||||
### Erster erfolgreicher IG-DEMO OPEN→CLOSE-E2E (21.08.2026)
|
||||
- **OPEN** `IGE2E-US500-OPEN-1787292734` → dealId `DIAAAAYB46KMNAE`, size 1.0, BUY,
|
||||
openLevel 7652.58 → **FILLED**
|
||||
- **CLOSE-Bug gefunden + gefixt:** erster CLOSE sendete fälschlich als zweite OPEN
|
||||
(action_type ignoriert) + falsche direction (BUY statt SELL)
|
||||
- **CLOSE2** `IGE2E-US500-CLOSE2-1787293768` für `DIAAAAYB463S4AB` → **FILLED**
|
||||
(filled_quantity 1, avg_fill_price 7652.19)
|
||||
- **IG GET /positions: Anzahl 0** — alle Positionen geschlossen
|
||||
- **Safety-Reset:** M09 zurück auf PAPER (`EXECUTION_MODE=PAPER`,
|
||||
`TRADING_ENABLED=false`, `DEFAULT_BROKER=paper`)
|
||||
|
||||
## Idempotenz
|
||||
|
||||
- Unique-Index `uq_execution_order_src` auf `source_portfolio_decision_id`
|
||||
|
|
@ -89,10 +144,11 @@ sowie `REJECTED`, `CANCELLED`, `FAILED`.
|
|||
|
||||
## Tests
|
||||
|
||||
- **21/21 Unit-Tests** (test_execution.py): gültige Order → PAPER FILLED,
|
||||
Idempotenz, ungültige Quantity → REJECTED, Kill-Switch, fehlende
|
||||
Broker-Credentials → FAIL-CLOSED, Broker-Reject, Timeout → keine blinde
|
||||
Doppelorder, Partial Fill, Reconnect-Backoff, parallele identische Events
|
||||
- **31/31 Unit-Tests** (test_execution.py + test_ig_demo.py + test_control.py):
|
||||
gültige Order → PAPER FILLED, Idempotenz, ungültige Quantity → REJECTED,
|
||||
Kill-Switch, fehlende Broker-Credentials → FAIL-CLOSED, Broker-Reject,
|
||||
Timeout → keine blinde Doppelorder, Partial Fill, Reconnect-Backoff,
|
||||
parallele identische Events, Control-Gate (M15), IG-Adapter (6/6)
|
||||
- **E2E 6/6 Checks** (Kette 03→04→05→06→07→08→09): Execution-Order in DB,
|
||||
exakt 1 Paper-Order, Pflichtfelder, Idempotenz, ORDER_SUBMITTED+ORDER_FILLED,
|
||||
gültiger Trade → PAPER FILLED
|
||||
|
|
|
|||
Loading…
Reference in a new issue