Polars vs Pandas bei Tickdaten: Benchmark und Migration.
Polars hat in den letzten Jahren den Pandas-Thron ernsthaft angegriffen. Schneller, parallelisiert, mit Lazy Evaluation und einer API, die Sie nach zwei Tagen lieben werden. Aber: Polars ist nicht in jedem Setup die richtige Wahl. Wann lohnt sich der Umstieg, wann bleiben Sie bei Pandas?
Was Polars anders macht.
Polars ist in Rust geschrieben und nutzt Apache Arrow als Speicherformat. Daraus
ergeben sich drei wesentliche Unterschiede zu Pandas: erstens parallele Ausführung
auf allen verfügbaren CPU-Kernen, zweitens ein Query-Optimizer durch Lazy Evaluation,
drittens eine konsistente Typisierung ohne die object-Fallen, die
Pandas plagen.
Für Tickdaten-Workloads sind alle drei Punkte relevant. Tickdaten sind groß, profitieren von Parallelität, enthalten oft viele Joins und Filter, die ein Optimizer zusammenfassen kann, und sind typisch genug, dass das Type-System hilft.
Benchmark: 100 Mio. Ticks aggregieren.
Ein realistisches Beispiel: 100 Mio. EURUSD-Ticks aus einem Parquet-File einlesen, zu 1-Minuten-Bars aggregieren, Spread berechnen, nach Stunde gruppieren.
import polars as pl
# Lazy: nichts wird geladen, bis collect() aufgerufen wird
result = (
pl.scan_parquet('eurusd_ticks_2025.parquet')
.with_columns([
(pl.col('ask') - pl.col('bid')).alias('spread'),
])
.group_by_dynamic('timestamp', every='1m')
.agg([
pl.col('bid').first().alias('open'),
pl.col('bid').max().alias('high'),
pl.col('bid').min().alias('low'),
pl.col('bid').last().alias('close'),
pl.col('spread').mean().alias('avg_spread'),
pl.len().alias('n_ticks'),
])
.collect(streaming=True)
)
Auf einem M2-MacBook-Pro mit 16 GB RAM dauert die Operation in Polars rund 8
Sekunden. Der äquivalente Pandas-Code braucht etwa 90 Sekunden — und scheitert,
wenn die Rohdaten nicht in den Speicher passen. Polars streamt die Daten dank
streaming=True in Chunks, ohne das gesamte File zu laden.
Lazy Evaluation: der Game-Changer.
Pandas führt jeden Befehl sofort aus. Polars sammelt im Lazy-Modus alle Operationen,
optimiert sie als Graph und führt erst beim collect() aus. Dabei werden
Filter nach oben gezogen, unnötige Spalten verworfen, Aggregate kombiniert.
Ein konkretes Beispiel: Sie lesen 50 Spalten ein, filtern auf ein Symbol und berechnen am Ende einen Indikator auf 3 Spalten. Pandas liest alle 50 Spalten ein, Polars (lazy) liest nur die 4 Spalten, die im Endergebnis vorkommen. Das spart bei großen Parquet-Files Faktor 5–10 in I/O-Zeit.
import polars as pl
# Plan zeigen statt ausführen
query = (
pl.scan_parquet('all_symbols.parquet')
.filter(pl.col('symbol') == 'AAPL')
.with_columns([
pl.col('close').pct_change().alias('ret'),
pl.col('close').rolling_mean(20).alias('sma20'),
])
.select(['timestamp', 'close', 'ret', 'sma20'])
)
print(query.explain()) # zeigt den optimierten Plan
df = query.collect()
Wo Pandas weiter im Vorteil ist.
Polars ist nicht universell überlegen. Drei Bereiche, in denen Pandas weiterhin stärker ist: erstens das Ökosystem — statsmodels, scikit-learn, pyfolio und empyrical erwarten Pandas-DataFrames; zweitens komplexe Time-Series-Operationen mit heterogenem Index, wo Pandas mehr Flexibilität bietet; drittens etablierte Teams, in denen alle Pandas können und niemand Polars.
Auch bei kleinen DataFrames (unter 100k Zeilen) ist der Performance-Vorteil von Polars vernachlässigbar — der Overhead beim DataFrame-Erstellen ist sogar leicht höher als bei Pandas. Polars spielt seine Stärken erst bei Millionen von Zeilen aus.
Migration: schrittweise und pragmatisch.
Wer migriert, sollte das nicht in einem Big-Bang machen. Polars und Pandas sind über Apache Arrow ohne Copy-Overhead konvertierbar. Heißt: Sie können einzelne Pipeline-Schritte umstellen und am Übergang zurückkonvertieren.
import polars as pl
import pandas as pd
# Heavy Lifting in Polars
pl_df = (
pl.scan_parquet('ticks.parquet')
.filter(pl.col('symbol').is_in(['AAPL', 'MSFT', 'NVDA']))
.group_by_dynamic('timestamp', every='5m')
.agg([pl.col('last').last().alias('close')])
.collect()
)
# Konvertierung für sklearn / statsmodels
pdf = pl_df.to_pandas()
# ... ML-Pipeline läuft weiter mit Pandas
Typische Migrationsfehler.
- 1:1-Übersetzung: Wer Polars wie Pandas schreibt, verschenkt die Vorteile.
group_by_dynamicstattresample,with_columnsstatt mehrere Assignments. - Eager statt Lazy:
pl.read_parquetliest sofort,pl.scan_parquetist lazy. Die scan-Variante ist fast immer schneller. - Index-Mentalität: Polars kennt keinen Index im Pandas-Sinn. Wer ständig
set_indexsucht, denkt im falschen Modell. - String-Operations als apply: Polars hat hochoptimierte String-Methoden via
pl.col('x').str.*. Custom-Funktionen mitmap_elementskillen die Performance.
Wann Polars die richtige Wahl ist.
Klare Empfehlungen aus unserer Praxis: Polars überall dort, wo Datenmengen über 10 Millionen Zeilen liegen und das Ergebnis weiterverarbeitet wird — Aggregations- Pipelines, Feature-Engineering, Datenbereinigung. Pandas für das letzte Stück vor ML-Modellen, für interaktive Analyse mit kleinen Subsets, für die Integration mit etablierten Bibliotheken.
Wer einen neuen Stack baut, sollte Polars als Standard setzen. Wer ein bestehendes System modernisiert, beginnt mit den langsamsten Pipelines und arbeitet sich vor. In den meisten Fällen sind das die Datenladung und die ersten Aggregationsstufen — also genau die Bereiche, in denen Polars am stärksten ist.
Fazit.
Polars ist kein Hype, sondern ein echter Fortschritt für daten-intensive Trading- Workloads. Die Migration ist überschaubar, der Performance-Gewinn substanziell, und das Tooling reift schnell. Wer 2026 noch jeden Tick-Backtest in Pandas rechnet, verschenkt Stunden pro Tag. Wer aber wegen Polars das gesamte ML-Ökosystem aufgibt, tauscht Performance gegen Funktionalität — selten ein guter Deal.
Sie überlegen, Ihre Daten-Pipeline auf Polars umzustellen? Erstgespräch buchen — wir prüfen, was sich lohnt und was nicht.