npx claudepluginhub Yvictor/polars_backtest_extensionPolars backtest extension development helper - backtesting with polars expressions
Claude Code marketplace entries for the plugin-safe Antigravity Awesome Skills library and its compatible editorial bundles.
Production-ready workflow orchestration with 79 focused plugins, 184 specialized agents, and 150 skills - optimized for granular installation and minimal token usage
Directory of popular Claude Code extensions including development tools, productivity plugins, and MCP integrations
Blazingly fast portfolio backtesting for Polars
df.bt.backtest() namespacepip install polars-backtest
# or
uv add polars-backtest
import polars as pl
import polars_backtest as pl_bt
# Long format data: one row per (date, symbol)
df = pl.DataFrame({
"date": ["2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02"],
"symbol": ["AAPL", "GOOGL", "AAPL", "GOOGL"],
"close": [100.0, 50.0, 102.0, 51.0],
"weight": [0.6, 0.4, 0.6, 0.4],
})
# Run backtest
result = df.bt.backtest(trade_at_price="close", position="weight")
300-day breakout strategy (~2000 stocks, 17 years daily data, 12M rows):
# Finlab
position = close >= close.rolling(300).max()
report = backtest.sim(position, resample="M")
# polars_backtest
df = df.with_columns(
(pl.col("close") >= pl.col("close").rolling_max(300).over("symbol"))
.alias("weight")
)
report = df.bt.backtest_with_report(position="weight", resample="M")
| Finlab | polars_backtest | |
|---|---|---|
| Time | 3.7s | 244ms |
| Speedup | 1x | 15x faster |
just bench # Run benchmarks
Get AI-powered assistance for writing and analyzing backtests.
# 1. Add the marketplace
/plugin marketplace add Yvictor/polars_backtest_extension
# 2. Install the plugin
/plugin install polars-backtest@polars-backtest-marketplace
After installation, Claude Code can help you:
get_metrics(), get_stats(), etc.import polars_backtest as pl_bt
# Function API
result = pl_bt.backtest(df, trade_at_price="close", position="weight")
# DataFrame namespace
result = df.bt.backtest(trade_at_price="close", position="weight")
result = df.bt.backtest(
trade_at_price="close",
position=pl.col("signal").cast(pl.Float64),
resample="M",
)
report = pl_bt.backtest_with_report(df, trade_at_price="adj_close", resample="M")
report
BacktestReport(
creturn_len=4219,
trades_count=6381,
total_return=8761.03%,
cagr=29.85%,
max_drawdown=-35.21%,
sharpe=1.13,
win_ratio=46.33%
)
report.get_stats() # or report.stats
shape: (1, 15)
┌────────────┬────────────┬──────┬──────────────┬──────────┬──────────────┬──────────────┐
│ start ┆ end ┆ rf ┆ total_return ┆ cagr ┆ max_drawdown ┆ avg_drawdown │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ date ┆ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪════════════╪══════╪══════════════╪══════════╪══════════════╪══════════════╡
│ 2008-10-31 ┆ 2025-12-31 ┆ 0.02 ┆ 87.610293 ┆ 0.298538 ┆ -0.352092 ┆ -0.042957 │
└────────────┴────────────┴──────┴──────────────┴──────────┴──────────────┴──────────────┘
┌────────────┬───────────┬──────────────┬───────────────┬──────────┬───────────┬─────────┬───────────┐
│ daily_mean ┆ daily_vol ┆ daily_sharpe ┆ daily_sortino ┆ best_day ┆ worst_day ┆ calmar ┆ win_ratio │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════════╪═══════════╪══════════════╪═══════════════╪══════════╪═══════════╪═════════╪═══════════╡
│ 0.300815 ┆ 0.249645 ┆ 1.131947 ┆ 1.834553 ┆ 0.195416 ┆ -0.160707 ┆ 0.84784 ┆ 0.463303 │
└────────────┴───────────┴──────────────┴───────────────┴──────────┴───────────┴─────────┴───────────┘
report.creturn # Cumulative returns DataFrame
report.trades # Trade records with MAE/MFE metrics
report.stats # Statistics (same as get_stats())
Compare strategy performance against a benchmark to get alpha, beta, and rolling win rate:
# Method 1: Use a symbol from your data as benchmark
report = df.bt.backtest_with_report(
position="weight",
benchmark="0050", # Symbol value (e.g., ETF ticker)
)