Erledigt, Sir. Task-Block 17–21 ist implementiert, getestet, committed und auf `main` gepusht — weiterhin strikt synthetisch. Keine echte Coin-/Wallet-Datei, keine echten Wallet-Adressen, keine echten Finanzdaten. Die heilige Datei `260514_ Zusammenstellung aller Coins` blieb unberührt, wie es sich gehört.

## Push-Status

- Branch: `main`
- Neuer Commit: `0078253`
- Commit Message: `feat: add crypto wallet ledger core`
- Remote vorher: `348714e`
- Remote nachher: `0078253`
- Push: erfolgreich
- Git Status nach Push: `clean`
- Git-Safety nach Push: `GIT_SAFETY_OK`
- Getrackte Dateien: `137`

## Implementierte Funktionen

### Task 17 — Crypto Wallets und Assets

Implementiert in:

- `src/jarvis_finance/crypto/wallets.py`
- `src/jarvis_finance/crypto/assets.py`

Wallet-Funktionen:

- `create_wallet(...)`
- `get_wallet(...)`
- `update_wallet(...)`
- `deactivate_wallet(...)`

Umgesetzt:

- Wallet anlegen, lesen, aktualisieren, deaktivieren
- Wallet-Name eindeutig
- Wallet-Adresse optional
- keine Wallet-Adresse in Tests oder Fixtures
- Wallet-Typ validiert gegen:
  - `Hardware Wallet`
  - `Software Wallet`
  - `Exchange`
  - `Bank/Broker`
  - `DeFi`
  - `Sonstiges`
- Wallet-Änderungen erzeugen Audit-Einträge

Crypto-Asset-Funktionen:

- `create_crypto_asset(...)`
- `get_crypto_asset(...)`

Umgesetzt:

- Crypto Asset anlegen/lesen
- CoinGecko-ID empfohlen, aber nicht hart Pflicht
- fehlende CoinGecko-ID erzeugt Datenqualitätswarnung
- Symbol allein wird nicht als eindeutig behandelt
- Symbolkonflikt erzeugt Warnung für manuelle Auswahl
- Asset-Erstellung erzeugt Audit-Eintrag

---

### Task 18 — Crypto Holdings aus Initial Snapshot

Implementiert in:

- `src/jarvis_finance/crypto/holdings.py`

Funktionen:

- `create_initial_holding_snapshot(...)`
- `calculate_crypto_holdings(...)`

Umgesetzt:

- initiale Crypto-Holdings aus bestätigten Initial Snapshots
- Holdings pro Coin und Wallet
- Gesamtbestand pro Coin über alle Wallets
- `verification_status`:
  - `verified`
  - `stale`
  - `unverified`
  - `estimated`
- `last_verified_at` wird gespeichert
- Legacy Snapshot Values werden gespeichert:
  - `legacy_snapshot_value_original`
  - `legacy_snapshot_value_chf`
  - `legacy_snapshot_currency`
  - `legacy_snapshot_date`
- Legacy Values werden **nicht** als aktuelle Bewertung verwendet
- aktuelle Bewertung bleibt `None`, bis ein echter Crypto-Pricing-Block existiert
- fehlende CoinGecko-ID erzeugt Datenqualitätswarnung
- Holdings werden aus Snapshots und Crypto-Transaktionen berechnet, nicht still überschrieben

---

### Task 19 — Crypto Transfers

Implementiert in:

- `src/jarvis_finance/crypto/transactions.py`

Funktion:

- `record_crypto_transfer(...)`

Umgesetzt:

- Transfer Wallet A → Wallet B
- gleicher Coin
- Menge muss `> 0` sein
- Quellwallet und Zielwallet Pflicht
- Quellwallet und Zielwallet dürfen nicht gleich sein
- Coin-Fee optional
- TxHash optional
- Quellwallet wird reduziert
- Zielwallet wird erhöht
- Coin-Fee reduziert Bestand der Quellwallet
- negativer Wallet-Bestand wird blockiert
- bei Blockade wird kritischer Alert erzeugt
- bestätigter Transfer erzeugt Audit-Log

---

### Task 20 — Crypto Buy/Sell mit Ledger-Kopplung

Implementiert in:

- `src/jarvis_finance/crypto/transactions.py`

Funktionen:

- `record_crypto_buy(...)`
- `record_crypto_sell(...)`

Umgesetzt:

- Crypto-Kauf erzeugt allgemeine Ledger-Transaktion und referenziert diese in `crypto_transactions.transaction_id`
- allgemeine Ledger-Transaktion referenziert Crypto-Event über `source_type='crypto'` und `source_id`
- Crypto-Kauf erhöht Zielwallet-Bestand
- Crypto-Verkauf reduziert Quellwallet-Bestand
- Crypto-Verkauf erzeugt allgemeine Ledger-Transaktion
- Fremdwährung ohne FX wird als:
  - `fx_status='missing'`
  - `quality_status='incomplete'`
  markiert
- fehlende FX erzeugt kritischen Alert
- Cash-Auswirkung bleibt mit allgemeinem Ledger konsistent
- kein automatischer Import echter Exchange-Daten

Designentscheidung:

- Crypto-Assets werden noch nicht als allgemeine `instruments` modelliert. Die Ledger-Kopplung läuft aktuell über `source_type='crypto'` / `source_id` und nullable `instrument_id`. Das hält MVP sauber und verhindert falsche Vermischung mit Stock-/ETF-Positionslogik.

---

### Task 21 — Crypto Fees

Implementiert in:

- `src/jarvis_finance/crypto/transactions.py`

Umgesetzt:

- Coin-Fee reduziert Coin-Bestand
- Fiat-Fee wird als allgemeine Ledger-Gebühr abgebildet
- Fee-Währung wird in `crypto_transactions.fee_currency` gespeichert
- Fiat-Fee erzeugt separate allgemeine `transactions`-Zeile vom Typ `fee`
- Fee wird nicht doppelt gezählt:
  - Buy-Ledger-Transaction enthält nur den Kaufbetrag
  - Fiat-Fee liegt separat als Fee-Transaction
  - Sell-Fee bleibt in der Sell-Netto-Logik eingebettet, keine doppelte Fee-Zeile
- Fee ist über Crypto-Transaction, allgemeine Ledger-Transaction und Audit nachvollziehbar
- unklare Fee-Währung erzeugt Datenqualitätswarnung

## Neue/geänderte Dateien

Geändert:

- `src/jarvis_finance/crypto/assets.py`
- `src/jarvis_finance/crypto/holdings.py`
- `src/jarvis_finance/crypto/transactions.py`
- `src/jarvis_finance/crypto/wallets.py`

Neu:

- `tests/unit/test_crypto_core.py`

Zusätzlich aktualisiert:

- Finance-System-Skill intern ergänzt:
  - Alert-Deduplizierung vor produktiver Dashboard-Nutzung
  - Market-FX für Nicht-CHF-Marktpreise späterer Provider-Block
  - WAC bleibt MVP-Performance-Logik, nicht Steuerlogik

## Neue Tests

Neue Testdatei:

- `tests/unit/test_crypto_core.py`

Abgedeckt:

- Wallet anlegen
- Wallet lesen
- Wallet aktualisieren
- Wallet deaktivieren
- doppelter Wallet-Name wird verhindert
- ungültiger Wallet-Typ wird abgelehnt
- Crypto Asset mit CoinGecko-ID
- Crypto Asset ohne CoinGecko-ID erzeugt Warnung
- Symbolkonflikt erzeugt Warnung
- Initial Crypto Holding aus Snapshot
- gleicher Coin auf mehreren Wallets
- Gesamtbestand pro Coin aggregiert korrekt
- Legacy Snapshot Value wird nicht als aktuelle Bewertung verwendet
- Transfer zwischen Wallets
- Transfer mit Coin-Fee
- Transfer mit gleicher Quell-/Zielwallet wird abgelehnt
- Transfer mit zu hohem Betrag wird blockiert und kritisch markiert
- Crypto Buy mit Fiat erzeugt Ledger-Link
- Crypto Sell mit Fiat erzeugt Ledger-Link
- Coin-Fee reduziert Bestand
- Fiat-Fee erzeugt Ledger-Gebühr
- bestätigte Crypto-Transaktion erzeugt Audit-Log
- fehlende CoinGecko-ID erzeugt Datenqualitätswarnung
- fehlende FX bei Crypto-Fiat-Transaction erzeugt `missing/incomplete`

## Testergebnis

Ausgeführt:

```bash
PYTHONPATH=src python -m compileall src tests
PYTHONPATH=src pytest tests -q
PYTHONPATH=src python -m jarvis_finance.cli.main git-safety-scan .
git status
```

Ergebnis:

- Compile: OK
- Pytest: `52 passed`
- Git-Safety: `GIT_SAFETY_OK`
- Git Status: `clean`

## Safety

Eingehalten:

- keine echten Finanzdaten
- keine echte Coin-/Wallet-Datei
- `260514_ Zusammenstellung aller Coins` nicht verwendet
- keine echten Wallet-Adressen
- keine echten Portfolioauszüge
- keine Tokens/Secrets ins Repo
- keine Runtime-Daten ins Repo
- nur synthetische Testdaten und synthetische IDs

## Offene Risiken / Designentscheidungen

- Crypto Valuation ist noch nicht implementiert. Legacy Snapshot Values werden bewusst gespeichert, aber nicht als aktuelle Bewertung verwendet.
- CoinGecko-ID fehlt aktuell nur als Warnung; spätere Pricing-Pipeline muss diese Warnung für Valuation priorisieren.
- Crypto Cost Basis / WAC ist noch nicht Teil dieses Blocks. Aktuell geht es um Bestände, Transfers, Fees und Ledger-Kopplung.
- Crypto Buy/Sell referenziert allgemeine Ledger-Transactions, aber Crypto-Assets sind noch nicht mit `instruments` verschmolzen. Das ist absichtlich konservativ.
- Overdraft wird aktuell hart blockiert und zusätzlich kritisch markiert. Eine spätere bestätigte Korrektur-Logik kann ergänzt werden, falls echte Migrationen Altbestände erklären müssen.
- Alert-Deduplizierung ist weiterhin offen und vor produktiver Dashboard-Nutzung wichtig.
- Fiat-Fee-Handling ist so modelliert, dass Buy-Fee separat als Ledger-Fee geschrieben wird, um Cash nicht doppelt zu belasten.

Damit ist der Crypto-Kern stabil genug, um später eine Mapping- und Dry-Run-Schicht für die echte Coin-/Wallet-Datei zu bauen — aber noch ohne sie anzufassen. Genau die langweilige Disziplin, die verhindert, dass ein Finanzsystem zur Excel-Seance wird.