nikkisora
PolarBT
Python

Blazingly fast strategy backtest with polars

Last updated Jul 21, 2026
11
Stars
2
Forks
0
Issues
0
Stars/day
Attention Score
36
Language breakdown
Python 100.0%
โ–ธ Files click to expand
README

PolarBT

Polar BackTest

A lightweight, high-performance backtesting library for trading strategy development and optimization. Built on Polars for fast vectorized data processing with an event-driven execution loop for flexible strategy logic.

Features

  • Hybrid architecture โ€” vectorized preprocessing (Polars) + event-driven execution loop
  • 25+ built-in indicators โ€” SMA, EMA, RSI, MACD, Bollinger Bands, ATR, SuperTrend, ADX, and more
  • Complete order system โ€” market, limit, stop, stop-limit, bracket orders, day/GTC orders
  • Risk management โ€” stop-loss, take-profit, trailing stops, position size limits, drawdown stops
  • Short selling โ€” negative positions, borrow costs, position reversals
  • Margin & leverage โ€” configurable leverage, margin tracking, margin calls
  • Commission models โ€” percentage, fixed, maker/taker, volume-tiered, custom
  • Position sizing โ€” fixed, percent, fixed-risk, Kelly, volatility-based
  • Weight-based backtesting โ€” declarative portfolio allocation with backtest_weights() or WeightStrategy, rebalance scheduling, stop-loss/take-profit, next-actions output
  • Multi-asset โ€” pass a dict of DataFrames or a long-format DataFrame with symbol column; all OHLC data preserved
  • Dynamic universe โ€” UniverseProvider protocol filters tradeable symbols per bar; built-in AgeFilter, VolumeFilter, TopN, CompositeFilter; token lifecycle tracking via ctx.firstseenbar / ctx.bar_count
  • Parallel optimization โ€” grid search, multi-objective Pareto, Bayesian optimization
  • Walk-forward analysis โ€” rolling and anchored train/test splits
  • Advanced analysis โ€” Monte Carlo simulation, look-ahead bias detection, permutation testing
  • Visualization โ€” interactive Plotly charts (price, equity, drawdown, trade markers, heatmaps)
  • AMM-aware execution โ€” pluggable SlippageModel with FlatSlippage and AMMSlippage (constant-product formula)
  • Exchange rate support โ€” Engine(exchange_rate=...) converts equity curve to USD; reports dual quote/USD metrics
  • DeFi indicators โ€” buysellratio, netflow, tradeintensity, pumpdetector, rugpulldetector, AMM priceimpactestimate, liquidityratio, and more
  • Trade data pipeline โ€” validate and aggregate raw DEX/AMM trades into OHLCV bars (time-based or trade-count), with buy/sell volume split, VWAP, and optional USD conversion
  • Data utilities โ€” validation, cleaning, OHLCV resampling
  • Optional TA-Lib integration โ€” wrap any TA-Lib function into Polars expressions

Installation

pip install polarbt

Or with optional extras:

pip install polarbt[plotting]   # Plotly charts
pip install polarbt[talib]      # TA-Lib integration

Install from source:

git clone git@github.com:nikkisora/PolarBT.git
cd PolarBT
pip install -e .

Quick Start

import polars as pl
import yfinance as yf
from polarbt import Engine, Strategy
from polarbt import indicators as ind
from polarbt.core import BacktestContext
from polarbt.plotting import plot_backtest

class SMACross(Strategy): def preprocess(self, df: pl.DataFrame) -> pl.DataFrame: return df.with_columns( ind.sma("close", 10).alias("sma_fast"), ind.sma("close", 30).alias("sma_slow"), ).with_columns( ind.crossover("smafast", "smaslow").alias("buy"), ind.crossunder("smafast", "smaslow").alias("sell"), )

def next(self, ctx: BacktestContext) -> None: if ctx.row.get("buy"): ctx.portfolio.ordertargetpercent("asset", 1.0) elif ctx.row.get("sell"): ctx.portfolio.close_position("asset")

Download data from Yahoo Finance

ticker = yf.download("AAPL", start="2016-01-01", end="2026-01-01", auto_adjust=True) ticker = ticker.droplevel("Ticker", axis=1).reset_index() data = pl.from_pandas(ticker)

Run backtest

engine = Engine(SMACross(), data, commission=.005, initialcash=100000) results = engine.run()

print(results)

Interactive chart saved to HTML

fig = plotbacktest(engine, title="SMA Crossover โ€” AAPL", indicators=["smafast", "sma_slow"]) fig.write_html("backtest.html")
Equity Final [$]                        366,236.83
Equity Peak [$]                         433,930.72
Return [%]                                  266.24
Buy & Hold Return [%]                      1044.52
Return (Ann.) [%]                            14.08
CAGR [%]                                     14.08
Volatility (Ann.) [%]                        19.78

Sharpe Ratio 0.76 Sortino Ratio 0.92 Calmar Ratio 0.44 Max. Drawdown [%] -32.16 Avg. Drawdown Duration [bars] 38 Max. Drawdown Duration [bars] 730

Trades 42

Win Rate [%] 47.62 Best Trade [%] 57.11 Worst Trade [%] -13.43 Avg. Trade [%] 3.94 Max. Trade Duration [bars] 128 Avg. Trade Duration [bars] 39 Avg. Trade MDD [%] -8.78 Profit Factor 1.79 Expectancy [$] 6338.97 SQN 1.27 Kelly Criterion 0.2098

PolarBT

Weight-Based Backtesting

For portfolio allocation strategies, skip the event loop entirely โ€” just supply target weights per (date, symbol):

import polars as pl
from polarbt import backtest_weights

data: long-format DataFrame with columns date, symbol, close, weight

result = backtest_weights( data, resample="M", # rebalance monthly resample_offset="2d", # delay 2 trading days after month boundary fee_ratio=0.001, stop_loss=0.10, # 10% per-position stop-loss position_limit=0.5, # max 50% in any single name initialcapital=100000, )

print(result.metrics) # standard BacktestMetrics print(result.trades.head()) # per-trade log print(result.next_actions) # forward-looking rebalance actions

Trade Data & DeFi Backtesting

PolarBT can ingest raw DEX/AMM trade data (e.g. Pump.fun on Solana), aggregate it into OHLCV bars, apply DeFi-specific indicators, and backtest with AMM-aware slippage โ€” all in a single pipeline.

import polars as pl
from polarbt import Engine, Strategy, indicators_defi as defi
from polarbt.core import BacktestContext
from polarbt.data.trades import aggregatetrades, validatetrades
from polarbt.slippage import AMMSlippage
from polarbt.universe import AgeFilter, CompositeFilter, VolumeFilter

1. Load and validate raw trades

trades = pl.read_parquet("trades.parquet") assert validate_trades(trades.sort("symbol", "timestamp")).valid

2. Aggregate to 5-minute OHLCV bars

bars = aggregatetrades(trades.sort("symbol", "timestamp"), "5m", mintrades=3)

3. Define a strategy using DeFi indicators

class PumpMomentum(Strategy): def preprocess(self, df: pl.DataFrame) -> pl.DataFrame: return df.with_columns( defi.buysellratio().over("symbol").alias("bs_ratio"), defi.trade_intensity(window=10).over("symbol").alias("intensity"), )

def next(self, ctx: BacktestContext) -> None: for sym in ctx.symbols: row = ctx.row(sym) if row.get("bs_ratio", 0) > 0.7 and row.get("intensity", 0) > 2.0: ctx.portfolio.ordertargetpercent(sym, 0.1) elif row.get("bs_ratio", 0) < 0.3: ctx.portfolio.close_position(sym)

4. Run with AMM slippage and universe filtering

engine = Engine( PumpMomentum(), bars, initial_cash=100.0, # in SOL commission=0.01, slippage=AMMSlippage(), # uses poolreservelast from bar data universeprovider=CompositeFilter(AgeFilter(minbars=5), VolumeFilter(min_volume=1.0)), ) results = engine.run() print(results)

Examples

| Example | Description | |---|---| | example.py | Basic SMA crossover | | examplesmacrossover_stoploss.py | SMA crossover with ATR stop-loss and trailing stop | | examplersibracket_orders.py | RSI mean reversion with bracket orders | | examplemomentum_rotation.py | Multi-asset momentum rotation | | exampleml_strategy.py | ML model integration | | examplewalk_forward.py | Walk-forward analysis workflow | | exampleadvanced_analysis.py | Full workflow: optimization, heatmaps, Monte Carlo, permutation test | | examplelimit_orders.py | Limit orders and stop-loss | | exampletrade_analysis.py | Trade-level analysis | | example_plotting.py | Interactive chart generation | | example_commission.py | Commission model comparison | | examplemulti_asset.py | Multi-asset dict input | | exampleweight_backtest.py | Weight-based portfolio backtest | | exampledefi_trades.py | DeFi trade data pipeline with AMM slippage |

Documentation

License

MIT

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท nikkisora/PolarBT ยท Updated daily from GitHub