Data Versioning mit DVC: reproduzierbare Backtests auf Wochen-Skala.
„Können Sie den Backtest von vor sechs Wochen noch einmal laufen lassen?" — eine harmlose Frage, die in vielen Quant-Setups ein halber Albtraum ist. Code ist versioniert. Daten meistens nicht. Und beides ohne Verknüpfung ist halbe Reproduzierbarkeit. DVC, lakeFS und Pachyderm lösen genau diesen Spalt.
Warum Git nicht reicht.
Git ist auf Text-Diffs ausgelegt. Eine 12 GB Parquet-Datei mit Tick-Daten lässt sich
nicht sinnvoll diffen, sie sprengt jedes Repo und macht git clone zur
Stunden-Operation. Git LFS ist ein Pflaster, kein Heilmittel — das LFS-Backend wird
schnell zur Kostenfalle, und große Branches sind eine Tortur.
Was wir wirklich wollen:
- Daten nicht im Git-Repo, sondern in einem Object-Store (S3, GCS, Azure Blob).
- Eine kleine Text-Datei im Git, die per Hash referenziert, welche Daten zu welchem Commit gehören.
- Reproduzierbares
checkout + pull: anhand eines alten Git-Commits genau die damaligen Daten wiederherstellen.
DVC, lakeFS, Pachyderm im Vergleich.
- DVC (Data Version Control): Open-Source, Git-native. Speichert kleine
.dvc-Pointer-Dateien im Repo, echte Daten im konfigurierbaren Remote (S3, GCS, Azure, SSH, lokal). Pipelines werden indvc.yamldeklariert. Mein Default für Quant-Repos. - lakeFS: legt eine Git-ähnliche Schicht direkt über einen Object-Store. Branches, Commits, Merges auf S3-Verzeichnissen. Sehr stark, wenn mehrere Pipelines parallel Daten schreiben und konsistente Snapshots brauchen. Schwergewichtiger als DVC, ein eigener Server-Prozess.
- Pachyderm: Kubernetes-natives Pipeline-System mit eingebauter Data-Versionierung. Sinnvoll, wenn ein Team ohnehin auf K8s arbeitet und reaktiven Pipeline-Trigger („run when data changes") braucht. Für klassische Quant-Backtests meistens überdimensioniert.
Für 90 % der Mandanten — ein bis fünf Quants, Backtest-orientiert — ist DVC die richtige Wahl. Geringer Overhead, läuft auf jedem CI-Runner, kein zusätzlicher Server.
DVC-Setup in 5 Minuten.
# Repo initialisieren
cd quant-research/
git init
dvc init
git commit -m "init dvc"
# Remote konfigurieren (S3 als Beispiel)
dvc remote add -d s3remote s3://my-quant-bucket/dvc
dvc remote modify s3remote region eu-central-1
git add .dvc/config
git commit -m "configure dvc remote"
# Daten tracken
dvc add data/raw/ticks_msft_2031.parquet
# erzeugt: data/raw/ticks_msft_2031.parquet.dvc (kleine YAML)
# und schreibt: .gitignore mit Pfad-Ausschluss
git add data/raw/ticks_msft_2031.parquet.dvc data/raw/.gitignore
git commit -m "add MSFT 2031 tick data"
# Daten ins Remote pushen
dvc push
# Auf anderem Rechner / im CI:
git clone <repo>
dvc pull # holt nur die Daten zum aktuellen Commit
Das war's. Der entscheidende Punkt: die .dvc-Datei enthält einen MD5- oder
SHA-Hash der echten Daten. Wer einen alten Git-Commit auscheckt und dvc pull
macht, bekommt byte-genau die Daten zurück, mit denen damals gearbeitet wurde.
Remote Storage — was wirklich zählt.
- S3: Standard. Versioning auf dem Bucket aktivieren, Lifecycle-Policy für alte Objekte definieren. Kosten kalkulieren — Tick-Daten in dreistelligen GB summieren sich.
- GCS: Praktisch wenn Backtest-Compute in GCP läuft. Egress vermeiden.
- Azure Blob: Gleichwertig, sinnvoll im MS-Stack.
- SFTP / SSH: Für On-Prem / kleines Setup. Authentifizierung via SSH-Keys, kein eigenes Storage-System nötig.
- Self-hosted MinIO: S3-kompatibel, On-Prem oder im eigenen Rechenzentrum. Sinnvoll bei strengen Datenschutz-Anforderungen.
Eines vorab: das Remote sollte versioniert werden. S3 Object Versioning oder GCS Object Versioning ist ein Klick und schützt vor versehentlichem Überschreiben. DVC selbst verlässt sich auf Content-Hashes — wer einen alten Hash hat, holt die Daten zurück. Wer ihn nicht hat, ist abhängig vom Storage-Backend.
Pipelines mit dvc.yaml.
DVC kann mehr als nur Dateien tracken. Mit dvc.yaml wird der ganze
Backtest deklarativ:
stages:
ingest:
cmd: python src/ingest.py
deps:
- src/ingest.py
- data/raw/ticks_msft_2031.parquet
outs:
- data/interim/clean_msft.parquet
features:
cmd: python src/features.py
deps:
- src/features.py
- data/interim/clean_msft.parquet
params:
- features.vol_window
- features.flow_lookback
outs:
- data/processed/features_msft.parquet
backtest:
cmd: python src/backtest.py
deps:
- src/backtest.py
- data/processed/features_msft.parquet
params:
- strategy.threshold
- strategy.position_size
metrics:
- metrics/backtest.json
plots:
- plots/equity_curve.csv
dvc repro führt nur die Stages aus, deren Inputs oder Parameter sich
geändert haben — wie make, nur mit Datenabhängigkeiten. dvc metrics show
und dvc plots diff vergleichen Backtest-Ergebnisse zwischen Commits.
Code-Hash und Daten-Hash verknüpfen.
Ein reproduzierbarer Backtest ist erst dann reproduzierbar, wenn der Run einen eindeutigen Fingerprint hat. Ich schreibe in jeden Backtest-Output:
{
"run_id": "2032-07-30T14:21:09Z_a8f3c9d",
"git_commit": "a8f3c9d7e4b2a1...",
"git_dirty": false,
"dvc_lock_hash": "f4c2b3a8...",
"params": {
"features.vol_window": 5,
"strategy.threshold": 0.0042,
"strategy.position_size": 0.02
},
"data_inputs": [
{"path": "data/raw/ticks_msft_2031.parquet",
"md5": "d41d8cd98f00b204..."}
],
"metrics": { "sharpe": 1.87, "max_dd": -0.092 }
}
Mit diesem Block lässt sich jeder Run Monate später byte-genau wiederherstellen:
Git-Commit auschecken, dvc pull, dvc repro. Wenn das nicht
geht, ist die Pipeline kaputt — und das ist eine Information, die man früh haben will,
nicht nach drei Monaten Live-Trading.
Praktisches Beispiel: ein Strategie-Backtest mit Code, Daten, Ergebnis.
Letztes Mandantenprojekt, vereinfacht: eine Volatilitäts-Carry-Strategie auf VIX-Futures. Inputs: 4 Jahre tägliche Settlement-Daten (~12 MB), 18 Monate Intraday-Ticks (~6 GB), zwei Macro-Reihen aus FRED. Code: Python, ein paar hundert Zeilen plus Backtest-Loop.
Setup:
- DVC-Repo auf GitHub.
- Remote: S3-Bucket mit Object Versioning, KMS-Verschlüsselung.
dvc.yamlmit drei Stages:ingest,features,backtest.- Parameter in
params.yaml: lookback, threshold, sizing-Parameter. - CI-Job (GitHub Actions): bei PR-Push automatisch
dvc pull+dvc repro+ Vergleich der Metrics zwischen Branch und main.
Wirkung: jeder Pull-Request zeigt, wie sich Sharpe, Max Drawdown und Trade-Count verändern, wenn ich an einem Feature schraube. Diskussion mit dem Mandanten läuft entlang konkreter Zahlen statt entlang von Eindrücken. Und sechs Wochen später eine Frage beantworten zu können „mit welchen Daten lief der Backtest vom 14. Juni?" ist eine Minute Arbeit, nicht ein halber Tag.
Meine Praxis.
Für ernsthafte Mandanten-Backtests ist DVC für mich Pflicht. Nicht weil ich Tools
sammle, sondern weil ohne ein solches System bei jeder Diskussion „aber bei mir kam
etwas anderes raus" der Beweis fehlt, dass beide Seiten von denselben Daten reden.
Mit DVC ist die Frage in zehn Sekunden geklärt: gleicher Commit, gleicher
dvc pull, gleicher Hash — gleiches Ergebnis.
Für persönliche Experimente reicht oft ein lokaler Parquet-Ordner. Für alles, was länger als eine Woche lebt oder von zwei oder mehr Personen angefasst wird, kostet DVC einen Nachmittag Setup und spart in Summe Tage Detektivarbeit. Das ist eine der besten ROI-Investitionen, die ein systematischer Trader machen kann.
Sie wollen reproduzierbare Backtests etablieren, bevor das nächste „warum stimmt das nicht mehr?" auf dem Tisch liegt? Erstgespräch buchen — wir bringen Ihren Quant-Stack auf Versionierungs-Niveau.