Free Daily Stock Backtesting with Yahoo and LumiBot¶
NOTE: Please ensure you have installed the latest lumibot version using ``pip install lumibot –upgrade`` before proceeding as there have been some major changes to the backtesting module in the latest version.
What BotSpot MCP adds
Use Claude, ChatGPT, Codex, Cursor, VS Code or another MCP-compatible assistant? Connect the free BotSpot MCP for:
Skills: build LumiBot strategies.
Free data: news, economics and SEC filings.
Backtests: run tests and read charts.
Cloud hosting: low-cost scheduled bots.
Community: share bots and discuss trades.
Marketplace: discover and publish strategies.
Broker linking: connect accounts through BotSpot.
Yahoo backtesting is so named because we get data for the backtesting from the Yahoo Finance website. The user is not required to supply data. Any stock information that is available in the Yahoo Finance API should be available for backtesting. The Yahoo backtester is only for stock data (including ETFs). Additionally, you cannot use the Yahoo backtester for intra-day trading, it is for daily trading only. For other securities, use the Polygon or Pandas backtesters.
For a complete AI stock example, see the bull/bear large-cap team. Yahoo daily bars cannot supply the 09:30 to 09:45 evidence required by the opening range breakout tutorial.
Using Yahoo backtester, you can also run backtests very easily on your strategies, you do not have to modify anything in your strategies.
To use the Yahoo backtester, you must import the YahooDataBacktesting and BacktestingBroker objects.
from lumibot.backtesting import BacktestingBroker, YahooDataBacktesting
To run a backtest, you must create a YahooDataBacktesting object, then pass it to the BacktestingBroker object. The BacktestingBroker object is then passed to the Strategy object. Finally, the Strategy object is passed to the Trader object and the backtest is run.
There are also several plots that are generated by the backtester. These plots are by defaults saved in the logs folder.
Option 1: Provide Start and End in Code¶
from datetime import datetime
from lumibot.backtesting import BacktestingBroker, YahooDataBacktesting
from lumibot.strategies import Strategy
from lumibot.traders import Trader
# A simple strategy that buys AAPL on the first day
class MyStrategy(Strategy):
def on_trading_iteration(self):
if self.first_iteration:
aapl_price = self.get_last_price("AAPL")
quantity = self.portfolio_value // aapl_price
order = self.create_order("AAPL", quantity, "buy")
self.submit_order(order)
# Pick the dates that you want to start and end your backtest in code
backtesting_start = datetime(2025, 1, 1)
backtesting_end = datetime(2025, 1, 31)
# Run the backtest
result = MyStrategy.run_backtest(
YahooDataBacktesting,
backtesting_start,
backtesting_end,
)
Using Environment Variables (Optional)¶
You can set the following environment variables without making any changes to your code. LumiBot will automatically use them if they are set. If they are not set, LumiBot will default to normal behavior (i.e., you can specify the start/end in code as above).
Below is a table describing these optional environment variables:
Variable |
Description |
Example |
|---|---|---|
IS_BACKTESTING |
(Optional) Available to startup code that explicitly checks it. It does not change a |
False |
BACKTESTING_START |
(Optional) The start date for backtesting in the format “YYYY-MM-DD”. Only needed if you are backtesting. |
2025-01-01 |
BACKTESTING_END |
(Optional) The end date for backtesting in the format “YYYY-MM-DD”. Only needed if you are backtesting. |
2025-01-31 |
Examples of how you might set these variables:
Render / Other Cloud: Define Environment Variables in your service’s dashboard.
Repl.it: Add them to your project’s “Secrets.”
Local Development: Create a .env file (or set them at the OS level).
Option 2: Rely on Environment Variables (No Start/End in Code)¶
Below is an example strategy that omits backtesting_start and backtesting_end:
from lumibot.backtesting import BacktestingBroker, YahooDataBacktesting
from lumibot.strategies import Strategy
from lumibot.traders import Trader
# A simple strategy that buys AAPL on the first day
class MyStrategy(Strategy):
def on_trading_iteration(self):
if self.first_iteration:
aapl_price = self.get_last_price("AAPL")
quantity = self.portfolio_value // aapl_price
order = self.create_order("AAPL", quantity, "buy")
self.submit_order(order)
# This call always backtests. BACKTESTING_START and BACKTESTING_END
# can supply the dates when they are omitted here.
result = MyStrategy.run_backtest(
YahooDataBacktesting
)
This example calls run_backtest() in every case. BACKTESTING_START and
BACKTESTING_END can supply omitted dates; IS_BACKTESTING=false does not
start broker execution. See Backtest, paper, or live: choose the runner for the separate broker
runner.
Frequently asked questions¶
Is Yahoo backtesting free?¶
Yes. You do not need an API key, broker account or data provider credentials. LumiBot downloads the data from Yahoo Finance with the yfinance library.
Can I backtest intraday strategies with Yahoo?¶
No. The Yahoo backtester is for daily trading only. For minute bars, use ThetaData, Polygon.io, Alpaca or your own data with Pandas.
Which assets work with the Yahoo backtester?¶
Stocks and ETFs. Any stock that Yahoo Finance has data for should work. For options, futures, forex or crypto, pick another data source from Backtesting Trading Strategies in Python with LumiBot.
How do I get historical prices in a Yahoo backtest?¶
Call self.get_historical_prices(asset, length, "day") inside your strategy, and use bars.df for the pandas DataFrame. The same call works with every LumiBot data source, so you do not have to change your strategy.
How do I add commissions and slippage to a Yahoo backtest?¶
Pass buy_trading_fees and sell_trading_fees (lists of TradingFee objects) and buy_trading_slippages and sell_trading_slippages (lists of TradingSlippage objects) to run_backtest(). See Trading Fee and Trading Slippage.
How do I select Yahoo without changing my code?¶
Set BACKTESTING_DATA_SOURCE=yahoo. This setting wins over the data source class in your code. You can also set BACKTESTING_START and BACKTESTING_END to pick the dates.
Where does LumiBot cache Yahoo data?¶
In the yahoo folder inside LUMIBOT_CACHE_FOLDER. When that variable is not set, LumiBot uses your user cache folder.
Where are the backtest results saved?¶
By default, the plots and reports go in the logs folder. See LumiBot Backtest Tear Sheets and Performance Reports and Trades Files for what each file shows.