# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Was das ist Crypto-Trading-Bot, der **alle 15 Minuten** Marktdaten von **Kraken Futures Demo** holt, sie an **zwei LLM-Voter im Ensemble** schickt und nur bei Konsens (beide BUY/SELL ≥ 0.6 confidence) einen Trade ausführt. Alle Decisions/Trades landen in SQLite, ein Streamlit-Dashboard visualisiert PnL, ein Discord-Webhook benachrichtigt über Trades/Errors/Daily-Summary. **Zweck:** Empirisch herausfinden, ob LLM-basiertes Trading profitabel wäre — ohne reales Risiko (Demo-Account). ## Commands ```bash # Tests + Lint .venv/bin/pytest -q # Unit-Tests .venv/bin/pytest tests/test_indicators.py # einzelner Test .venv/bin/ruff check src/ # Linting # Smoke-Tests (erfordern .env mit echten Keys) .venv/bin/python scripts/smoke_kraken.py # Demo-API erreichbar? .venv/bin/python scripts/smoke_ai.py # AI-Voter liefern JSON? .venv/bin/python scripts/smoke_discord.py # Webhook erreichbar? # Ausführen .venv/bin/python -m aitrader.main --once # Ein vollständiger Tick aitrader --once # alternativ via installiertem Entrypoint # Dashboard (lokal) .venv/bin/streamlit run src/aitrader/dashboard/app.py ``` Package-Manager: `uv`. Dependencies installieren mit `uv pip install -e ".[dev]"`. ## Architektur ``` src/aitrader/ ├── main.py # run_tick(): vollständiger Tick-Flow von oben nach unten ├── config.py # YAML (config.yaml) + .env → Pydantic Settings (lru_cache) ├── exchange/ │ ├── kraken.py # ccxt-Wrapper, sandbox=True für Demo │ └── market_data.py # OHLCV + Orderbook + Ticker → MarketSnapshot ├── features/ │ ├── indicators.py # RSI/MACD/EMA/ATR — pandas-only, kein pandas-ta │ └── orderbook.py # Spread, Imbalance ├── news/sentiment.py # CryptoPanic + VADER (optional) ├── ai/ │ ├── registry.py # VoterConfig → konkreter Client (make_voter) │ ├── prompt.py # System- + User-Prompt-Builder │ ├── schema.py # TradeDecision Pydantic-Modell + JSON-Schema │ ├── gemini.py # google-genai SDK, response_schema │ ├── claude.py # anthropic SDK, Tool-Use für strukturierten Output │ ├── openai_compat.py # OpenAI-kompatible Endpunkte (groq/deepseek/xai/openrouter/ollama) │ └── ensemble.py # combine() / single() — HOLD bei Disagreement oder zu niedriger Confidence ├── trader/ │ ├── risk.py # evaluate(): Position-Cap, Daily-Loss-Limit, max offene Positionen │ ├── executor.py # Market-Order auf Kraken Demo + DB-Eintrag │ └── portfolio.py # SL/TP-Check, Equity-Snapshot, Trade-Close ├── notify/discord.py # Webhook-Notifier (Embeds) ├── storage/ │ ├── models.py # SQLModel-Tabellen: Decision, Trade, EquitySnapshot │ └── db.py # SQLite-Engine + create_all └── dashboard/app.py # Streamlit — absolute Imports wegen Script-Ausführung ``` **Tick-Flow** (`main.py:run_tick`): Marktdaten → Features/Indikatoren → Orderbook → News/Sentiment → Prompt-Builder → Voter A + B → Ensemble → DB → Discord → Risk-Check → Execute. ## AI-Voter Zwei generische **Voter-Slots** in `config.yaml` (`ai.voter_a`, `ai.voter_b`). Provider werden via `ai/registry.py` instanziiert. Default: `voter_a=gemini`, `voter_b=groq`. Wechsel braucht nur Config-Änderung + den passenden ENV-Key. | provider | ENV-Key | Beispiel-Modell | |---|---|---| | gemini | `GEMINI_API_KEY` | `gemini-2.0-flash` | | claude | `ANTHROPIC_API_KEY` | `claude-haiku-4-5-20251001` | | groq | `GROQ_API_KEY` | `llama-3.3-70b-versatile` | | deepseek | `DEEPSEEK_API_KEY` | `deepseek-chat` | | xai | `XAI_API_KEY` | `grok-4-fast` | | openrouter | `OPENROUTER_API_KEY` | `meta-llama/llama-3.3-70b-instruct:free` | | ollama | (kein Key) | `llama3.3` | `ai.mode: single` → nur `voter_a`, kein Konsens nötig. ## Wichtige Regeln & Gotchas - **Niemals** `exchange.sandbox: false` ohne explizite User-Bestätigung. Das ist die einzige Schutzlinie zum Live-Geld. - `exchange.paper_only: true` blockt Trade-Execution zusätzlich, auch bei sandbox=true. - **Indikatoren** sind selbst implementiert (pandas-only) weil pandas-ta + numpy 2 inkompatibel war. - **Pair-Symbole**: Kraken Futures nutzt teils `PI_XBTUSD`-Format statt `BTC/EUR` — bei Symbol-Fehlern `pairs:` in `config.yaml` anpassen. - **Ensemble-HOLD ist gewollt**: Bei Disagreement oder zu niedriger Confidence wird absichtlich nicht getradet. - **`discord.notify_on`** enthält `decision` standardmäßig nicht (192 Embeds/Tag wären spammig). Nur `trade_open`, `trade_close`, `error` etc. - **Daily-Loss-Limit (5%)** pausiert Trading automatisch — Reset um 00:00 UTC. - **`get_settings()` ist `lru_cache`** — Änderungen an `.env`/`config.yaml` nach Start werden nicht übernommen ohne Neustart. ## Wo läuft was | Umgebung | Pfad | Aufruf | |---|---|---| | Lokal (Dev) | `~/code/aitrader` | `.venv/bin/python -m aitrader.main --once` | | Server (Prod) | `/opt/aitrader` | `systemctl status aitrader` | | DB | `data/aitrader.db` | `sqlite3 data/aitrader.db ".tables"` | | Logs (Server) | journald | `journalctl -u aitrader -f` | | Dashboard (Server) | `http://:8501` | nur via Tailscale | ## Update-Workflow (lokal → Server) 1. `git commit && git push` 2. Auf Server: `cd /opt/aitrader && sudo -u aitrader git pull` 3. Bei neuen Dependencies: `sudo -u aitrader /home/aitrader/.local/bin/uv pip install -e .` 4. `sudo systemctl restart aitrader aitrader-dashboard` 5. `sudo journalctl -u aitrader -f` Siehe `DEPLOY.md` für vollen Setup vom Frischserver inkl. Tailscale. ## Ausstehende Erweiterungen (nicht implementiert) - Backtest-Modus (historische Daten replay durch Decisions-Tabelle) - Mehr Pairs / dynamisches Universe-Selection - Position-Sizing per Kelly oder Vol-Targeting - Prompt-Tuning A/B (zwei Prompts, vergleichen welcher besser performt) ## Für Claude - Kein Refactor "weil schöner" — der Code ist bewusst kompakt gehalten. - Bei Trading-Logik: `ai/ensemble.py` und `trader/risk.py` sind die zwei kritischen Dateien. - Bei Daten-Pipeline: `main.py:run_tick` ist der Flow von oben nach unten. - Niemals echtes Geld ohne explizite User-Bestätigung — das Projekt ist Demo-only.