Skip to main content

Lightweight backtesting library built on polars

Project description

PolarBT

PolarBT

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
  • Multi-asset — pass a dict of DataFrames for portfolio strategies
  • 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)
  • 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, format_results
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("sma_fast", "sma_slow").alias("buy"),
            ind.crossunder("sma_fast", "sma_slow").alias("sell"),
        )

    def next(self, ctx: BacktestContext) -> None:
        if ctx.row.get("buy"):
            ctx.portfolio.order_target_percent("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, initial_cash=100_000)
results = engine.run()

# Pretty-print results
print(format_results(results))

# Interactive chart saved to HTML
fig = plot_backtest(engine, title="SMA Crossover — AAPL", indicators=["sma_fast", "sma_slow"])
fig.write_html("backtest.html")
Equity Final [$]                        366,237.10
Equity Peak [$]                         433,931.04
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
Profit Factor                                 1.79
Expectancy [$]                             6338.98
SQN                                           1.27
Kelly Criterion                             0.2098

PolarBT

Examples

Example Description
example.py Basic SMA crossover
example_sma_crossover_stoploss.py SMA crossover with ATR stop-loss and trailing stop
example_rsi_bracket_orders.py RSI mean reversion with bracket orders
example_momentum_rotation.py Multi-asset momentum rotation
example_ml_strategy.py ML model integration
example_walk_forward.py Walk-forward analysis workflow
example_advanced_analysis.py Full workflow: optimization, heatmaps, Monte Carlo, permutation test
example_limit_orders.py Limit orders and stop-loss
example_trade_analysis.py Trade-level analysis
example_plotting.py Interactive chart generation
example_commission.py Commission model comparison
example_multi_asset.py Multi-asset dict input

Documentation

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polarbt-0.1.3.tar.gz (132.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

polarbt-0.1.3-py3-none-any.whl (82.9 kB view details)

Uploaded Python 3

File details

Details for the file polarbt-0.1.3.tar.gz.

File metadata

  • Download URL: polarbt-0.1.3.tar.gz
  • Upload date:
  • Size: 132.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for polarbt-0.1.3.tar.gz
Algorithm Hash digest
SHA256 c69ba821c638b264531023933ca3b7f4bd635a08fbb5a781ad796718410974d8
MD5 82409c9057f13fbce997351bb038cd7c
BLAKE2b-256 c0eaa4fa153564c131daa31b6f319a689f86ec331e90ca20db2dd44ed71fa825

See more details on using hashes here.

Provenance

The following attestation bundles were made for polarbt-0.1.3.tar.gz:

Publisher: publish.yml on nikkisora/PolarBT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polarbt-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: polarbt-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 82.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for polarbt-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 b0299e6574291152b899b63e9c3d76b1e7ad6ceb54eda36bc0dcb34e5a473c56
MD5 496a10325782a56019962be2ffc61396
BLAKE2b-256 db1f93014edf0ab4bab6927f282c5c7585e1d6454c81028912838859cb0e2994

See more details on using hashes here.

Provenance

The following attestation bundles were made for polarbt-0.1.3-py3-none-any.whl:

Publisher: publish.yml on nikkisora/PolarBT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page