Metadata-Version: 2.4
Name: polarbt
Version: 0.1.3
Summary: Lightweight backtesting library built on polars
Author: PolarBT Contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/nikkisora/PolarBT
Project-URL: Repository, https://github.com/nikkisora/PolarBT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: polars>=0.19.0
Requires-Dist: numpy>=1.24.0
Provides-Extra: plotting
Requires-Dist: plotly>=5.0.0; extra == "plotting"
Provides-Extra: talib
Requires-Dist: TA-Lib>=0.4.0; extra == "talib"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: plotly>=5.0.0; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="assets/cover.png" alt="PolarBT" width="600">
</p>

# PolarBT

A lightweight, high-performance backtesting library for trading strategy development and optimization. Built on [Polars](https://pola.rs/) 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

```bash
pip install polarbt
```

Or with optional extras:

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

Install from source:

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

## Quick Start

```python
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")

```

```text
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
```
<p align="center">
  <img src="assets/example_plot.png" alt="PolarBT" width="100%">
</p>

## Examples

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

## Documentation

- [Getting Started Guide](docs/getting-started.md)
- [API Reference](docs/api-reference.md)
- [Complete Reference](docs/complete-reference.md)

## License

[MIT](LICENSE)
