Drei Erweiterungen aus der vorangegangenen Analyse. Lerngeschwindigkeit - background_sample_every_n_bars von 10 auf 5. Gemessen stammen nur rund 3 % der Beobachtungen aus echten Trades; diese Stichproben sind der wirksamste Hebel. Nicht weiter gesenkt, weil benachbarte Kerzen stark korreliert sind und sich die Label-Fenster überlappen - mehr Gradientenschritte heißt dort nicht mehr Information. Funding Rate und Open Interest als Merkmale (strategy.derivatives, standardmäßig aus) - Vier zusätzliche Merkmale vom Perpetual zum jeweiligen Spot-Paar. Gehandelt wird weiterhin Spot, die Kennzahlen kommen über einen zweiten ccxt-Client mit defaultType=future. - Die Zuordnung ist lookahead-frei: Für jede Kerze gilt nur der Wert, der zu diesem Zeitpunkt bereits veröffentlicht war. - Fällt eine Quelle aus oder deckt sie weniger als min_coverage ab, bleiben die Spalten neutral. Die Modelldimension bleibt dabei stabil. - Gemessene API-Grenzen bei Binance: Open Interest reicht 30 Tage zurück, 500 Zeilen je Abruf; Funding Rate über ein Jahr. Beide Merkmale sind deshalb einzeln abschaltbar. ERGEBNIS: kein Nutzen. Zwei Backtests mit identischen Kerzen und Seed - 5m/20 Tage: Rendite -1,79 % auf -1,90 %, Accuracy 51,2 % auf 50,4 %; 15m/28 Tage: Rendite -2,22 % auf -2,67 %, LogLoss praktisch unverändert. Die Anbindung arbeitet einwandfrei (100 % Datenabdeckung), das Modell gewichtet die neuen Merkmale aber nur mit 0,01 bis 0,09 gegenüber 0,39 für ema_spread. Die Funktion bleibt aus und ist dafür da, das auf anderen Zeiträumen selbst zu prüfen - nicht weil sie sich bewährt hätte. Ollama-Erklärungen (llm, standardmäßig aus) - Neuer Dashboard-Bereich und POST /control/explain. Das Modell bekommt den Zustand als Text und gibt Text zurück; es entscheidet nichts, beeinflusst keine Order und wird nie aus dem Handels-Loop heraus aufgerufen. Der System-Prompt untersagt Anlageempfehlungen und Kursprognosen. - Bewusst nicht als Entscheider: nicht reproduzierbar, kaum backtestbar, und es würde die Nachvollziehbarkeit des linearen Modells zerstören. - Beim Test an qwen3.8:27b zeigte sich ein echter Fehler: Reasoning-Modelle legen ihre Denkschritte in ein eigenes Antwortfeld und verbrauchten dafür das gesamte Token-Budget, response blieb leer. llm.think ist jetzt standardmäßig false, die Fehlermeldung nennt Ursache und Ausweg statt nur "leere Antwort", und für ältere Ollama-Versionen ohne das Feld gibt es einen Wiederholungsversuch ohne es. Bewusst nicht enthalten: News- und Google-Trends-Sentiment. Es fehlt eine Quelle mit Point-in-Time-Historie; ohne die lässt sich das Merkmal nicht backtesten. Nach dem Ergebnis oben wäre ein unvalidiertes Merkmal der falsche Schritt. test_stop_loss_bounds_the_worst_trade läuft jetzt mit strategy.name: rules. Er hing über die geänderte Voreinstellung an zufälligem Modellverhalten, geprüft werden soll aber die Stop-Logik. 270 Tests (36 neue), ruff sauber. Gegen echte Binance-Daten und eine laufende Ollama-Instanz geprüft, Dashboard-Bereich im Browser bedient.
27 KiB
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 — 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
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
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
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 mitserver.control_tokenschü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.containerPublishPort=127.0.0.1:8080:8080Ganz abschalten lässt sich der Server über
server.enabled: falsein der Konfiguration odertrademind 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, mitpodman machine ssh curl -s localhost:8080/healthgegenprü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
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)
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:
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:
- Werte in der YAML-Datei
${VAR}/${VAR:-fallback}— aus der Umgebung eingesetztTRADEMIND__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.
Börse wechseln
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:
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.
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.
Terminmarktdaten als Zusatzmerkmale
Optional fließen Funding Rate und Open Interest vom zugehörigen Perpetual
(BTC/USDT → BTC/USDT:USDT) als vier weitere Merkmale ein. Gehandelt wird weiterhin Spot.
strategy:
derivatives:
enabled: true
Die Zuordnung ist lookahead-frei: Für jede Kerze gilt nur der Wert, der zu diesem Zeitpunkt
bereits veröffentlicht war. Fällt eine Quelle aus oder deckt sie weniger als
min_coverage der Kerzen ab, bleiben die Spalten neutral — die Modelldimension ändert sich
nicht, der Bot läuft weiter.
Gemessenes Ergebnis: kein Nutzen. Zwei Backtests mit identischen Kerzen und Seed:
Lauf Rendite Trefferquote Modell-Accuracy LogLoss 5m, 20 Tage, ohne −1,79 % 18,9 % 51,2 % 0,7262 5m, 20 Tage, mit −1,90 % 21,4 % 50,4 % 0,7445 15m, 28 Tage, ohne −2,22 % 20,7 % 46,8 % 0,7856 15m, 28 Tage, mit −2,67 % 18,8 % 48,3 % 0,7831 Die Datenanbindung funktioniert (100 % Abdeckung in beiden Läufen), aber das Modell gewichtet die neuen Merkmale schwach (0,01–0,09 gegenüber 0,39 für
ema_spread). Deshalb ist die Funktion standardmäßig aus. Sie ist da, damit du es auf deinen Zeiträumen selbst prüfen kannst — nicht, weil sie sich bewährt hätte.
Grenzen der Börsen-API (gemessen an Binance): Open Interest reicht nur 30 Tage
zurück, 500 Zeilen je Abruf. Funding Rate reicht über ein Jahr. Längere Backtests deshalb
mit open_interest: false fahren.
Ein- und Ausschalten ändert die Anzahl der Merkmale (18 ↔ 22). Ein gespeichertes Modell mit abweichender Dimension wird verworfen und das Training beginnt von vorn — die Schalter sind darum als neustartpflichtig markiert.
Erklärungen über ein lokales Sprachmodell
Mit einer laufenden Ollama-Instanz erscheint im Dashboard der Bereich Erklärung: Auf Knopfdruck fasst ein lokales Modell zusammen, was die Zahlen zeigen — Merkmalsgewichte, Trefferquote, Risikolage, offene Positionen.
llm:
enabled: true
model: llama3.2
Das Modell entscheidet nichts. Es bekommt den Zustand als Text und gibt Text zurück; es wird nie aus dem Handels-Loop heraus aufgerufen und beeinflusst keine Order. Bewusst so: Ein Sprachmodell je Kerze entscheiden zu lassen wäre nicht reproduzierbar, kaum backtestbar und würde die Nachvollziehbarkeit zerstören, die das lineare Modell heute bietet.
Der System-Prompt untersagt Anlageempfehlungen und Kursprognosen. Beispielausgabe:
Der Bot befindet sich im simulierten Modus und hat bislang keine Handelsaktivität entfaltet […] Da die Trefferquote knapp über dem Zufallswert liegt und keine realen Handelsdaten vorliegen, ist die Belastbarkeit des Modells unter realen Marktbedingungen noch nicht nachgewiesen.
Reasoning-Modelle.
qwen3,deepseek-r1und Verwandte legen ihre Denkschritte in ein eigenes Antwortfeld und verbrauchen dafür das gesamte Token-Budget — die eigentliche Antwort bleibt leer.llm.think: false(Standard) schaltet das ab; getestet mitqwen3.8:27b, das damit in rund 20 Sekunden antwortet. Reicht das Budget trotzdem nicht, sagt die Fehlermeldung genau das und nennt den Schalter.
Nicht enthalten: News- oder Google-Trends-Sentiment als Merkmal. Der Grund ist nicht technischer Natur — es fehlt eine Quelle mit Point-in-Time-Historie. Ohne die lässt sich ein solches Merkmal nicht backtesten, und ein unvalidiertes Merkmal in ein Modell zu geben, das bei 51 % Accuracy steht, macht es eher schlechter. Google Trends kommt zusätzlich mit täglicher Auflösung und pro Abfrage neu skalierten Werten — für 5-Minuten-Kerzen unbrauchbar.
Risikomanagement
Vor jeder Order greifen mehrere unabhängige Grenzen:
max_position_pct— Anteil der Equity je Positionmax_total_exposure_pct— Summe aller Positionenmax_open_positions— parallele Positionen- ATR-basierter Stop-Loss und Take-Profit, optional nachziehender Stop
cooldown_bars_after_exit— Pause pro Symbol nach einem Ausstiegmin_notionalsowie 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:
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
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.:
podman exec -it trademind trademind report --config /config/config.yaml
Backtest
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 |
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 mittrading.require_confirmation_for_live: false.Die Kombination Live-Modus + Port nicht nur lokal + kein
control_tokenwird 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 auf127.0.0.1steht 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:
config.yaml${ENV}-Platzhalter darinTRADEMIND__ABSCHNITT__SCHLUESSEL-Umgebungsvariablen- 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/uidWerden 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: liveWechsel zwischen paperundbacktestgeht; auf Echtgeld umstellen nicht.live_confirmationSonst wäre die Live-Freigabe aus dem Netz setzbar. Zusammen verhindert das, dass jemand über das Dashboard schrittweise auf Echtgeldhandel umstellt.
Per HTTP:
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:
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/explain |
POST | Erklärung des aktuellen Zustands (braucht llm.enabled) |
/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 HeaderX-TradeMind-Token, während/statusund Co. offen bleiben. Ohne Token warnt der Bot beim Start. Komplett abschalten lässt sich die Steuerung mitserver.enable_control: false; die Routen sind dann nicht vorhanden (404).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
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
1mist 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 (
/statuszeigt 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