# Backtesting.py

Two thousand lines, one OHLC series, and no idea what a funding payment is.

*https://cryptomarkets.tools/tools/backtesting-py · Backtesting & Research Libraries*

## Also covered on

- [Backtesting.py on StockMarketStack](https://stockmarketstack.com/tools/backtesting-py.md) — the same library on daily equities, where its assumptions cost far less

## Facts

### At a glance

| Field | Value |
| --- | --- |
| Vendor | kernc |
| Category | Backtesting & Research Libraries |
| Job | backtesting |
| Website | https://kernc.github.io/backtesting.py/ |
| Pricing model | open-source |
| Free tier | true |
| Open source | true |
| Licence | AGPL-3.0-only |
| Self-hosted | true |
| KYC required | false |
| Tested hands-on | false |
| Last updated | 2026-09-19 |

### Coverage

| Field | Value |
| --- | --- |
| Asset classes | spot |
| Chains | none |
| Venues | none |
| Data latency | none |
| Platforms | library |
| AI features | none |

### Interfaces

| Field | Value |
| --- | --- |
| API | false |
| Webhooks | false |
| Scripting | Python |
| MCP server | false |
| Export | none |

### Capabilities

Yes: charting, backtesting

No: screening, automation, live_trading, paper_trading, portfolio_tracking, exchange_import, tax_reporting, alerts, news, onchain_data, wallet_tracking, derivatives_analytics

*Verified: pricing 2026-09-19; capabilities 2026-09-19; coverage 2026-09-19.*

## What it is

A Python backtester in about two thousand lines. You hand `Backtest` a single pandas DataFrame
with `Open`, `High`, `Low`, `Close` and optionally `Volume`, and a `Strategy` subclass with an
`init()` that computes indicators and a `next()` that runs once per bar. It returns a pandas
Series of statistics and a trades DataFrame, and `bt.plot()` draws an interactive Bokeh chart with
every entry and exit marked on the candles.

It was written for any instrument with candles and it shows: the engine knows about price, size,
commission and spread, and nothing else. That is a real virtue when you are testing a spot
rotation and a real problem when you are testing a perp.

The maintainer publishes under the GitHub account `kernc`; there is no company behind it and
nothing is sold.

## Pricing

Free, and there is no paid anything. The package is on PyPI as `backtesting`, the repository is
under the AGPL, and the only money link in the README is a GitHub Sponsors badge for the
maintainer. There is no hosted tier, no data bundle and no commercial licence on offer, which is
why this card carries no price table at all.

The AGPL is the part with a cost attached. Running it locally for your own research is the
uncomplicated case. Putting it behind a web service other people use is the case the network
clause was written for, and it is worth reading before you build a product on top.

## Data & coverage

It ships no data and has no notion of a venue. You supply the candles; the library never makes a
network call. Three sample series come with the package for the tutorials — `GOOG`, `EURUSD` and
`BTCUSD` in `backtesting.test` — and they are examples, not a feed.

The input contract is strict in a useful way: the four OHLC columns must be present and must not
contain NaNs, and the index has to be either a datetime index or a monotonic range index. Extra
columns are passed through to the strategy, which is how people attach funding rates, order-book
imbalance or sentiment as a signal — but they are signals, not something the accounting
understands.

Fills happen at the next bar's open by default, or at the current bar's close with
`trade_on_close=True`. There is no intrabar path: a bar that touches both your stop and your take
profit is resolved by the engine's ordering rules, not by what actually happened inside the
minute. On a 1m crypto series that matters more than it does on daily equities.

## Integrations

Effectively none, by design. The dependencies are numpy, pandas and bokeh, Python 3.9 or newer,
and the library is indicator-agnostic — `self.I()` wraps any function that returns an array, so
TA-Lib, pandas-ta or your own numpy works the same way. The parameter optimiser has a grid mode
and a model-based mode built on SAMBO.

There are no exchange connectors, no broker adapters and no live loop. Whatever pulls the candles
and whatever places the orders are your problem, and the strategy you tested is not the code that
will run.

## Limitations

**No funding, at all.** Grep the engine for `funding`, `perpetual` or `liquidation` and you get
nothing. The only cost inputs are `spread` and `commission`, which is a flat rate, a
`(fixed, relative)` pair or a callable on order size and price. For a perp strategy held across
funding boundaries that is not an approximation, it is a missing leg, and it flatters carry-negative
strategies for as long as you leave it out.

**No maintenance margin and no mark-price liquidation.** The docstring is blunt about it: "`margin`
is the required margin (ratio) of a leveraged account. No difference is made between initial and
maintenance margins." One number sets leverage and nothing checks it again. The simulation stops
only when total equity reaches zero, at which point the broker closes everything and zeroes the
rest of the equity curve. An exchange would have taken the position long before that, at a mark
price this engine does not have.

**The defaults cost nothing.** `spread=0`, `commission=0`, `margin=1`. A first run of any
high-turnover idea will look wonderful and mean nothing. Set both before you read a single
statistic.

**One instrument per backtest.** `MultiBacktest` runs the same strategy over several DataFrames in
parallel to compare results per ticker; it is not a portfolio. Cross-pair basis, a funding-carry
pair trade, or anything that sizes one leg against another cannot be expressed.

**Whole units, unless you rescale.** The base class refuses fractional sizes and warns when a close
exceeds your starting cash. `FractionalBacktest` multiplies the whole series by `fractional_unit`,
one satoshi by default, and divides volume by it — workable, and a wrapper you have to know
exists.

**It has stopped before.** PyPI has 0.3.3 in December 2021 and then nothing until January 2025,
when 0.4.0 and 0.5.0 were uploaded twenty seconds apart. Development since has been steady — eight
tagged releases across 2025 and 2026 — but the gap is in the record, and it is the reason to check the
dates yourself rather than trust a "actively maintained" line anywhere, including this one.

## Alternatives

If the strategy is spot and the instrument is one pair, the small surface here is the feature. If
it is a perp, the question is not which library is nicer to write against but which one charges
funding and liquidates at a mark price — the rest of
[this category](https://cryptomarkets.tools/categories/backtesting-libraries) is where to look.

## FAQ

### Is backtesting.py still maintained in 2026?

Yes, with a caveat about its history. The last release is 0.6.6, published to PyPI on 2026-07-22, and the last commit on master is 2026-08-05. The repository is not archived. But PyPI shows nothing at all between 0.3.3 in December 2021 and January 2025, so the project has gone quiet for years once already.

### Can backtesting.py backtest perpetual futures?

Not properly. The engine has no concept of a funding rate, a mark price or a maintenance-margin liquidation — the words do not appear in the source. You can simulate a levered position with the margin parameter, but the funding leg that usually decides a perp strategy simply is not charged.

### Does backtesting.py handle Bitcoin prices out of the box?

Only if you rescale. The default Backtest class trades whole units against 10,000 in starting cash, so a five-figure BTC price triggers a warning and places nothing. The FractionalBacktest wrapper rescales the series to satoshis, which is the intended workaround.

### What licence is backtesting.py under?

The LICENSE.md file in the repository is the plain GNU Affero General Public License v3 text. The AGPL network clause is the part to read if you plan to run it behind a hosted service rather than on your own machine.

## Also worth comparing

- [Barter](https://cryptomarkets.tools/tools/barter.md) — Rust trading engine and market-data streams — live execution is a trait you implement.
- [HftBacktest](https://cryptomarkets.tools/tools/hftbacktest.md) — Tick-by-tick backtesting that models order queue position and feed and order latency.
- [LEAN](https://cryptomarkets.tools/tools/lean.md) — The engine behind QuantConnect, Apache-2.0 and runnable on your own machine.
- [Lumibot](https://cryptomarkets.tools/tools/lumibot.md) — One Python strategy that backtests and then trades live, across eight CCXT exchanges.
- [NautilusTrader](https://cryptomarkets.tools/tools/nautilus-trader.md) — Event-driven Rust engine that settles perpetual funding at the venue boundary.
- [Jesse](https://cryptomarkets.tools/tools/jesse.md) — Python backtesting and research framework whose live-trading half is a paid plugin.
