Lumibot: backtestable AI trading agents and Python strategies, with the GPL catch
Backtestable AI trading agents and Python algorithmic trading strategies for stocks, options, crypto, futures, forex, SEC filings, FRED macro data, and real brokers.
At a glance
- What is it?
- Lumibot wraps deterministic Python strategies and LLM agent teams in the same backtest-and-broker loop. The interesting part is the shared loop. The awkward part is a GPL-3.0 licence on a library you are meant to import into your own code.
- Who is it for?
- Adopt Lumibot if you already write Python trading logic and want the same Strategy subclass to run a YahooDataBacktesting replay, an Alpaca paper account, and an LLM research team without rewriting the execution layer.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap Lumibot targets: one strategy class, three execution contexts
Most retail algo stacks split into two camps. Backtesting frameworks replay historical bars but have no order routing. Broker SDKs route orders but give you no replay. Lumibot's pitch is that a single class, subclassed from lumibot.strategies.Strategy, is the unit of work in both cases. The README's quick start makes the claim concrete: the same MyStrategy class that defines on_trading_iteration is passed to MyStrategy.backtest(YahooDataBacktesting, datetime(2023, 1, 1), datetime(2024, 1, 1)) in the backtest example, and is then instantiated as MyStrategy(broker=broker) with an Alpaca broker object in the paper-trading example. The audience is a Python developer who already knows what an indicator is and does not want to learn a domain-specific strategy language. The README frames the choice as fixed rules, AI agents, or a hybrid where Python handles the hard gates and agents reason through evidence.
What actually runs: the Strategy loop, the broker object, and the Trader
The architecture visible in the README is three layers. The Strategy subclass owns the decision logic and exposes lifecycle hooks, of which on_trading_iteration is the one shown. It also exposes helpers such as self.create_order("AAPL", 10, "buy") and self.submit_order(...), plus a self.first_iteration flag the sample uses to trade once. Below that sits a broker adapter. The example imports from lumibot.brokers import Alpaca and constructs it with a plain dict carrying API_KEY, API_SECRET and PAPER. Above the strategy sits lumibot.traders.Trader, which is instantiated, given strategies via trader.add_strategy(strategy), and started with trader.run_all(). Backtesting swaps the broker layer for a data source class, here YahooDataBacktesting, passed as the first positional argument to the classmethod backtest. The README states that backtests replay historical data and simulated orders with artifacts you can inspect, though it does not describe the artifact format. That is a documentation gap worth noting before you commit to an audit trail.
The AI agent runtime and its tool list
The newer layer is an agent runtime that runs inside the same strategy loop. According to the README, agents can inspect market data, read filings, query indicators, search memory, compare macro context, and submit orders through the same loop used by normal backtests and live trading. The tool list is explicit: market and account state, order inspection, DuckDB queries, documentation search, Alpaca news when credentials exist, technical indicators, SEC fundamentals and filings, FRED macro data, local memory, and Telegram notifications. Note the conditional on Alpaca news. Several tools depend on credentials you supply, so the agent's evidence pack is only as wide as your API keys. The README's worked pattern is a four-role team: a research agent builds an evidence pack, a bull agent argues the long case, a bear agent argues for avoiding, delaying or reducing the trade, and a trader or portfolio manager agent checks cash, positions, open orders and risk limits before deciding. The sample uses Gemini Flash Lite, which the README justifies on speed and cost for experiments rather than on reasoning quality. That is a fair description of a small model, and it also means the debate pattern is only as good as the model you swap in.
Getting it running: the exact commands and config keys in the README
Install with pip install lumibot. The backtest path needs no credentials: save the sample as my_strategy.py and run python my_strategy.py. The paper path needs three environment variables, ALPACA_API_KEY, ALPACA_API_SECRET and ALPACA_IS_PAPER, and the README's config dict reads PAPER as os.environ.get("ALPACA_IS_PAPER", "true").lower() != "false", so any value other than the literal string false is treated as paper. That is a forgiving default and a sharp edge at the same time: ALPACA_IS_PAPER=0 or ALPACA_IS_PAPER=no will not switch you to live, they will silently keep you on paper. The agent example adds GEMINI_API_KEY and is run as python ai_trading_team_bull_bear_leveraged_etf.py, with the README noting that flipping IS_BACKTESTING from False to True in the runner backtests the same strategy. The README does not give a full list of supported brokers beyond Alpaca and Interactive Brokers appearing in the repository topics, so treat broker coverage as something to confirm per broker in the docs rather than assume from the topic tags.
Where it breaks: LLM agents in a backtest are not a historical simulation
The headline feature is also the weakest link. When an agent reasons over filings, news and macro data during a backtest, the model is not the model that existed at the historical timestamp, and the news and filing corpus is whatever the live tools return now. The README does not describe point-in-time reconstruction of the agent's evidence, so a backtested agent strategy is best read as a logic rehearsal rather than a performance estimate. The same caution applies to YahooDataBacktesting: it is one named data source, and the README gives no statement about survivorship bias, dividend adjustment, or how options and futures chains are reconstructed historically. Lumibot lists stocks, options, crypto, futures, forex, SEC filings and FRED in its description, which is a wide surface for a single backtesting data class to cover honestly. If your strategy depends on option greeks or futures roll schedules, confirm the data path before trusting a backtest number. And if you only ever trade one asset class against one broker, a plain pandas loop plus that broker's SDK is less machinery to reason about.
Alternatives and the actual difference in approach
Backtrader is the closest comparison for the deterministic half. It is a Python backtesting engine built around its own strategy and indicator class hierarchy, and it does not ship a broker adapter layer with the same paper-to-live path the README shows for Alpaca, nor an agent runtime. The difference is where the abstraction sits: Backtrader abstracts the strategy into its own object model, while Lumibot keeps the strategy as a plain Python class with lifecycle hooks and moves the swapping to the data source and broker arguments. If your work is research on historical bars, that distinction favors Backtrader. If your work is one strategy that must survive the move from replay to a funded account, it favors Lumibot. On the agent side, the honest comparison is not another library but your own code: a few dozen lines calling an LLM with your own tool functions gives you the same debate pattern with full control over what evidence the model sees and when. Lumibot's value there is the pre-built tool set and the fact that agent output can reach submit_order through the same loop, not the pattern itself.
Licence, release cadence, and what that costs you
The repository metadata says GPL-3.0. The README's own badge says License: MIT and links to a LICENSE file. Those cannot both be right, and it matters more than usual here: GPL-3.0 on a library you import into your own strategy code is a different proposition from GPL on a standalone tool. If the repository licence governs, distributing a product that imports lumibot brings the copyleft question into scope, and that is a conversation for your own counsel, not for this article. The release cadence is visible and fast: v4.5.88 on 2026-09-01, v4.5.90 on 2026-09-04, v4.5.91 on 2026-09-06, with the default branch set to dev rather than main. Frequent patch releases on a dev default branch mean you should pin an exact version in your requirements file rather than track the branch, because the agent runtime and broker adapters are the parts most likely to move. The README also points to a managed cloud deployment at BotSpot.trade and an MCP integration for AI coding agents, so part of the project's direction is commercial hosting around the open-source core. That is a normal arrangement, but it tells you where the maintainers' operational attention is likely to sit.
Editorial conclusion
Adopt Lumibot if you already write Python trading logic and want the same Strategy subclass to run a YahooDataBacktesting replay, an Alpaca paper account, and an LLM research team without rewriting the execution layer. Do not adopt it if you intend to ship a closed-source product that imports the library, because the repository is GPL-3.0 even though the README badge still says MIT, and that discrepancy is the first thing to resolve with the maintainers before you build on it. Verify the licence file in the tree you pin, and verify that your broker's asset class is actually covered by the data source you plan to backtest against.
Community notes