Phase 9: M12/M13 Phase-2-Readiness-Audit + Implementierungsmatrix A-N (Analyse/Design/Verifikation, keine Implementierung)
This commit is contained in:
parent
d3d6b1ef76
commit
e8d91b78b3
1 changed files with 341 additions and 0 deletions
341
notes/trading/system-docs/phase9_readiness_audit.md
Normal file
341
notes/trading/system-docs/phase9_readiness_audit.md
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
---
|
||||
type: Note
|
||||
tags: [trading, mt5, architecture, historical-v2, m12, m13, phase9, readiness-audit, phase2]
|
||||
created: 2026-08-22
|
||||
---
|
||||
|
||||
# Phase 9 — M12/M13 Phase-2-Readiness-Audit + Implementierungsmatrix A–N
|
||||
|
||||
> Autor: Rain Ocampo | Datum: 22.08.2026 | Status: ✅ ANALYSE + DESIGN + VERIFIKATION (KEINE Implementierung)
|
||||
> **Geändert von: Rain Ocampo, Datum: 22.08.2026, Grund: Phase-9-Audit (read-only, Code-Evidenz)**
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Phase 2 (realistischer Backtest: Bid/Ask-Fill, Spread, Slippage, Kosten, Intrabar, Gap) ist NICHT implementiert. Das heutige M12 nutzt ein **reines Single-Price-Bid-Modell** (nur Legacy-`ohlcv`-`close`, oder V2-`bid_close` als `close`). Es gibt keine Bid/Ask-Fill-Logik, kein separates Spread-Modell außer einem pauschalen Preispunkte-Abschlag auf Entry+Exit, keine Slippage außer derselben Punkte-Verschlechterung, und keinen Kosten-Breakdown. Der wichtigste Verzerrungs-Punkt: **Der Intrabar-Exit ist symmetrie-verzerrt** — Stop gewinnt immer bei Stop+Target-in-einer-Bar (konservativ, aber pessimistisch für Target-Trades).
|
||||
|
||||
Die Erweiterung muss einen **ExecutionContext** einführen, der `execution_model`, `spread_model`, `slippage_model`, `cost_model`, `intrabar_policy`, `price_basis`, `feed_type` transportiert und versioniert — inklusive Run-Hash-Integration, aber **strikt getrennt** von Dataset-Identität und Strategie-Parameter.
|
||||
|
||||
---
|
||||
|
||||
## A — PRICE MODEL / SINGLE-PRICE AUDIT
|
||||
|
||||
### Candle-Datenmodell (M12)
|
||||
- **Legacy** (`repository.py:_load_candles_legacy`, Zeile 305-327): `ohlcv`-Tabelle, Keys `timestamp, open, high, low, close, volume`. **Nur Einzelpreis** pro Bar (Mid/Einzelpreis). Kein bid/ask.
|
||||
- **V2** (`repository.py:_load_candles_v2`, Zeile 332-371): liest aus `historical_bar` und mappt **`bid_open→open, bid_high→high, bid_low→low, bid_close→close`**. Das `historical_bar`-Schema HAT bid_open..ask_close (verifiziert: 37.480/37.480 bid+ask, mid=0), aber `load_candles` **transportiert sie NICHT** — wirft die ask-Seite weg und liefert nur bid-OHLC.
|
||||
- Die Engine bekommt also immer OHLC (nur bid/Einzel) — **niemals ask**.
|
||||
|
||||
### Entry / Exit / Stop / Target (engine.py)
|
||||
| Feld | Quelle | Zeile |
|
||||
|---|---|---|
|
||||
| Entry (Signal) | `setup.entry` = **letzter Close der Signal-Candle** (Strategie: `entry = last_close`) | strategy 134/175 |
|
||||
| Entry-Fill (Open Pos) | `next_candle["open"]` + Spread + Slippage (verschlechtert) | `_open_position` 192-214 |
|
||||
| Stop | `setup.stop_loss` = Swing-Low/High ± buffer | 135, 176 |
|
||||
| Target | `setup.target` = Entry ± 2R | 139, 180 |
|
||||
| Exit (normales Ende) | `candle["close"]` (OHNE Slippage/Spread auf Stop/Target) | `_close_position` 283-336 |
|
||||
| Market-Order-Fill | pauschaler Preispunkte-Abschlag LONG+ / SHORT- | 198-200 |
|
||||
| Gap | Open-Fill zum Gap-Open | `_evaluate_exit` 268-280 |
|
||||
| Run-Ende | Force-Close zum letzten `close` | 141-153 |
|
||||
|
||||
### Aktuelle Annahmen (Single-Price)
|
||||
| Annahme | Konsequenz |
|
||||
|---|---|
|
||||
| `open`/`close` sind handelbarer Preis (Einzel) | Kein Bid/Ask-Spread |
|
||||
| LONG Entry = OPEN + spread + slippage | Wird besser (künstlicher Overhead) |
|
||||
| LONG Exit = CLOSE (bei normalem Exit) | Kein Exit-Spread/Slippage — nur Entry hat Kosten |
|
||||
|
||||
**RISIKO**: V2-Daten sind real `bid_ask`, aber `load_candles` reduziert auf bid — die ask-Seite wird VOR der Engine verworfen. Realisierung als Bid/Ask-Fill ist daher **nicht möglich ohne Datenmodell-Änderung**.
|
||||
|
||||
**SOLL**: Engine muss `price_basis` + `bid_*`/`ask_*`/`mid_*` transportieren; Entry/Exit-Getrennt je nach Richtung; Stop/Target auf entsprechende Seite anwenden.
|
||||
|
||||
---
|
||||
|
||||
## B — BID/ASK READINESS
|
||||
|
||||
### Was liefert Historical V2 tatsächlich?
|
||||
- `historical_bar` hat **`bid_open/high/low/close` UND `ask_open/high/low/close`** (verifiziert: 37.480/37.480/37.480, mid=0) — bid_ask vorhanden, mid NICHT.
|
||||
- `load_bars_with_quality` (Zeile 163-247) transportiert bid+ask+mid+quality-Keys (vollständig).
|
||||
- ABER: `load_candles` (der Pfad, den die Engine nutzt) liefert **nur bid-OHLC** — ask wird verworfen.
|
||||
|
||||
### Kann M12 es heute transportieren?
|
||||
**Nein, nicht über den Engine-Pfad.** Die Engine bekommt `open/high/low/close` als Einzelwerte. `build_dataset_context` bringt `price_basis="bid_ask"` (aus Bar-Metadaten), aber diese Info erreicht die Engine-Fills **nicht** (nur Run-Audit).
|
||||
|
||||
### Zielmodell
|
||||
```
|
||||
LONG: Entry grundsätzlich Ask (Käufer zahlt ask)
|
||||
Exit grundsätzlich Bid (Verkäufer erhält bid)
|
||||
SHORT: Entry grundsätzlich Bid (Verkäufer verkauft bid)
|
||||
Exit grundsätzlich Ask (Käufer erhält ask)
|
||||
```
|
||||
**Sonderfälle (zu dokumentieren, NICHT implementieren):**
|
||||
- **Stop LONG**: Löse aus, wenn bid_low ≤ stop → fill = stop (oder gap-open bid, wenn gap unter)
|
||||
- **Stop SHORT**: bid_high ≥ stop → fill = stop (bid/ask?)
|
||||
- **Target LONG**: ask_high ≥ target → fill = target
|
||||
- **Market**: Entry LONG = ask_open; Entry SHORT = bid_open
|
||||
- **Limit**: (Phase 2 nicht eingeführt — kein Limit-Fill)
|
||||
- **Gap**: bid/ask-gap-opening überschlägt Stop/Target
|
||||
- **Bar Open**: Entry zum nächsten Bar-Open auf der korrekten Seite
|
||||
- **End-of-data**: force-close zum letzten bid/ask-close
|
||||
|
||||
---
|
||||
|
||||
## C — SPREAD AUDIT
|
||||
|
||||
Heute (**engine.py** `_open_position` Zeile 198-201, `_close_position` Zeile 297-303):
|
||||
- **Spread = ein fester Punktwert** (`params["spread"]`, Default 0.0, M13-Default 0.0).
|
||||
- **Einheit: Preispunkte** (absolute Preisdifferenz, nicht %).
|
||||
- Anwendung: **sowohl Entry als auch Exit**, je Richtung versetzt — d.h. ein **doppelter Spread pro Trade** (Entry+Exit) statt einmal.
|
||||
- **Preisbasis**: unklar — es wird einfach von `open`/`close` abgezogen, ohne bid/ask-Bezug. Da Daten heute bid-single sind, ist es ein "Abschlag" auf den einzigen Preis.
|
||||
|
||||
**Doppelzählungsrisiko**: Wenn Bid/Ask-Fill eingeführt wird, ist der aktuelle pauschale Spread-Abzug bereits implizit im echten bid/ask-Spread enthalten. Zusätzlich ein künstlicher `spread`-Abzug ⇒ **Doppelzählung**.
|
||||
|
||||
**Zielregel**:
|
||||
- `price_basis=bid_ask` (echte bid/ask) → Spread NICHT künstlich aufschlagen; nutze den intrinsischen bid/ask.
|
||||
- `price_basis=mid`/single → synthetisches Spread-Modell möglich (aufzuschlagen).
|
||||
- Beide Modi **strikt unterscheidbar** durch `spread_model` (z.B. `BID_ASK_INTRINSIC` vs `SYNTHETIC_FIXED` vs `SYNTHETIC_POINTS`).
|
||||
|
||||
---
|
||||
|
||||
## D — SLIPPAGE AUDIT
|
||||
|
||||
Heute (engine.py):
|
||||
- **Wann**: nur Entry + normaler Exit (nicht Stop/Target, siehe unten).
|
||||
- **Einheit**: Preispunkte (`params["slippage"]`, Default 0.0).
|
||||
- **Long/Short**: symmetrisch — Long schlägt auf (Entry+Exit), Short zieht ab. Adversarial in beiden Fällen.
|
||||
- **Deterministisch**: JA — ein fester Punkte-Wert. Kein Zufall, kein Seed.
|
||||
- **Bestandteil run_hash**: JA (steht in `params_snapshot` → `_compute_run_hash` inkludiert `params`). Slippage-Änderung ändert run_hash.
|
||||
- **Bestandteil Audit**: indirekt über `parameters` (in `metrics.audit` nicht explizit).
|
||||
|
||||
**Zielmodell**: `slippage_model` (`DETERMINISTIC_FIXED` | `SYNTHETIC_POINTS` | `BROKER_REPLAY`...). Kein Zufall im deterministischen Kern; falls stochastisch, Seed fix + in Hash. Jeder Trade trennbar slippage_cost.
|
||||
|
||||
---
|
||||
|
||||
## E — COST MODEL
|
||||
|
||||
| Kosten | Status | Quelle | Heutige Modellierung |
|
||||
|---|---|---|---|
|
||||
| **Commission** | TEILWEISE | CONFIG (`fee_fixed`+`fee_pct`) | `_fee()` auf Entry+Exit |
|
||||
| **Spread** | TEILWEISE | CONFIG (`spread`, Punkte) | pauschaler Preispunkte-Abschlag auf Entry+Exit |
|
||||
| **Slippage** | TEILWEISE | CONFIG (`slippage`, Punkte) | pauschaler Preispunkte-Abschlag auf Entry+Exit |
|
||||
| **Financing/Overnight/Swap** | NICHT | — | nicht modelliert |
|
||||
| **FX conversion** | NICHT | — | nicht modelliert |
|
||||
| **Guaranteed Stop Premium** | NICHT | — | nicht modelliert |
|
||||
| **sonstige Gebühren** | NICHT | — | nicht modelliert |
|
||||
|
||||
**Kosten-Quellen heute**: ausschließlich **CONFIG** (keine Broker-, keine Referenz-Kosten). Keine IG-Gebühren erfunden ✓.
|
||||
|
||||
**Doppelzählungsrisiko (Kosten)**: `fee` UND `spread` UND `slippage` werden alle separat abgezogen — kein Broker/Referenz-Double-count, aber `spread` als pauschaler Abzug + künftiges bid/ask würde doppelt zählen (siehe C).
|
||||
|
||||
---
|
||||
|
||||
## F — INTRABAR AMBIGUITY (engine.py `_evaluate_exit`, Zeile 251-281)
|
||||
|
||||
**Aktuelles Verhalten — Code-Evidenz:**
|
||||
- **LONG**: Stop wird VOR Target geprüft. Wenn `open<=stop`→Gap-Stop. Dann `if low<=stop`→Stop. Dann `if high>=target`→Target.
|
||||
⇒ **Wenn Stop UND Target in derselben Bar** → **Stop gewinnt IMMER** (Worst-Case konservativ).
|
||||
- **SHORT**: spiegelbildlich (Stop zuerst).
|
||||
|
||||
**Verzerrung**: M1-OHLC kann reale Intrabar-Reihenfolge nicht bestimmen (bekannt aus POC). Aktuelle Wahl ist deterministisch-pessimistisch (Stop-first), aber **kann Target-Gewinner in realistischen Sequenzen unterschätzen** (Stop-first bei bar mit beiden → Trades als Verluste klassifiziert, die real oft Target-Trades wären).
|
||||
|
||||
**Zielmodi (Design, NICHT implementiert)**:
|
||||
- `PESSIMISTIC` (= Stop-first, heutiges Verhalten)
|
||||
- `OPTIMISTIC` (= Target-first)
|
||||
- `STOP_FIRST` / `TARGET_FIRST` (explizite Varianten)
|
||||
- `TICK_RESOLUTION` (benötigt Tick-Daten — nur V2 nicht lieferbar)
|
||||
- `UNKNOWN/BLOCK` (fail-closed: keine Intrabar-Reihenfolge festgelegt → Run blocken)
|
||||
- Optional `DEFAULT=STOP_FIRST` (behält heutiges Verhalten als Baseline; künftig wählbar)
|
||||
|
||||
---
|
||||
|
||||
## G — GAP EXECUTION (engine.py, Zeile 268-280)
|
||||
|
||||
- **LONG Stop-Gap**: wenn `open<=stop` → Fill zum `min(open, stop)` = Gap-Open (schlechter). Bewiesen: ein Gap-Down unter Stop füllt nicht perfekt bei stop, sondern Gap-Open.
|
||||
- **LONG Target**: `high>=target`→ fill=target (kein Gap-Fall bei Target gesondert). wenn `open>=target` → wird als `high>=target` abgefangen und zum target gefüllt (das wäre Optimistisch — Gap UP über Target müsste evtl. Gap-Open, nicht target).
|
||||
- **SHORT analog**.
|
||||
- **RISIKO**: `target`-Fill bei Gap wird zum target (nicht gap-open) — unrealistisch optimistisch für Gap-UP-LONG (sollte bid/ask-open nach gap). Umgekehrt ist der Stop-Gap korrekt pessimistisch.
|
||||
- **Zielverhalten**: Gap-Fill-Regel konsistent: bei Gap-Öffnung jenseits Stop/Target → zum **Gap-Open der realen ausführbaren Seite**, nie zum anvisierten Level.
|
||||
|
||||
---
|
||||
|
||||
## H — REFERENCE VS BROKER FEED
|
||||
|
||||
- **Heute**: M12 kennt keinen Feed-Unterschied. Engine ignoriert `feed_type`/`price_basis`. Ergebnis wird als generischer Backtest-Output geliefert (einzig Run-Audit enthält `feed_type`/`price_basis`, aber nur bei V2 + Context).
|
||||
- **Zielregel**: REFERENCE-Daten nie als exakte Broker-Ausführung ausgeben. Run muss `execution_model` + `cost_model` + `spread_model` + `feed_type` + `price_basis` sichtbar kennzeichnen.
|
||||
- **Execution-Klassen (Phase 2)**:
|
||||
- `MARKET_SIMULATION` — nur OHLC, synthetische Modelle (Spread/Slippage/Cost als config)
|
||||
- `BROKER_APPROXIMATION` — echte bid/ask OHLC (REFERENCE), realistische Spread/Fill
|
||||
- `BROKER_REPLAY` — echte Broker-Feed + Broker-Fill (IG later), fehler bei REFERENCE
|
||||
- `BROKER_REPLAY` auf REFERENCE-Daten → **fail-closed** (inconsist).
|
||||
|
||||
---
|
||||
|
||||
## I — M13 OPTIMIZATION IMPACT
|
||||
|
||||
M13 (optimizer.py) ruft M12 mit `spread`/`slippage`/`fee_fixed`/`fee_pct` als **feste Baustein-Argumente** (`_bt_kwargs`, Zeile 326-335, alle Default 0.0). **NICHT Teil des Optimizer-Suchraums** — `param_space` enthält nur Strategie-Parameter.
|
||||
|
||||
**Gefahr**: Wenn `spread`/`slippage`/Fees in `param_space` aufgenommen würden, könnte der Optimizer sie MINIMIEREN (um Score zu maximieren) — realistische Kosten würden "schönoptimiert". Das ist **verboten**.
|
||||
|
||||
**Klassifikation (Phase-2-Design)**:
|
||||
| Klasse | Beispiele | M13 optimiert? |
|
||||
|---|---|---|
|
||||
| STRATEGY_PARAMETER | ema_period, rr_multiplier, stop_buffer | JA |
|
||||
| EXECUTION_PARAMETER | intrabar_policy, gap_rule | NEIN |
|
||||
| BROKER_PARAMETER | spread, slippage, commission, financing | NEIN |
|
||||
| DATA_PARAMETER | data_source, feed, price_basis, timeframe | NEIN |
|
||||
| POLICY_PARAMETER | eligibility_policy, quality_rule | NEIN |
|
||||
|
||||
M13 darf **standardmäßig nur STRATEGY_PARAMETER** optimieren; alle anderen Klassen bleiben fix aus dem Backtest-Request (nicht optimierbar).
|
||||
|
||||
---
|
||||
|
||||
## J — RUN HASH / REPRODUCIBILITY
|
||||
|
||||
Phase-2-Parameter, die die Run-Identität beeinflussen müssen (Kandidaten):
|
||||
- `execution_model_version`
|
||||
- `spread_model_version`
|
||||
- `slippage_model_version`
|
||||
- `cost_model_version`
|
||||
- `intrabar_policy_version`
|
||||
|
||||
**Entscheidung** (Grundregel: Daten ≠ Ausführungsmodell ≠ Strategieparameter):
|
||||
- **Dataset-Hash** (data_hash): rein die OHLC/Bar-Daten (bid/ask). Unverändert durch Execution-Modelle.
|
||||
- **Run-Hash**: Dataset-Hash + Strategie+Param + **Execution/Broker/Cost-Modell-Versionen** (weil anderer Execution-Modus → anderes Ergebnis → anderes run_hash, sonst falscher Cache-Hit).
|
||||
- **Audit**: alle expliziten Modelle/Versions + breakdown, aber NICHT in den Hash (nur repräsentativ).
|
||||
- M13-Optimizer-Hash analog: Execution-Modell-Versionen zusätzlich.
|
||||
|
||||
---
|
||||
|
||||
## K — RESULT METRICS
|
||||
|
||||
Heute (`_compute_metrics`): total_trades, winrate, profit_factor, expectancy_r, avg_r, net_pnl, gross_profit, gross_loss, avg_holding_h, long_count, short_count, max_drawdown, by_regime. **Kein Kosten-Breakdown.**
|
||||
|
||||
**Zielmetriken (Phase-2-Design)**:
|
||||
- `gross_pnl` (ohne Kosten)
|
||||
- `net_pnl` (nach allen Kosten)
|
||||
- `spread_cost` / `slippage_cost` / `commission_cost` / `financing_cost` / `total_cost`
|
||||
- `ambiguous_bars` (Bars mit Intrabar-Ambiguität)
|
||||
- `gap_fills`
|
||||
- `conditional_bars_used` (V2-Conditional)
|
||||
- `reference_feed_warning`
|
||||
|
||||
---
|
||||
|
||||
## L — FAIL-CLOSED CONDITIONS (Phase-2)
|
||||
|
||||
Design-Liste, Situationen in denen Phase-2-M12 NICHT rechnen darf:
|
||||
| Fall | Error-Code |
|
||||
|---|---|
|
||||
| Bid/Ask erforderlich aber fehlt | `BID_ASK_REQUIRED_MISSING` |
|
||||
| unbekannte price_basis | `UNKNOWN_PRICE_BASIS` |
|
||||
| unbekanntes execution_model | `UNKNOWN_EXECUTION_MODEL` |
|
||||
| Fixture blockiert | `FIXTURE_DATA_BLOCKED` |
|
||||
| Dataset nicht eligible | `DATASET_NOT_ELIGIBLE` / `UNKNOWN_CRITICAL_METADATA` |
|
||||
| DatasetContext fehlt | `DATASET_CONTEXT_MISSING` |
|
||||
| Kostenmodell verlangt Brokerdaten fehlen | `COST_MODEL_BROKER_DATA_MISSING` |
|
||||
| BROKER_REPLAY + REFERENCE-Feed | `BROKER_REPLAY_REFERENCE_INCOMPATIBLE` |
|
||||
| Tick-Modus verlangt Tickdaten, hat nur M1 | `TICK_DATA_REQUIRED_MISSING` |
|
||||
|
||||
---
|
||||
|
||||
## M — MIGRATION / COMPATIBILITY
|
||||
|
||||
| Modus | Daten | Execution | Spread | Slippage | Costs | Intrabar | Audit | Reproducibility | Zulässig |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| **LEGACY Single-Price** | ohlcv single | open/close, Stop-first | Config-punkte | Config-punkte | Config-fix/% | Stop-first | Legacy-Hash | run_hash | ✅ |
|
||||
| **V2 REFERENCE BID/ASK** | historical bid/ask | bid/ask-Fill | intrinsic (bid/ask) | Config/Determ. | Config-fix/% | wählbar | full-Audit | run_hash + execution_version | ✅ (nach Implementierung) |
|
||||
| **BROKER BID/ASK** | Broker bid/ask | broker-Fill | real broker | real broker | real broker | broker | full | Broker-Feed-Audit | (künftig) |
|
||||
| **TICK** | tick-data | tick-seq | real | real | real | tick-resolved | full | Tick-Audit | (künftig) |
|
||||
|
||||
Legacy bleibt **unverändert** (durch `price_basis`/`execution_model`-Gates). Kein stiller Fallback.
|
||||
|
||||
---
|
||||
|
||||
## N — IMPLEMENTIERUNGSREIHENFOLGE (begründet)
|
||||
|
||||
Code-Audit belegt, dass die Engine rein Single-Price ist. Empfohlene Reihenfolge (jede Phase testbar + rückbaubar):
|
||||
|
||||
1. **ExecutionContext** (Datenmodell/Versionierung) — Voraussetzung, trennt alles. LOW
|
||||
2. **Bid/Ask-Datenmodell** (load_candles/bars trägt bid/ask; Engine liest nach price_basis) — MEDIUM
|
||||
3. **Bid/Ask Fill** (LONG buy ask/sell bid, SHORT bid/ask) — HIGH (Fill-Preis)
|
||||
4. **Spread-Modell** (bid_ask intrinsic vs synthetic, keine Doppelzählung) — HIGH
|
||||
5. **Slippage** (slippage_model, Entry/Exit-Einheit, Determinismus) — MEDIUM
|
||||
6. **Cost-Breakdown** (Commission/Financing getrennt, nicht nur pauschal) — MEDIUM
|
||||
7. **Gap-Fills** (konsistentes Gap-Open-Verhalten, Stop+Target) — HIGH
|
||||
8. **Intrabar-Policy** (PESSIMISTIC/OPTIMISTIC/STOP_FIRST/TARGET_FIRST/TICK/UNKNOWN-BLOCK) — MEDIUM
|
||||
9. **Result-Cost-Breakdown** (gross/net/cost-Metriken) — LOW
|
||||
10. **M13-Param-Grenzen** (nur STRATEGY_PARAMETER optimizierbar, Execution-Kosten fix) — MEDIUM
|
||||
11. **Reproducibility** (execution_model_version in run_hash, Audit-Vollständigkeit) — MEDIUM
|
||||
12. **Regression/Legacy** (unverändert; Gate-Zusammenheit) — LOW
|
||||
13. **Acceptance-Tests** (Plan unten)
|
||||
|
||||
Die Reihenfolge weicht von der (User)-Suggestions ab: **ExecutionContext-Versionierung zuerst** ist zwingend, sonst werden Modelle ohne Versionierung eingebaut und Reproducibility bricht nachträglich. Bid/Ask-Datenmodell vor Fill zwingend.
|
||||
|
||||
---
|
||||
|
||||
## RISIKO-MATRIX
|
||||
|
||||
| Änderung | Modul | Datei/Fn | Risiko | Regression | Test | Rollback |
|
||||
|---|---|---|---|---|---|---|
|
||||
| ExecutionContext | M12 | service.py/engine.py | LOW | — | Hash-Vergleich | revert service+engine |
|
||||
| Bid/Ask-Datenmodell | M12 | marketdata/client.py, repo | **MEDIUM** | Daten-Format | load-candles-Pfad | revert client/repo |
|
||||
| Bid/Ask-Fill | M12 | engine.py | **HIGH** | Fill-Preis | LONG/SHORT Fill-Test | revert engine |
|
||||
| Spread-Modell | M12 | engine.py | **HIGH** | Spread, PnL | No-Doppelzählung | revert |
|
||||
| Slippage | M12 | engine.py | MEDIUM | slippage-Einheit | Entry/Exit-Slipp | revert |
|
||||
| Commission/Costs | M12 | engine.py | MEDIUM | Cost-Breakdown | Fee-Test | revert |
|
||||
| Gap-Fills | M12 | engine.py | **HIGH** | Stop/Target, PnL | Gap-Tests | revert |
|
||||
| Intrabar-Policy | M12 | engine.py | MEDIUM | Stop/Target | Intrabar-Tests | revert |
|
||||
| Result-Cost-Breakdown | M12 | engine.py | **HIGH** | PnL | Metrics | revert |
|
||||
| M13-Param-Grenzen | M13 | optimizer.py | MEDIUM | Overfit | Optimizer-Test | revert |
|
||||
| Reproducibility | M12/M13 | service.py/optimizer.py | MEDIUM | Run-Hash | Hash-Repro | revert |
|
||||
|
||||
---
|
||||
|
||||
## ACCEPTANCE PLAN (vor Implementierung — Katalog)
|
||||
|
||||
**Fill/Spread:**
|
||||
- LONG Entry Ask, LONG Exit Bid (BID-ASK)
|
||||
- SHORT Entry Bid, SHORT Exit Ask
|
||||
- echte bid/ask-Spread NICHT doppelt (Bid/Ask-Modus)
|
||||
- synthetischer Spread korrekt (Single-Price-Modus)
|
||||
|
||||
**Slippage/Cost:**
|
||||
- Slippage Long/Short adversarial
|
||||
- Commission korrekt (fix+%)
|
||||
|
||||
**Intrabar/Gap:**
|
||||
- Stop-only, Target-only, Stop+Target gleiche Bar
|
||||
- Gap über Stop, Gap über Target
|
||||
- PESSIMISTIC/OPTIMISTIC unterscheidbar
|
||||
|
||||
**Feed/Klassifizierung:**
|
||||
- REFERENCE korrekt markiert
|
||||
- BROKER_REPLAY + REFERENCE → fail-closed
|
||||
|
||||
**Reproduzierbarkeit:**
|
||||
- gleicher Input → identisches Ergebnis
|
||||
- andere Execution-Version → anderer run_hash
|
||||
|
||||
**Regression:**
|
||||
- Legacy unverändert
|
||||
|
||||
---
|
||||
|
||||
## OFFENE ENTSCHEIDUNGEN (für Christian)
|
||||
|
||||
1. **Spread-Anwendung**: heutiger doppelter Entry+Exit-Spread → auf **einmaliger Roundtrip** oder je Seite ändern? Empfehlung: je Seite (realistisch).
|
||||
2. **Intrabar-Default**: PESSIMISTIC (heutig, konservativ) als Standard bis Tick? Oder OPTIMISTIC?
|
||||
3. **Slippage-Form**: deterministisch (Punkte) oder stochastisch (Seed)? Empfehlung: deterministisch default, stochastisch nur mit Seed+Hash.
|
||||
4. **Cost-Modell-Version**: initial simple (fix+%, Spread/Punkte) → spätere Finanzierung/Swap/GS-Premium nachgeschaltet?
|
||||
5. **Bid/Ask-Datenmodell**: sollen V2-bid/ask OHLC-Daten direkt in Engine (execution_model=APPROXIMATION) oder erst als REFERENCE-Feed (MARKET_SIMULATION) weitergegeben werden? Empfehlung: bid/ask zuerst nur in `load_bars_with_quality`, Engine-Pfad weiterhin single, bis Fill implementiert.
|
||||
6. **M13**: Execution-Costs fix → ja (nicht optimizierbar) bestätigt.
|
||||
7. **feed_type-Klassifizierung**: MARKT_SIMULATION vs BROKER_APPROXIMATION Bezeichnungen beibehalten?
|
||||
|
||||
---
|
||||
|
||||
## EXAKTER NÄCHSTER IMPLEMENTIERUNGSSCHRITT
|
||||
|
||||
Sobald Christian die offenen Entscheidungen freigibt, ist der **1. Schritt von Phase 10**:
|
||||
1. **ExecutionContext-Dataclass** (execution_model, spread_model, slippage_model, cost_model, intrabar_policy, price_basis, feed_type + je *_version) — **ausser** DatasetContext, reine Ausführungs-Konfiguration.
|
||||
2. Engine lädt als Einzelz: `execution_model` in `BacktestRequest`.
|
||||
3. Tests: deterministisch, Hash-Integration, Legacy unverändert.
|
||||
|
||||
**NOCH NICHT implementiert** (verboten bis Freigabe): Bid/Ask-Fill, Spread-Änderung, Slippage-Änderung, Kostenmodell-Änderung, Intrabar-Ausführungslogik, Jahresbackfill, IG-Calls, Orders, Docker-Netzwerkänderung.
|
||||
Loading…
Reference in a new issue