9f10f9000e
Neuer Abschnitt "Konfiguration" im Dashboard, aus dem pydantic-Schema erzeugt:
76 Felder in 13 Bereichen mit Kurzbeschreibung, typgerechtem Eingabefeld und den
Grenzen aus dem Modell. 70 davon sind änderbar, 45 greifen sofort, 31 sind als
neustartpflichtig markiert. Dazu GET und POST /control/config sowie
/control/config/reset.
Overlay statt Direktschreiben
- config.yaml ist im Container read-only eingehängt. Änderungen landen deshalb in
/data/config.overrides.yaml und werden beim Start über die Basiskonfiguration
gelegt. Rangfolge: YAML, dann ${ENV}, dann TRADEMIND__-Variablen, dann Overlay.
- Gespeichert wird nur, was vom Basiswert abweicht. Ein auf den Ausgangswert
zurückgestelltes Feld verschwindet wieder aus dem Overlay, damit spätere
Änderungen an config.yaml dort erneut durchschlagen.
- Beschädigte oder ungültige Overlays werden protokolliert und ignoriert, statt
den Start zu blockieren.
Übernehmen zur Laufzeit
- apply_config hängt die Laufzeitobjekte auf die neuen Teilkonfigurationen um
(Risiko, Strategie, Regelwerk, Lernmodell, Paper-Broker, Notifier, Log-Level).
- Was nur beim Aufbau ausgewertet wird - Börsenclient, Symbole, Timeframe,
Startkapital, Datenbank, Socket - meldet der Store als neustartpflichtig.
Nebenbei behoben: Der Handels-Loop las Abfrageintervall und Historienlänge nur
einmal vor der Schleife. Eine Änderung an poll_interval_seconds hätte nie
gegriffen; beide werden jetzt je Durchlauf frisch gelesen.
Drei Ausnahmen von "komplett", bewusst gesetzt
- exchange.api_key/api_secret/password/uid werden maskiert angezeigt und nicht
entgegengenommen. Sonst könnte jeder mit Zugriff auf den Port die
Börsenschlüssel auslesen oder austauschen.
- mode lässt sich zwischen paper und backtest umstellen, nicht auf live.
- live_confirmation ist nicht schreibbar.
Zusammen verhindern sie, dass sich der Bot über das Netz schrittweise auf
Echtgeldhandel umstellen lässt.
222 Tests (36 neue), ruff sauber. Darunter Prüfungen, dass Geheimnisse in keiner
Antwort auftauchen und dass Tippfehler in RESTART_REQUIRED oder NON_WRITABLE
auffallen. Im Browser durchgeklickt: Änderung sofort wirksam, neustartpflichtige
Felder korrekt gemeldet und nach Neustart aktiv, Zurücksetzen einzeln und
komplett, alle Schutzregeln mit HTTP 400 samt lesbarer Begründung.
542 lines
23 KiB
Markdown
542 lines
23 KiB
Markdown
# TradeMind
|
||
|
||
Ein per Podman deploybarer Krypto-Trading-Bot mit drei Betriebsarten:
|
||
|
||
| Modus | Kurse | Orders | Lernen | Zweck |
|
||
|------------|--------------|------------------|--------|------------------------------------------|
|
||
| `paper` | live | simuliert | ja | Dauerbetrieb ohne Risiko — **Standard** |
|
||
| `backtest` | historisch | simuliert | ja | Strategie und Parameter bewerten |
|
||
| `live` | live | echt | optional | Echtgeldhandel |
|
||
|
||
Die Börsenanbindung läuft über [ccxt](https://github.com/ccxt/ccxt) — Binance, Kraken, Coinbase,
|
||
Bybit, OKX, KuCoin, Bitget, Gate.io, MEXC und rund 100 weitere sind allein über den
|
||
Konfigurationsschlüssel `exchange.id` erreichbar (`trademind exchanges` listet alle auf).
|
||
|
||
> **Hinweis zum Risiko.** Der Bot ist ein Werkzeug, keine Ertragsgarantie und keine
|
||
> Anlageberatung. Die mitgelieferte Strategie ist eine funktionsfähige Grundlage, kein
|
||
> erprobtes Handelssystem — im Backtest unten liegt sie deutlich hinter Buy & Hold.
|
||
> Vor jedem Live-Einsatz gehören eigene Backtests, ein langer Paper-Lauf und eine bewusste
|
||
> Entscheidung über den Kapitaleinsatz. Der Live-Modus ist doppelt abgesichert und muss
|
||
> ausdrücklich freigeschaltet werden.
|
||
|
||
---
|
||
|
||
## Schnellstart
|
||
|
||
```bash
|
||
git clone <repo> && cd Trademind_Claude
|
||
cp config/config.example.yaml config/config.yaml
|
||
cp config/trademind.env.example config/trademind.env
|
||
podman build --format docker -t trademind:latest -f Containerfile .
|
||
podman-compose up -d
|
||
```
|
||
|
||
`--format docker` sorgt dafür, dass der eingebaute HEALTHCHECK ins Image übernommen wird —
|
||
das OCI-Format kennt die Anweisung nicht. Compose und Quadlet bringen ihren eigenen
|
||
Healthcheck mit, dort spielt das Format keine Rolle.
|
||
|
||
Dashboard: `http://<host>:8080/` · Logs: `podman-compose logs -f`
|
||
|
||
Ohne Zugangsdaten läuft der Bot im Paper-Modus auf echten Live-Kursen und beginnt sofort zu
|
||
lernen. Für den Start werden nur öffentliche Marktdaten gelesen — kein API-Schlüssel nötig.
|
||
|
||
### Ohne Container
|
||
|
||
```bash
|
||
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
|
||
pip install -e ".[dev]"
|
||
trademind backtest --config config/config.yaml --bars 6000 --fresh-model
|
||
trademind run --config config/config.yaml
|
||
```
|
||
|
||
---
|
||
|
||
## Deployment mit Podman
|
||
|
||
### Variante 1 — podman-compose
|
||
|
||
```bash
|
||
podman-compose up -d # starten
|
||
podman-compose logs -f # verfolgen
|
||
podman-compose down # stoppen
|
||
```
|
||
|
||
Port 8080 wird auf allen Interfaces veröffentlicht — das Dashboard ist damit standardmäßig
|
||
von anderen Rechnern erreichbar.
|
||
|
||
> **Sicherheit.** Die lesenden Endpunkte sind **nicht authentifiziert** — wer den Port
|
||
> erreicht, sieht Kontostand, offene Positionen und die gesamte Trade-Historie. Dazu kommen
|
||
> die Steuerbefehle unter `/control/…` (Training anstoßen, Lernen umschalten), die sich mit
|
||
> `server.control_token` schützen lassen und das auch sollten. Gehandelt oder konfiguriert
|
||
> werden kann über HTTP in keinem Fall. In offenen Netzen deshalb einen Reverse Proxy mit
|
||
> Authentifizierung davorsetzen, den Zugriff per Firewall auf bekannte Quell-IPs begrenzen
|
||
> oder auf rein lokalen Zugriff zurückstellen:
|
||
>
|
||
> | Datei | lokal statt offen |
|
||
> |------------------------------|----------------------------------|
|
||
> | `podman-compose.yml` | `- "127.0.0.1:8080:8080"` |
|
||
> | `deploy/trademind.container` | `PublishPort=127.0.0.1:8080:8080`|
|
||
>
|
||
> Ganz abschalten lässt sich der Server über `server.enabled: false` in der Konfiguration
|
||
> oder `trademind run --no-server`; der Container-Healthcheck braucht ihn allerdings.
|
||
|
||
> **Windows und macOS.** Dort läuft Podman in einer VM (`podman machine`), die
|
||
> veröffentlichte Ports nicht in jeder Konstellation an den Host weiterreicht. Ist das
|
||
> Dashboard nicht erreichbar, mit `podman machine ssh curl -s localhost:8080/health`
|
||
> gegenprüfen — antwortet das, liegt es an der VM-Weiterleitung, nicht am Bot. Auf Linux —
|
||
> dem Ziel für den Dauerbetrieb — greift die Veröffentlichung unmittelbar.
|
||
|
||
### Variante 2 — einzelner Container
|
||
|
||
```bash
|
||
podman volume create trademind-data
|
||
podman run -d --name trademind \
|
||
--restart=unless-stopped \
|
||
--env-file config/trademind.env \
|
||
-v ./config:/config:ro,Z \
|
||
-v trademind-data:/data:Z \
|
||
-p 8080:8080 \
|
||
--security-opt no-new-privileges \
|
||
trademind:latest
|
||
```
|
||
|
||
### Variante 3 — systemd über Quadlet (empfohlen für Dauerbetrieb)
|
||
|
||
```bash
|
||
mkdir -p ~/.config/containers/systemd ~/.config/trademind
|
||
cp deploy/trademind.container deploy/trademind-data.volume ~/.config/containers/systemd/
|
||
cp config/config.yaml config/trademind.env ~/.config/trademind/
|
||
loginctl enable-linger $USER
|
||
systemctl --user daemon-reload
|
||
systemctl --user start trademind
|
||
journalctl --user -u trademind -f
|
||
```
|
||
|
||
Der Container läuft als UID 10001 ohne zusätzliche Rechte. `podman stop` sendet SIGTERM; die
|
||
Engine beendet den laufenden Durchlauf, sichert Modell und Zustand und fährt sauber herunter.
|
||
|
||
### Persistenz
|
||
|
||
Alles Wichtige liegt im Volume `/data`:
|
||
|
||
| Pfad | Inhalt |
|
||
|-----------------------------|-----------------------------------------------------------|
|
||
| `/data/trademind.sqlite3` | Trades, Equity-Kurve, Laufzeitzustand |
|
||
| `/data/models/adaptive.npz` | Modellgewichte, Normalisierung, Erfahrungsspeicher |
|
||
|
||
Ohne dieses Volume geht bei jedem Neustart der gesamte Lernfortschritt verloren.
|
||
|
||
---
|
||
|
||
## Konfiguration
|
||
|
||
Alles läuft über `config/config.yaml`. Geheimnisse kommen über Umgebungsvariablen dazu:
|
||
|
||
```yaml
|
||
exchange:
|
||
id: ${TRADEMIND_EXCHANGE:-binance}
|
||
api_key: ${TRADEMIND_API_KEY}
|
||
api_secret: ${TRADEMIND_API_SECRET}
|
||
password: ${TRADEMIND_API_PASSWORD} # OKX, KuCoin, Coinbase Advanced, Bitget
|
||
sandbox: true # Testnet der Börse
|
||
```
|
||
|
||
Drei Ebenen, in dieser Reihenfolge:
|
||
|
||
1. Werte in der YAML-Datei
|
||
2. `${VAR}` / `${VAR:-fallback}` — aus der Umgebung eingesetzt
|
||
3. `TRADEMIND__ABSCHNITT__SCHLUESSEL` — überschreibt einzelne Werte punktuell,
|
||
z. B. `TRADEMIND__RISK__MAX_OPEN_POSITIONS=5`
|
||
|
||
Die vollständig kommentierte Vorlage steht in
|
||
[config/config.example.yaml](config/config.example.yaml).
|
||
|
||
### Börse wechseln
|
||
|
||
```bash
|
||
trademind exchanges --search kraken
|
||
```
|
||
|
||
Dann `exchange.id` setzen. Handelspaare in ccxt-Schreibweise (`BTC/USDT`, `ETH/EUR`);
|
||
alle Symbole müssen dieselbe Quote-Währung haben, sonst bricht der Start mit einer
|
||
verständlichen Meldung ab.
|
||
|
||
### Live-Modus freischalten
|
||
|
||
Zwei Bedingungen müssen erfüllt sein, sonst startet der Bot nicht:
|
||
|
||
```yaml
|
||
mode: live
|
||
live_confirmation: I_UNDERSTAND_THE_RISK
|
||
exchange:
|
||
api_key: ...
|
||
api_secret: ...
|
||
```
|
||
|
||
API-Schlüssel bitte ausschließlich mit **Handelsrecht** anlegen — Auszahlungen niemals
|
||
erlauben — und wenn die Börse es anbietet auf die Server-IP beschränken. Zuerst mit
|
||
`sandbox: true` gegen das Testnet fahren.
|
||
|
||
---
|
||
|
||
## Wie der Bot lernt
|
||
|
||
Die Strategie besteht aus zwei Schichten:
|
||
|
||
**1. Regelwerk** (`strategy.rules`) — erzeugt Kandidaten für Einstiege: EMA-Kreuzung nach
|
||
oben mit RSI- und Trendfilter, dazu Rücksetzer-Einstiege bei überverkauftem RSI im
|
||
Aufwärtstrend. Ausstiege über EMA-Kreuzung nach unten oder nachlassendes Momentum, dazu
|
||
immer ATR-basierter Stop und Kursziel.
|
||
|
||
**2. Lernmodell** (`strategy.learner`) — eine online trainierte logistische Regression über
|
||
18 skalenfreie Merkmale (EMA-Abstände, RSI und dessen Steigung, MACD-Histogramm, ATR in
|
||
Prozent, Volatilitätsverhältnis, Momentum, Donchian-Lage, Volumen-z-Score, Kerzenform,
|
||
Tageszeit). Sie schätzt für jeden Kandidaten die Gewinnwahrscheinlichkeit und lässt nur
|
||
Signale oberhalb von `entry_threshold` durch.
|
||
|
||
Trainiert wird aus drei Quellen:
|
||
|
||
| Quelle | Gewicht | Wofür |
|
||
|-----------------------|---------|--------------------------------------------------------------|
|
||
| Reale Trade-Ergebnisse| 3,0 | Das eigentliche Ziel: hat sich der Trade gelohnt? |
|
||
| Signal-Shadow-Labels | 1,0 | **Jeder** Kandidat wird nachträglich bewertet — auch abgelehnte |
|
||
| Hintergrund-Stichproben | 0,5 | Regelmäßige Marktzustände, damit genug Daten zusammenkommen |
|
||
|
||
Gelabelt wird nach der Triple-Barrier-Methode: Ein Signal gilt als Treffer, wenn der Kurs
|
||
innerhalb von `label_horizon_bars` das Ziel (`label_target_bps`) erreicht, ohne vorher um
|
||
denselben Betrag zu fallen. Läuft das Fenster ohne Berührung ab, entscheidet der Schlusskurs.
|
||
|
||
Zwei Details sind dabei wichtig:
|
||
|
||
- **Off-Policy-Lernen** — auch abgelehnte Signale werden gelabelt. Der Bot lernt also aus
|
||
Trades, die er *nicht* gemacht hat, und kann eine zu strenge Schwelle selbst korrigieren.
|
||
- **Exploration** — `exploration_rate` (Standard 5 %) handelt gelegentlich bewusst gegen das
|
||
Modell. Ohne das würde es seine eigenen Vorurteile nie widerlegen.
|
||
|
||
**Kaltstart.** Ein frisches Modell würde bei 5-Minuten-Kerzen Tage brauchen, um die
|
||
Aufwärmphase zu durchlaufen. Deshalb lernt der Bot beim ersten Start automatisch aus
|
||
`bootstrap_bars` historischen Kerzen vor — in der Praxis rund 3 Sekunden statt einer Woche:
|
||
|
||
```
|
||
Modell ist untrainiert – lerne aus bis zu 3000 historischen Kerzen vor …
|
||
Vorlernen abgeschlossen: 662 neue Beobachtungen (gesamt 662), Modell einsatzbereit
|
||
```
|
||
|
||
Nachtrainieren lässt sich jederzeit — per Knopf im Dashboard oder über
|
||
`trademind backtest --save-model`, siehe [Training aus dem Dashboard anstoßen](#training-aus-dem-dashboard-anstoßen).
|
||
|
||
Solange das Modell nicht warm ist (`warmup_samples`), entscheidet allein das Regelwerk.
|
||
Die Qualität lässt sich im Status unter `strategy.learner.online_accuracy` verfolgen — das ist
|
||
eine *prequentielle* Messung: erst vorhersagen, dann lernen, also keine Selbstbewertung auf
|
||
bereits gesehenen Daten.
|
||
|
||
Im Live-Modus lässt sich das Weiterlernen mit `freeze_in_live: true` einfrieren, wenn ein
|
||
im Paper-Betrieb gereiftes Modell unverändert bleiben soll.
|
||
|
||
---
|
||
|
||
## Risikomanagement
|
||
|
||
Vor jeder Order greifen mehrere unabhängige Grenzen:
|
||
|
||
- `max_position_pct` — Anteil der Equity je Position
|
||
- `max_total_exposure_pct` — Summe aller Positionen
|
||
- `max_open_positions` — parallele Positionen
|
||
- ATR-basierter Stop-Loss und Take-Profit, optional nachziehender Stop
|
||
- `cooldown_bars_after_exit` — Pause pro Symbol nach einem Ausstieg
|
||
- `min_notional` sowie die Mindestgrößen und Rundungsschritte der Börse
|
||
|
||
Dazu zwei Notbremsen:
|
||
|
||
- **`max_daily_loss_pct`** — Handel pausiert bis zum nächsten UTC-Tag.
|
||
- **`max_drawdown_pct`** — dauerhafter Stopp bis zum Neustart; offene Positionen werden
|
||
geschlossen.
|
||
|
||
Ausstiege werden nie durch die Liquiditätsgrenze gedrosselt: Das Risikomanagement muss
|
||
jederzeit vollständig aus einer Position herauskommen.
|
||
|
||
---
|
||
|
||
## Simulation
|
||
|
||
Der Paper-Broker bildet die Kosten nach, an denen Strategien in der Praxis scheitern:
|
||
|
||
```yaml
|
||
paper:
|
||
fee_rate: 0.001 # 0,1 % je Seite
|
||
slippage_bps: 5 # Ausführung 5 bps schlechter als der Referenzkurs
|
||
max_volume_participation: 0.1 # höchstens 10 % des Kerzenvolumens
|
||
```
|
||
|
||
Zusätzlich werden Mengen auf die Präzision der Börse abgerundet, Käufe auf das verfügbare
|
||
Guthaben begrenzt und Verkäufe auf den tatsächlichen Bestand. Ein Round-Trip ohne
|
||
Kursbewegung kostet damit realistisch ~0,3 %.
|
||
|
||
---
|
||
|
||
## Kommandos
|
||
|
||
```bash
|
||
trademind run --config config/config.yaml # Dauerbetrieb (paper oder live)
|
||
trademind backtest --config config/config.yaml # historischer Durchlauf
|
||
trademind validate --config config/config.yaml # Konfiguration + Börsenverbindung prüfen
|
||
trademind report --config config/config.yaml # Ergebnisse aus der Datenbank
|
||
trademind exchanges --search kraken # verfügbare Börsen
|
||
```
|
||
|
||
Im Container davor `podman exec -it trademind` setzen, z. B.:
|
||
|
||
```bash
|
||
podman exec -it trademind trademind report --config /config/config.yaml
|
||
```
|
||
|
||
### Backtest
|
||
|
||
```bash
|
||
trademind backtest -c config/config.yaml --bars 20000 --fresh-model --save-model --out-dir out/
|
||
trademind backtest -c config/config.yaml --start 2025-01-01T00:00:00Z --end 2025-06-30T23:59:59Z
|
||
trademind backtest -c config/config.yaml --csv-dir data/csv --json
|
||
```
|
||
|
||
| Option | Wirkung |
|
||
|------------------|--------------------------------------------------------------------|
|
||
| `--fresh-model` | untrainiertes Modell — sonst wird auf dem gespeicherten aufgesetzt |
|
||
| `--save-model` | Ergebnis nach `learner.model_path` schreiben (Vortraining) |
|
||
| `--out-dir` | `trades.csv`, `equity.csv` und `report.json` ablegen |
|
||
| `--csv-dir` | eigene OHLCV-Daten statt Börsenabruf |
|
||
| `--seed` | reproduzierbare Läufe (Exploration ist zufällig) |
|
||
|
||
CSV-Format: `timestamp,open,high,low,close,volume`, eine Datei je Symbol
|
||
(`BTC_USDT.csv`). Der Zeitstempel darf in Sekunden, Millisekunden oder ISO-8601 stehen.
|
||
|
||
Der Backtest ist ein Walk-Forward-Lauf: Das Modell trainiert währenddessen ganz normal
|
||
weiter, es gibt also keine getrennte Trainings- und Testphase.
|
||
|
||
Ein Beispiellauf über 20 Tage BTC/USDT und ETH/USDT (5m, frisches Modell):
|
||
|
||
```
|
||
Endkapital 9818.92 USDT Trades 29 (4/25)
|
||
Gesamtrendite -1.81 % Trefferquote 13.8 %
|
||
Max. Drawdown 2.23 % Profit-Faktor 0.17
|
||
Buy & Hold BTC +23.81 % Gebühren 114.84 USDT
|
||
```
|
||
|
||
Genau dafür ist der Backtest da: Die Standardparameter schlagen in einem starken
|
||
Aufwärtstrend kein Buy & Hold, und der Bot sagt das offen. Kürzere Zeiträume, andere
|
||
Timeframes und Parameter gehören ausprobiert, bevor auch nur ein Paper-Euro fließt.
|
||
|
||
---
|
||
|
||
## Monitoring
|
||
|
||
| Endpunkt | Inhalt |
|
||
|--------------|-------------------------------------------------------------|
|
||
| `/` | Dashboard: Equity, Positionen, Trades, Modellzustand, Training |
|
||
| `/health` | Liveness — nutzt der Container-Healthcheck |
|
||
| `/ready` | Readiness (503, solange der Bot nicht sauber läuft) |
|
||
| `/status` | vollständiger Zustand als JSON |
|
||
| `/positions` | offene Positionen |
|
||
| `/trades` | letzte Trades (`?limit=100`) |
|
||
| `/metrics` | Prometheus-Textformat |
|
||
|
||
```bash
|
||
curl -s localhost:8080/status | jq '.portfolio, .strategy.learner'
|
||
curl -s localhost:8080/metrics | grep trademind_portfolio
|
||
```
|
||
|
||
Optionale Benachrichtigungen über `notifications.webhook_url` — ein Payload bedient sowohl
|
||
Slack als auch Discord.
|
||
|
||
---
|
||
|
||
## Handel und Training aus dem Dashboard steuern
|
||
|
||
### Automatisierter Handel
|
||
|
||
Der Abschnitt **Automatisierter Handel** zeigt den Zustand und schaltet ihn um — in beiden
|
||
Modi, simuliert wie echt. Standardmäßig startet der Bot handelnd (`trading.autostart: true`);
|
||
mit `autostart: false` sammelt er zunächst nur Daten und wartet auf die Freigabe.
|
||
|
||
Pausiert bedeutet **nur: keine neuen Einstiege**. Alles andere läuft weiter:
|
||
|
||
| Auch pausiert | Pausiert ausgesetzt |
|
||
|---|---|
|
||
| Marktdaten werden abgerufen | Neue Positionen eröffnen |
|
||
| Signale werden ausgewertet und gelabelt | |
|
||
| Das Modell trainiert weiter | |
|
||
| Offene Positionen bleiben unter Stop-/Ziel-Überwachung | |
|
||
|
||
Der Bot lernt also durchgehend weiter, auch wenn er nicht handelt. Auf identischen Daten:
|
||
|
||
```
|
||
Handel aktiv Trades=9 Beobachtungen=99 Shadow=90 Trade-Labels=9 nur-gelernte Signale=0
|
||
Handel pausiert Trades=0 Beobachtungen=90 Shadow=90 Trade-Labels=0 nur-gelernte Signale=9
|
||
```
|
||
|
||
Der Unterschied sind genau die neun Trade-Labels, die ohne Handel nicht entstehen können —
|
||
die Shadow-Labels aus dem Marktgeschehen laufen unverändert weiter.
|
||
|
||
> **Live-Modus.** Das Starten verlangt zusätzlich die Bestätigung `START_LIVE_TRADING`
|
||
> (das Dashboard fragt sie ab, per HTTP als `"confirm"` im Body). **Pausieren** geht immer
|
||
> ohne Bestätigung — im Zweifel muss man schnell anhalten können. Abschalten lässt sich die
|
||
> Rückfrage mit `trading.require_confirmation_for_live: false`.
|
||
>
|
||
> Die Kombination *Live-Modus + Port nicht nur lokal + kein `control_token`* wird **nicht
|
||
> bedient**: Der Bot schaltet die Steuerung dann beim Start ab und sagt das im Log. Sonst
|
||
> könnte jeder im Netz echten Handel starten. Mit Token oder auf `127.0.0.1` steht sie
|
||
> wieder zur Verfügung.
|
||
|
||
### Konfiguration
|
||
|
||
Der Abschnitt **Konfiguration** zeigt alle 76 Felder, nach Bereichen gruppiert, mit
|
||
Kurzbeschreibung und den Grenzen aus dem Schema. 70 davon sind direkt änderbar.
|
||
|
||
Weil `config.yaml` im Container read-only eingehängt ist, landen Änderungen als Overlay in
|
||
`/data/config.overrides.yaml` und werden beim Start über die Basiskonfiguration gelegt.
|
||
Die Rangfolge, von schwach nach stark:
|
||
|
||
1. `config.yaml`
|
||
2. `${ENV}`-Platzhalter darin
|
||
3. `TRADEMIND__ABSCHNITT__SCHLUESSEL`-Umgebungsvariablen
|
||
4. Overlay aus dem Dashboard
|
||
|
||
Gespeichert wird nur, was vom Basiswert abweicht — stellst du ein Feld auf seinen
|
||
Ausgangswert zurück, verschwindet es wieder aus dem Overlay und spätere Änderungen an
|
||
`config.yaml` schlagen dort wieder durch. Einzelne Felder oder alles auf einmal lassen sich
|
||
über die Knöpfe zurücksetzen; die Overlay-Datei zu löschen hat denselben Effekt.
|
||
|
||
Jedes Feld ist markiert, wenn es **einen Neustart braucht** (31 Felder — Börsenclient,
|
||
Symbole, Timeframe, Datenbank, Socket und alles andere, was nur beim Aufbau ausgewertet
|
||
wird). Der Rest greift sofort: Risikoregeln, Strategie-Parameter, Lernmodell, Gebühren und
|
||
Slippage der Simulation, Abfrageintervall, Benachrichtigungen, Log-Level.
|
||
|
||
Ungültige Eingaben werden abgelehnt, bevor irgendetwas übernommen wird — inklusive
|
||
feldübergreifender Regeln:
|
||
|
||
```
|
||
HTTP 400 — Ungültige Werte – strategy.rules: strategy.rules.fast_ema muss kleiner als slow_ema sein
|
||
```
|
||
|
||
> **Drei Felder sind bewusst ausgenommen** und bleiben der Konfigurationsdatei
|
||
> beziehungsweise der Umgebung vorbehalten:
|
||
>
|
||
> | Feld | Grund |
|
||
> |---|---|
|
||
> | `exchange.api_key` / `api_secret` / `password` / `uid` | Werden nie ausgeliefert (maskiert als „gesetzt"/„nicht gesetzt") und nicht entgegengenommen. Sonst könnte jeder mit Zugriff auf den Port die Börsenschlüssel auslesen oder austauschen. |
|
||
> | `mode: live` | Wechsel zwischen `paper` und `backtest` geht; auf Echtgeld umstellen nicht. |
|
||
> | `live_confirmation` | Sonst wäre die Live-Freigabe aus dem Netz setzbar. |
|
||
>
|
||
> Zusammen verhindert das, dass jemand über das Dashboard schrittweise auf Echtgeldhandel
|
||
> umstellt.
|
||
|
||
Per HTTP:
|
||
|
||
```bash
|
||
curl -X POST localhost:8080/control/config -H 'Content-Type: application/json' -H "X-TradeMind-Token: $TOKEN" -d '{"risk.max_open_positions": 5, "strategy.learner.entry_threshold": 0.6}'
|
||
```
|
||
|
||
### Training
|
||
|
||
Im Abschnitt **Training** stehen zwei Bedienelemente:
|
||
|
||
**Historisch nachtrainieren.** Anzahl Kerzen wählen (500 – 50 000 je Symbol), Knopf drücken.
|
||
Der Bot lädt die Historie, läuft sie mit derselben Logik wie ein Backtest durch — **ohne zu
|
||
handeln** — und speichert das Modell danach. Der Fortschritt erscheint direkt darunter:
|
||
|
||
```
|
||
Fertig in 4.3s: +1099 Beobachtungen (gesamt 1753), Modell einsatzbereit, gespeichert
|
||
```
|
||
|
||
Ein zweiter Start wird abgelehnt, solange einer läuft. Handelsdurchlauf und Nachtraining
|
||
schließen sich gegenseitig aus, der Live-Betrieb pausiert also für die paar Sekunden.
|
||
Die Labels des laufenden Betriebs bleiben davon unberührt.
|
||
|
||
**Kontinuierliches Lernen.** Schaltet das Online-Lernen im laufenden Betrieb an und aus.
|
||
Ausgeschaltet handelt der Bot weiter, verändert das Modell aber nicht mehr — praktisch, um
|
||
einen erreichten Stand einzufrieren, ohne den Bot anzuhalten.
|
||
|
||
Dieselben Aktionen per HTTP:
|
||
|
||
```bash
|
||
curl -X POST localhost:8080/control/train/history -H 'Content-Type: application/json' -H "X-TradeMind-Token: $TOKEN" -d '{"bars": 5000}'
|
||
```
|
||
|
||
| Endpunkt | Methode | Wirkung |
|
||
|--------------------------------|---------|--------------------------------------------|
|
||
| `/control/config` | GET | Alle Felder mit Wert, Typ, Grenzen und Markierungen |
|
||
| `/control/config` | POST | `{"risk.max_open_positions": 5}` — ändern und sichern |
|
||
| `/control/config/reset` | POST | `{}` oder `{"paths": [...]}` — Overlay verwerfen |
|
||
| `/control/trading` | GET | Zustand des automatisierten Handels |
|
||
| `/control/trading` | POST | `{"enabled": true}` — Handel starten/pausieren (live zusätzlich `"confirm"`) |
|
||
| `/control/training` | GET | Zustand des letzten/laufenden Trainings |
|
||
| `/control/train/history` | POST | `{"bars": 5000}` — Nachtraining anstoßen |
|
||
| `/control/train/live` | POST | `{"enabled": false}` — Lernen ein/aus |
|
||
|
||
> **Absicherung.** Anders als die lesenden Endpunkte verändern diese den Zustand des Bots.
|
||
> Setze deshalb `server.control_token` (bzw. `TRADEMIND_CONTROL_TOKEN`), sobald der Port
|
||
> nicht nur lokal erreichbar ist — die Steuerbefehle verlangen ihn dann im Header
|
||
> `X-TradeMind-Token`, während `/status` und Co. offen bleiben. Ohne Token warnt der Bot
|
||
> beim Start. Komplett abschalten lässt sich die Steuerung mit `server.enable_control: false`;
|
||
> die Routen sind dann nicht vorhanden (404).
|
||
>
|
||
> ```bash
|
||
> openssl rand -hex 24
|
||
> ```
|
||
|
||
---
|
||
|
||
## Aufbau
|
||
|
||
```
|
||
src/trademind/
|
||
├── cli.py Kommandozeile
|
||
├── app.py Zusammenbau aus der Konfiguration
|
||
├── config.py Konfigurationsmodell (pydantic) + ${ENV}-Auflösung
|
||
├── engine.py Handelsschleife und Bar-Verarbeitung
|
||
├── backtest.py Walk-Forward-Durchlauf und Auswertung
|
||
├── strategy.py Regelwerk und lernende Strategie
|
||
├── learner.py Online-Logistikregression, Replay-Buffer, Persistenz
|
||
├── features.py Merkmalsvektoren (vektorisiert)
|
||
├── indicators.py EMA, RSI, ATR, MACD, Bollinger, Donchian, ROC
|
||
├── risk.py Positionsgröße, Stops, Notbremsen
|
||
├── portfolio.py Positionen, Equity, Kennzahlen
|
||
├── broker.py Paper- und Live-Ausführung
|
||
├── exchange.py ccxt-Client und Börsen-Metadaten
|
||
├── data.py Marktdaten: live, CSV, Replay
|
||
├── storage.py SQLite-Persistenz
|
||
├── server.py HTTP-Status, Metriken, Dashboard
|
||
└── notify.py Webhook-Benachrichtigungen
|
||
```
|
||
|
||
Die Bar-Verarbeitung in `engine.process_bar` ist für alle drei Modi identisch — ausgetauscht
|
||
werden nur Datenquelle und Broker. Was im Backtest passiert, passiert live genauso.
|
||
|
||
### Entwicklung
|
||
|
||
```bash
|
||
pip install -e ".[dev]"
|
||
pytest -q # 128 Tests
|
||
ruff check .
|
||
```
|
||
|
||
---
|
||
|
||
## Bekannte Grenzen
|
||
|
||
- **Nur Long, nur Spot.** Keine Short-Positionen, keine Hebel, keine Futures.
|
||
- **Bar-getaktet.** Entscheidungen fallen bei Kerzenschluss, nicht tick-genau. Bei `1m` ist
|
||
die Latenz zwischen Signal und Ausführung spürbar.
|
||
- **Kein Order-Abgleich im Live-Modus.** Der Bot führt seine Positionsbuchhaltung intern;
|
||
manuelle Trades auf demselben Konto bringen sie durcheinander. Ein eigenes (Sub-)Konto
|
||
verwenden.
|
||
- **Lineares Modell.** Bewusst so gewählt: nachvollziehbar (`/status` zeigt alle Gewichte),
|
||
robust bei wenig Daten, kein Overfitting-Zoo. Es findet keine nichtlinearen Muster.
|
||
- **Marktrisiko bleibt.** Backtests sagen wenig über die Zukunft, und ein lernender Filter
|
||
macht aus einer schwachen Strategie keine starke.
|
||
|
||
---
|
||
|
||
## Lizenz
|
||
|
||
MIT
|