docs: Design-Spec trade-kuns (Multi-Pair Donchian-Trendfolge, Walk-Forward-Gate)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
171
docs/specs/2026-06-09-trade-kuns-design.md
Normal file
171
docs/specs/2026-06-09-trade-kuns-design.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# trade-kuns — Multi-Pair-Trendfolge-Bot (Design)
|
||||||
|
|
||||||
|
**Datum:** 2026-06-09
|
||||||
|
**Status:** Entwurf zur Review
|
||||||
|
**Entscheidungen:** Neuer Bot, neues Repo · TypeScript + Bun · Paper-only · komplett eigenständig von krypto-kuns
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Was dieser Bot ist — und warum
|
||||||
|
|
||||||
|
**Ein Satz:** Der Bot kauft eines von vier Krypto-Assets (BTC, ETH, SOL, XRP), wenn dessen Preis auf dem 4-Stunden-Chart über das Hoch der letzten 20 Perioden ausbricht und der langfristige Trend aufwärts zeigt — und verkauft, wenn der Preis um 3×ATR vom Höchststand zurückfällt.
|
||||||
|
|
||||||
|
**Warum dieser Ansatz** (Lehren aus krypto-kuns v1, 8 Monate Live-Daten):
|
||||||
|
|
||||||
|
| v1-Problem | trade-kuns-Antwort |
|
||||||
|
|---|---|
|
||||||
|
| 20 bps Round-Trip-Fees fraßen den Mini-Edge der 1–15-min-Signale | 4h-Timeframe: Trades laufen Tage–Wochen, Zielbewegung 5–20 % → Fees sind Rundungsfehler |
|
||||||
|
| Ein Pair (XRP) = ein Schicksal | 4 Pairs: irgendwo trendet es meistens; kein Trade, wenn nirgends |
|
||||||
|
| R:R 0.88 bei 31 % WinRate — mathematisch chancenlos | Trailing-Stop ohne TP-Deckel: Verlierer klein (−1R), Gewinner offen (+2R bis +10R) |
|
||||||
|
| 5 Strategien, Aggregator, Gewichte, Veto, Confidence — nichts davon brachte messbaren Nutzen | Eine Regel, binär, in einem Satz erklärbar |
|
||||||
|
| Backtest in-sample optimiert → Overfitting → live rot | Walk-Forward-Validierung mit hartem Deploy-Gate (siehe §5) |
|
||||||
|
| `LongOnly`-Config griff live nie (Seed-Gap) | Config wird beim Start per Zod gegen Code-Defaults gemerged + effektive Config geloggt |
|
||||||
|
|
||||||
|
**Hinweis zu Fees:** Crypto.com berechnet 0.1 % pro Trade auf **alle** Pairs — XRP ist nicht günstiger als BTC. Entscheidend ist die Relation Fee : Zielbewegung, und die verbessert nur ein höherer Timeframe.
|
||||||
|
|
||||||
|
**Erwartungsprofil (wichtig, um live nicht nervös zu werden):** Trendfolge gewinnt nur 35–45 % der Trades. Das ist kein Defekt — der Edge kommt daraus, dass Gewinner im Schnitt 2–4× größer sind als Verlierer. Wochen ohne Trade (Seitwärtsmarkt) sind Normalbetrieb, kein Bug.
|
||||||
|
|
||||||
|
## 2. Strategie-Regeln (vollständig)
|
||||||
|
|
||||||
|
Alle Berechnungen auf **4h-Candles** (aggregiert aus 15-min-Candles).
|
||||||
|
|
||||||
|
**Entry (long-only):**
|
||||||
|
1. 4h-Candle schließt über dem Hoch der letzten 20 4h-Candles (Donchian-20-Breakout), **und**
|
||||||
|
2. Schlusskurs > EMA-200 (4h) — Trendfilter gegen Kaufen im Bärenmarkt, **und**
|
||||||
|
3. für dieses Pair ist keine Position offen, **und**
|
||||||
|
4. die Positionsgröße nach §3 ist ≥ Mindestordergröße.
|
||||||
|
|
||||||
|
**Exit (eine Regel, kein Take-Profit):**
|
||||||
|
- **Chandelier-Trailing-Stop:** höchstes Hoch seit Entry − 3×ATR(14, 4h). Der Stop wandert nur nach oben, nie nach unten. Geprüft auf **15-min-Granularität** (Low ≤ Stop → Exit zum Stop-Preis, pessimistisch).
|
||||||
|
- Initialer Stop bei Entry ≈ Entry − 3×ATR → definiert das Trade-Risiko (1R).
|
||||||
|
|
||||||
|
**Parameter (alle konfigurierbar, Defaults):**
|
||||||
|
|
||||||
|
| Parameter | Default | Walk-Forward-Grid |
|
||||||
|
|---|---|---|
|
||||||
|
| `donchianPeriod` | 20 | 20 / 40 / 55 |
|
||||||
|
| `atrPeriod` | 14 | fix |
|
||||||
|
| `atrMultiplier` | 3.0 | 2.0 / 3.0 / 4.0 |
|
||||||
|
| `trendEmaPeriod` | 200 | 100 / 200 |
|
||||||
|
| `pairs` | BTC, ETH, SOL, XRP (USDT) | fix |
|
||||||
|
| `longOnly` | true | fix |
|
||||||
|
|
||||||
|
## 3. Risiko & Positionsgrößen
|
||||||
|
|
||||||
|
- **Paper-Startkapital:** 1000 USDT.
|
||||||
|
- **Risiko pro Trade: 1 % der aktuellen Equity** (= 10 USDT initial). Positionsgröße = Risikobetrag ÷ (Entry − Initial-Stop). Beispiel: Entry 100, Stop 94 → 6 % Risiko-Distanz → Position 167 USDT.
|
||||||
|
- **Cap:** max. 30 % der Equity pro Position, max. 4 Positionen (eine pro Pair), kein Leverage, keine Shorts.
|
||||||
|
- **Fees:** 0.1 % pro Seite. **Slippage:** zusätzlich 5 bps pro Seite simuliert (konservativ).
|
||||||
|
- Kein Cooldown nötig — Re-Entry erfordert naturgemäß einen neuen Breakout.
|
||||||
|
|
||||||
|
## 4. Architektur
|
||||||
|
|
||||||
|
### 4.1 Stack
|
||||||
|
|
||||||
|
Bun 1.3 · Hono (HTTP) · Drizzle (Postgres) · Zod (Config/API-Validierung) · `bun test`. Eigene DB **`tradekuns`** in shared-postgres. Frontend: schlankes Vue 3 + Vite Dashboard.
|
||||||
|
|
||||||
|
### 4.2 Module
|
||||||
|
|
||||||
|
```
|
||||||
|
src/server/
|
||||||
|
market/ CryptoComClient (REST), CandleStore, Backfill (end_ts-Paginierung)
|
||||||
|
indicators/ ema, atr, donchian
|
||||||
|
strategy/ DonchianTrendStrategy (pure Funktion: Candles → Signal)
|
||||||
|
engine/ TradingEngine (5-min-Loop), PortfolioRisk, PaperTrader, DecisionLogger
|
||||||
|
backtest/ BacktestRunner, WalkForwardRunner, Metriken (PF, MaxDD, Sharpe, vs. Buy&Hold-BTC)
|
||||||
|
api/ Hono-Routen
|
||||||
|
db/ Drizzle-Schema + Migrations
|
||||||
|
config.ts Env (DATABASE_URL, ZITADEL_ISSUER) + Strategie-Defaults
|
||||||
|
src/frontend/ Vue 3 Dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ein Code-Pfad:** Strategie und PaperTrader sind pure Funktionen über `(candles, state) → actions`. Live füttert sie der 5-min-Loop mit frischen Candles, der Backtest mit historischem Replay — identische Logik, per Konstruktion.
|
||||||
|
|
||||||
|
### 4.3 Datenfluss (Live)
|
||||||
|
|
||||||
|
```
|
||||||
|
alle 5 min: 15m-Candles je Pair von Crypto.com → CandleStore (Dedup)
|
||||||
|
→ Stop-Check offener Positionen (15m-Lows gegen Trailing-Stop)
|
||||||
|
→ bei neuer 4h-Candle: Aggregation → Entry-Evaluation je Pair
|
||||||
|
→ PortfolioRisk (Sizing, Caps) → PaperTrader → DecisionLog
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 Datenbank (Drizzle, snake_case)
|
||||||
|
|
||||||
|
- `candles` — pair, timestamp, OHLCV, **unique(pair, timestamp)**; 15-min-Basis, ~8 Monate × 4 Pairs ≈ 93k Zeilen nach Backfill
|
||||||
|
- `paper_trades` — pair, entry/exit (Zeit+Preis), Größe, Initial-Stop, Exit-Grund, PnL netto, R-Multiple
|
||||||
|
- `positions` — offene Positionen inkl. aktuellem Trailing-Stop (übersteht Neustarts)
|
||||||
|
- `decision_logs` — pro 4h-Bar je Pair: Indikatorwerte, Signal/Blockierungsgrund, Preis + `price_after_4h/24h/72h` (Outcome-Backfill für Edge-Messung)
|
||||||
|
- `bot_state` — Equity, Running-Flag, effektive Config
|
||||||
|
- `backtest_runs` / `backtest_trades` — inkl. Walk-Forward-Fenster-Metriken (JSON)
|
||||||
|
|
||||||
|
### 4.5 API
|
||||||
|
|
||||||
|
| Route | Zweck |
|
||||||
|
|---|---|
|
||||||
|
| `GET /health` | Healthcheck (ohne Auth) |
|
||||||
|
| `GET /api/portfolio` | Equity, offene Positionen mit aktuellem Stop, Cash |
|
||||||
|
| `GET /api/trades?limit` | abgeschlossene Trades inkl. R-Multiple |
|
||||||
|
| `GET /api/candles?pair&tf&limit` | Candles (15m / 4h) |
|
||||||
|
| `GET /api/decisions?pair&limit` | DecisionLog inkl. Outcomes |
|
||||||
|
| `GET /api/stats` | PF, WR, MaxDD, Equity-Kurve, vs. Buy&Hold-BTC |
|
||||||
|
| `POST /api/bot/toggle` · `POST /api/bot/reset` | an/aus, Paper-Reset |
|
||||||
|
| `GET/PUT /api/config` | Strategie-Parameter |
|
||||||
|
| `POST /api/backtest/run` · `POST /api/backtest/walkforward` · `GET /api/backtest/runs/:id` | Backtests |
|
||||||
|
| `POST /api/data/backfill` | historische Candles laden |
|
||||||
|
|
||||||
|
Auth: JWT gegen Zitadel (`auth.kuns.dev`), wie bei den anderen kuns.dev-Apps.
|
||||||
|
|
||||||
|
### 4.6 Dashboard (Vue)
|
||||||
|
|
||||||
|
Vier Ansichten: **Portfolio** (Positionen, Equity-Kurve, Stops), **Trades** (Historie mit R-Multiples), **Markt** (4h-Charts je Pair mit Donchian-Kanal/EMA/Stops via lightweight-charts), **Backtest** (Walk-Forward-Report: Fenster-Tabelle Train vs. OOS, Equity-Kurven). Polling 30 s — bei einem 4h-System reicht das locker.
|
||||||
|
|
||||||
|
## 5. Validierung — Deploy-Gate vor Live-Schaltung
|
||||||
|
|
||||||
|
1. **Backfill:** 15-min-Candles für alle 4 Pairs so weit zurück wie die Crypto.com-API liefert (Ziel ≥ 12 Monate; XRP-1m-Historie aus krypto-kuns kann ergänzend zu 15m aggregiert werden).
|
||||||
|
2. **Walk-Forward:** Train 120 Tage → Test 30 Tage, rollierend (Schritt 30 Tage). Grid-Search (§2-Grid, 18 Kombinationen) **nur auf Train**; beste Train-Kombination läuft ungesehen über das Test-Fenster.
|
||||||
|
3. **Gate (hart) — kombiniert über alle Test-Fenster:**
|
||||||
|
- OOS-ProfitFactor ≥ 1.2 nach Fees+Slippage
|
||||||
|
- ≥ 25 OOS-Trades
|
||||||
|
- MaxDrawdown ≤ 25 %
|
||||||
|
- kein Test-Fenster mit PF < 0.5 bei ≥ 5 Trades
|
||||||
|
- Train-PF ÷ OOS-PF < 2 (Overfitting-Indikator)
|
||||||
|
4. **Fällt das Gate durch**, ist das Ergebnis „diese Regeln haben keinen handelbaren Edge" — dann werden Regeln überarbeitet (z. B. Donchian-Periode, anderer Filter), nicht das Gate. Dieses Ergebnis ist ein legitimer, einkalkulierter Ausgang.
|
||||||
|
5. **Live-Monitoring:** `/api/stats` zeigt den rollierenden Edge (Outcome-Tracking aus decision_logs) — der Frühindikator, der bei v1 fehlte.
|
||||||
|
|
||||||
|
## 6. Fehlerbehandlung
|
||||||
|
|
||||||
|
- Crypto.com-Ausfall: Retry mit Backoff (3×), Zyklus überspringen, Lücken-Backfill im nächsten Zyklus; Status in `/api/portfolio` sichtbar.
|
||||||
|
- DB-Ausfall: Engine pausiert, Healthcheck rot → Coolify-Restart.
|
||||||
|
- Neustart mit offenen Positionen: `positions` wird geladen, Trailing-Stops laufen nahtlos weiter; verpasste 15m-Bars werden nachgeholt und Stops rückwirkend geprüft.
|
||||||
|
- Pair-spezifischer Datenfehler (z. B. SOL-Feed leer): Pair wird für den Zyklus übersprungen, andere Pairs laufen weiter.
|
||||||
|
|
||||||
|
## 7. Tests
|
||||||
|
|
||||||
|
- **Unit:** EMA/ATR/Donchian gegen Referenzwerte; Chandelier-Stop (wandert nie abwärts); Sizing-Mathematik inkl. Caps; Intra-Bar-Stop-Ausführung pessimistisch.
|
||||||
|
- **Integration:** Backtest-Determinismus; Walk-Forward ohne Train/Test-Leak (konstruierter Datensatz); Restart-Recovery offener Positionen.
|
||||||
|
- **API:** Smoke-Tests gegen Test-DB.
|
||||||
|
|
||||||
|
## 8. Deployment
|
||||||
|
|
||||||
|
- Repo `trade-kuns` → Gitea, Subdomain **`trade.kuns.dev`**, Port 8080, via `deploy`-Script.
|
||||||
|
- Dockerfile multi-stage: `oven/bun` (Frontend-Build + Server), Healthcheck `/health`.
|
||||||
|
- Env: `DATABASE_URL` (DB `tradekuns` in shared-postgres), `ZITADEL_ISSUER`.
|
||||||
|
- **krypto-kuns läuft unberührt weiter** — Vergleich der beiden Paper-Bots über Wochen, bevor irgendetwas abgeschaltet wird.
|
||||||
|
|
||||||
|
## 9. Reihenfolge der Umsetzung
|
||||||
|
|
||||||
|
1. **Fundament:** Repo-Skelett, Drizzle-Schema, CryptoComClient + Backfill, Indikatoren (+ Tests)
|
||||||
|
2. **Backtest zuerst:** Strategie, PaperTrader-Logik, BacktestRunner, WalkForwardRunner → **Gate-Entscheidung** auf echten Daten
|
||||||
|
3. **Live-Engine:** 5-min-Loop, Positions-Recovery, DecisionLogger + Outcome-Backfill, API
|
||||||
|
4. **Dashboard:** 4 Views
|
||||||
|
5. **Deploy:** Gitea + Coolify + DB anlegen, `trade.kuns.dev`
|
||||||
|
|
||||||
|
Schritt 2 ist der Pivot: erst wenn das Gate besteht, wird die Live-Engine gebaut.
|
||||||
|
|
||||||
|
## 10. Nicht-Ziele
|
||||||
|
|
||||||
|
- Kein Live-Trading (keine Order-Ausführung, keine Schreib-API-Keys)
|
||||||
|
- Keine Shorts, kein Leverage, kein Intraday-Scalping
|
||||||
|
- Kein Strategie-Aggregator, keine Confidence-Scores, kein ML
|
||||||
|
- Keine Übernahme von v1-Code oder v1-Tabellen — nur die XRP-Candle-Historie wird ggf. als Backtest-Daten importiert
|
||||||
Reference in New Issue
Block a user