Your logic, in plain Python.
Define strategies bar by bar. Work with built-in indicators, explicit position sizing, and execution costs on a single instrument.
Write a strategyinit()→next()→run()An open-source Python framework for backtesting,
optimization, and strategy research.
GOOG / Daily bars / 2004–2013
Precomputed with OpenBacktesting 0.2.0; switch periods to compare two recorded runs. Positions closed on the final bar. Chart rendered by this website. *Buy & hold is normalized closing price, before costs. Historical results do not predict future performance.
THE FRAMEWORK
From the first rule to the next experiment,
keep your research in your own hands.
Define strategies bar by bar. Work with built-in indicators, explicit position sizing, and execution costs on a single instrument.
Write a strategyinit()→next()→run()Explore a grid of possibilities or use optional SAMBO optimization. Compare candidates and save experiments for later analysis.
Explore optimization51020slow2040Inspect orders, trades, equity, and risk. Take pandas results and Portfolio reports into your own notebooks and charting tools.
Understand the resultsequitytradesriskPurpose-built for historical, single-asset research.
Know the model’s boundariesAN IDEA, EXPRESSED IN CODE
Two moving averages. A crossover.
A simple place to start asking better questions.
Define your rules, compare parameters, then inspect the full history behind each result. The example uses bundled GOOG data, so you can get started without a data download.
Walk through your first backtestOpenBacktesting handles the historical execution, accounting, and results.
from openbacktesting import Backtest, Strategyfrom openbacktesting.test import GOOGclass SmaCross(Strategy): fast = 10 slow = 20 def init(self): self.fast_sma = self.ta.sma(self.close, length=self.fast) self.slow_sma = self.ta.sma(self.close, length=self.slow) def next(self): if self.ta.is_crossover(self.fast_sma, self.slow_sma): self.position.close() self.buy(percent=95) elif self.ta.is_crossunder(self.fast_sma, self.slow_sma): self.position.close() self.sell(percent=95)if __name__ == "__main__": bt = Backtest(GOOG, SmaCross, cash=10_000, commission=0.002, end_policy="close_at_last_close") result = bt.run() print(result[["Return [%]", "# Trades", "Max. Drawdown [%]"]])YOUR NEXT EXPERIMENT STARTS HERE
Clone the source. Run your first strategy.
Let the evidence lead from there.
git clone https://github.com/lucidcog/openbacktesting.gitcd openbacktestinguv sync --lockeduv run --locked python examples/advanced/native_run.pySource installation · Python 3.12–3.14 · Install uv ↗
OpenBacktesting is an open-source Python framework for historical backtesting, parameter optimization, and strategy research. Write strategy rules, simulate their execution on historical market data, and inspect trades, equity, and risk statistics.
Yes. Pass a pandas DataFrame with Open, High, Low, and Close columns. Volume is optional unless an indicator needs it. Each backtest models one asset in a single settlement currency. See the market data guide for requirements.
Use Python 3.12–3.14, clone the GitHub repository, and run uv sync --locked. You can also install the checked-out source with python -m pip install .. Add the optimize extra for parameter searches. The commands above run a complete bundled example.
The framework focuses on historical research. It exports results and plotting data for your own renderer; it does not include a chart renderer or live-trading engine. The interactive chart on this website displays precomputed framework results. Read the current scope and limitations.
Open tools take real support.
Pineify is our top paid sponsor, helping fund the framework.