{"id":6541,"library":"backtesting","title":"Backtesting.py","description":"Backtesting.py is a Python framework for backtesting trading strategies on historical candlestick data. It provides a fast, lightweight, and user-friendly API to define strategies, run simulations, inspect detailed statistics, and explore interactive charts. It is currently at version 0.6.5 and is actively maintained with regular releases.","status":"active","version":"0.6.5","language":"en","source_language":"en","source_url":"https://github.com/kernc/backtesting.py/","tags":["finance","trading","backtesting","quantitative analysis","algorithmic trading","data visualization"],"install":[{"cmd":"pip install backtesting","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Numerical array operations and indicator computation.","package":"numpy","optional":false},{"reason":"DataFrame-based OHLCV data handling and results.","package":"pandas","optional":false},{"reason":"Interactive HTML chart output. Specific versions (3.0.x and 3.2.x) are known to be incompatible.","package":"bokeh","optional":false}],"imports":[{"symbol":"Backtest","correct":"from backtesting import Backtest"},{"symbol":"Strategy","correct":"from backtesting import Strategy"},{"symbol":"crossover","correct":"from backtesting.lib import crossover"},{"note":"SMA is a test utility; for real strategies, users typically import from other indicator libraries (e.g., pandas_ta, TA-Lib).","symbol":"SMA","correct":"from backtesting.test import SMA"},{"note":"GOOG is a built-in test dataset; users typically provide their own pandas DataFrames.","symbol":"GOOG","correct":"from backtesting.test import GOOG"}],"quickstart":{"code":"from backtesting import Backtest, Strategy\nfrom backtesting.lib import crossover\nfrom backtesting.test import SMA, GOOG\n\nclass SmaCross(Strategy):\n    def init(self):\n        price = self.data.Close\n        self.ma1 = self.I(SMA, price, 10)\n        self.ma2 = self.I(SMA, price, 20)\n\n    def next(self):\n        if crossover(self.ma1, self.ma2):\n            self.buy()\n        elif crossover(self.ma2, self.ma1):\n            self.sell()\n\n# Prepare data (using built-in test data for quickstart)\n# In a real scenario, you'd load your own pandas.DataFrame\n# with columns 'Open', 'High', 'Low', 'Close', 'Volume' (optional)\n# and a DatetimeIndex.\n# For example: from pandas_datareader import data as yf\n#              data = yf.DataReader('SPY', start='2000', end='2020')\n\nbt = Backtest(GOOG, SmaCross, cash=10000, commission=.002, exclusive_orders=True)\nstats = bt.run()\nprint(stats)\nbt.plot(open_browser=False)","lang":"python","description":"This quickstart defines a simple Moving Average Crossover strategy. It initializes two Simple Moving Averages (SMAs) in `init()` using `self.I()` to prevent look-ahead bias, and then places buy/sell orders in `next()` based on their crossover. The `Backtest` instance is run with historical Google stock data, and performance statistics are printed, followed by an interactive plot."},"warnings":[{"fix":"Review existing strategies using `commission` and adjust if needed, or migrate to `spread` for one-time entry costs.","message":"The `Backtest(commission=)` parameter in versions 0.6.0 and later now applies commission *twice* per trade (at both entry and exit). If you intend for costs to be applied only once at entry (e.g., for spread/slippage), use the new `Backtest(spread=)` parameter instead.","severity":"breaking","affected_versions":"0.6.0+"},{"fix":"Consult the changelog and documentation for the 0.2.0 release to update strategy logic and order management to the new API.","message":"Version 0.2.0 introduced a completely new `Order / Trade / Position API`. Strategies written for versions prior to 0.2.0 are incompatible and require significant updates to use the new API.","severity":"breaking","affected_versions":"<0.2.0"},{"fix":"Force a compatible Bokeh version during installation: `pip install \"bokeh>=3.1,!=3.2.*\"`.","message":"Bokeh versions 3.0.x and 3.2.x are known to have incompatibilities with `backtesting.py`'s interactive plotting feature, potentially leading to errors.","severity":"gotcha","affected_versions":"All versions depending on Bokeh 3.0.x or 3.2.x"},{"fix":"Understand and account for this execution model. For more granular control or intra-candle trading, use higher-frequency data.","message":"Trading decisions made in the `next()` method are typically executed on the *next* bar's open price (or current bar's close if `trade_on_close=True`). This simulation characteristic means immediate execution at the exact candle price that triggered a signal is not guaranteed, which can impact profitability, especially for high-frequency or tight stop-loss/take-profit strategies.","severity":"gotcha","affected_versions":"All"},{"fix":"Always use `self.I(indicator_func, data_series, *args)` for all technical indicators in your `init()` method.","message":"When defining indicators within `Strategy.init()`, it's crucial to wrap indicator functions with `self.I()`. This ensures that indicator values are revealed gradually, bar-by-bar, simulating real-time data availability and preventing look-ahead bias. Failing to do so (e.g., directly computing indicators on `self.data.Close` for the full dataset outside `self.I()`) will lead to unrealistic, overly optimistic backtest results.","severity":"gotcha","affected_versions":"All"},{"fix":"Ensure your strategy includes logic to close positions, either explicitly with an opposing order or `self.position.close()`, or by using `exclusive_orders=True` in `Backtest` constructor to automatically close previous positions on new opposing orders.","message":"If a trading position is opened with `self.buy()` or `self.sell()` but never explicitly closed (e.g., with `self.position.close()`, `self.sell()`, or `self.buy()`), it will remain open until the end of the backtest. This can lead to misleading or `NaN`/`0` values in performance statistics because trades are not fully realized within the backtesting period.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}