Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
823a87b
save
grzesir Nov 18, 2025
a9afa21
save and deploy
grzesir Nov 19, 2025
42971ec
bug fixes and docs update
grzesir Nov 21, 2025
83968bf
Wording to switch to ThetaData.
grzesir Nov 21, 2025
308e41c
save. theta almost fully working
grzesir Nov 22, 2025
2d2b6e4
Document remote guardrails and trust downloader readiness
grzesir Nov 22, 2025
1a1574a
Massive improvements for Theta data.
grzesir Nov 23, 2025
d776842
deploy
grzesir Nov 23, 2025
0a6cff7
test fixes
grzesir Nov 23, 2025
64f8bca
bug fixes for theta data + added tests
grzesir Nov 23, 2025
b0af23d
deployed
grzesir Nov 23, 2025
1c69e75
Bug fixes for Theta Data S3 caching.
grzesir Nov 24, 2025
855ad76
deploy 4.4.0
grzesir Nov 24, 2025
64ea7b9
Fix cash accounting and tearsheet prep
grzesir Nov 26, 2025
b09c8b6
Add position sign tests and bracket regression
grzesir Nov 26, 2025
aad915c
deploy
grzesir Nov 26, 2025
aafec49
theta cache download problem fixed
grzesir Nov 28, 2025
e56487b
Huge improvements to ThetaData backtesting. Including better caching …
grzesir Nov 29, 2025
c60cd37
Saved. Backtest working very well now for ThetaData
grzesir Nov 29, 2025
1528643
Clean up logs and fix option Greeks for Theta data.
grzesir Nov 29, 2025
8e7f01f
Fix linting errors and undefined name references
grzesir Nov 29, 2025
a2d515e
Fix undefined name errors (F821) for CI
grzesir Nov 29, 2025
f8b9bf6
Reduce integration test date ranges for faster CI
grzesir Nov 29, 2025
894fa67
Fix integration tests: don't require trades for ThetaData verification
grzesir Nov 29, 2025
ffc10ef
Fix CI test failures: prevent data source override for legacy tests
grzesir Nov 29, 2025
29894ff
Fix CI: set BACKTESTING_DATA_SOURCE=none to prevent ThetaData override
grzesir Nov 30, 2025
9256502
Fix test failures: ThetaData-only optimization and test cleanup
grzesir Nov 30, 2025
9425310
fix: revert PandasData filter direction to avoid order fill regression
grzesir Nov 30, 2025
cb6ad2d
fix: revert PANDAS section changes to fix Polygon/multileg test regre…
grzesir Nov 30, 2025
6abf82c
fix: extend mock data coverage in test_update_pandas_data_fetches_rea…
grzesir Nov 30, 2025
5530333
fix: update test_stock_diversified_leverage expected CAGR to match cu…
grzesir Dec 1, 2025
305a493
chore: remove CLAUDE.md and AGENTS.md from repo and add to gitignore
grzesir Dec 1, 2025
ef7f64f
add asset to add_marker and add_line
grzesir Dec 2, 2025
df0cc95
fix: handle ALL 503 errors with exponential backoff and circuit breaker
grzesir Dec 4, 2025
d1c3078
Add ThetaData queue client for reliable request processing
grzesir Dec 5, 2025
1f9d075
Make queue mode the ONLY way to connect to ThetaData
grzesir Dec 5, 2025
d4720b8
Fix ThetaData v2 endpoint parameters to use v3 naming convention
grzesir Dec 5, 2025
fb54ccf
Revert v2 endpoint parameters to correct v2-style names
grzesir Dec 5, 2025
556aad2
Fix ThetaData v3 columnar format conversion for queue system
grzesir Dec 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/cicd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,18 @@ jobs:

env:
AIOHTTP_NO_EXTENSIONS: 1
# CRITICAL: Set this to "none" so tests use their explicit data sources.
# Tests that want ThetaData must explicitly request it.
# Without this, the default is "ThetaData" which overrides ALL backtests.
BACKTESTING_DATA_SOURCE: none
POLYGON_API_KEY: ${{ secrets.POLYGON_API_KEY }}
THETADATA_USERNAME: ${{ secrets.THETADATA_USERNAME }}
THETADATA_PASSWORD: ${{ secrets.THETADATA_PASSWORD }}
# NOTE (2025-11-28): Data Downloader is a production proxy for ThetaData that allows
# shared access without requiring a local ThetaTerminal JAR. When these are set,
# ThetaData tests will use the remote downloader instead of spawning a local process.
DATADOWNLOADER_BASE_URL: ${{ secrets.DATADOWNLOADER_BASE_URL }}
DATADOWNLOADER_API_KEY: ${{ secrets.DATADOWNLOADER_API_KEY }}
ALPACA_TEST_API_KEY: ${{secrets.ALPACA_TEST_API_KEY}} # Required for alpaca unit tests
ALPACA_TEST_API_SECRET: ${{secrets.ALPACA_TEST_API_SECRET}} # Required for alpaca unit tests
TRADIER_TEST_ACCESS_TOKEN: ${{secrets.TRADIER_TEST_ACCESS_TOKEN}} # Required for tradier unit tests
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ data/SRNE_Minute.csv
.env
token.json
schwab_token.json

# AI assistant instruction files (contain local paths)
CLAUDE.md
AGENTS.md
426 changes: 426 additions & 0 deletions BACKTESTING_ARCHITECTURE.md

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@

Lumibot is a backtesting and trading library for stocks, options, crypto, futures and more. It is made so that the same code you use for backtesting can be used for live trading, making it easy to transition from backtesting to live trading. Lumibot is a highly flexible library that allows you to create your own strategies and indicators, and backtest them on historical data. It is also highly optimized for speed, so you can backtest your strategies quickly and efficiently.

**IMPORTANT: This library requires data for backtesting. The recommended data source is [Polygon.io](https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10) (a free tier is available too). Please click the link to give us credit for the sale, it helps support this project. You can use the coupon code 'LUMI10' for 10% off.**
**IMPORTANT: This library requires data for backtesting. Our recommended data source is [ThetaData](https://www.thetadata.net/) because they provide the deepest historical coverage we’ve found and directly support BotSpot. Use the promo code `BotSpot10` at checkout for 10% off the first order (the code also tells ThetaData you were referred by us).**

> **Contributor note:** Read `AGENTS.md` before running anything Theta-related. That file spells out the hard rules—never launch ThetaTerminal or the shared downloader locally, always point LumiBot at the AWS-hosted downloader, and wrap all long
> commands with `/Users/robertgrzesik/bin/safe-timeout`. Breaking these rules kills the only licensed Theta session.

## Architecture Documentation

- `BACKTESTING_ARCHITECTURE.md` - Detailed documentation of the backtesting data flow (Yahoo, ThetaData, Polygon data sources, caching, and data flow diagrams)
- `CLAUDE.md` - AI assistant instructions for working with the codebase
- `AGENTS.md` - Critical rules for ThetaData and production safety

## Documentation - 👇 Start Here 👇

Expand Down
39 changes: 17 additions & 22 deletions docsrc/backtesting.how_to_backtest.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
How To Backtest
===================================

Backtesting is a vital step in validating your trading strategies using historical data. With LumiBot, you can backtest strategies across various data sources such as **Yahoo Finance**, **Polygon.io**, **ThetaData**, or even your own custom **CSV** files. This guide will walk you through each step of backtesting, explain the data sources, and introduce the files that LumiBot generates during backtesting.
Backtesting is a vital step in validating your trading strategies using historical data. With LumiBot, you can backtest strategies across various data sources such as **ThetaData** (our recommended vendor), **Polygon.io**, **Yahoo Finance**, or even your own custom **CSV** files. This guide will walk you through each step of backtesting, explain the data sources, and introduce the files that LumiBot generates during backtesting.

.. note::

Expand Down Expand Up @@ -41,38 +41,33 @@ Choosing a Data Source

LumiBot supports several data sources for backtesting, each suited for different asset types and backtesting needs. Here's an overview of the available sources:

**1. Yahoo Finance**
**1. ThetaData (Recommended)**

- Free stock and ETF data for daily trading backtests.
- Suitable for longer-term strategies but not ideal for intraday backtesting.

For more details, see the :ref:`Yahoo Backtesting <backtesting.yahoo>` section.
- Deep historical coverage for U.S. equities and options with SIP-quality filtering.
- Offers free tiers plus paid plans with higher rate limits and multi-year history.

**2. Polygon.io**
.. important::

- Offers intraday and end-of-day data for stocks, options, forex, and cryptocurrency.
- Provides up to two years of free data; paid plans offer more advanced features and faster data retrieval.
**Get Your ThetaData Account**

.. important::
Sign up at `ThetaData <https://www.thetadata.net/>`_. Use the promo code ``BotSpot10`` for 10% off the first order—ThetaData uses this code to credit BotSpot for the referral.

**Get Your API Key from Polygon.io**

You can get an API key at `Polygon.io <https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10>`_. **Please use the coupon code 'LUMI10' for 10% off!**
For more details, see the :ref:`ThetaData Backtesting <backtesting.thetadata>` section.

For more details, see the :ref:`Polygon.io Backtesting <backtesting.polygon>` section.
**2. Yahoo Finance**

**3. ThetaData**
- Free stock and ETF data for daily trading backtests.
- Suitable for longer-term strategies but not ideal for intraday backtesting.

- Designed for users looking to backtest stock and options trading strategies.
- Provides options pricing and other securities.
For more details, see the :ref:`Yahoo Backtesting <backtesting.yahoo>` section.

.. important::
**3. Polygon.io**

**Get Your ThetaData Account**
You can get a username and password at `thetadata.net <https://www.thetadata.net/>`_. **Please use the coupon code 'LUMI' for 10% off!**
- Offers intraday and end-of-day data for stocks, options, forex, and cryptocurrency.
- Provides up to two years of free data; paid plans offer more advanced features and faster data retrieval.
- Best suited for existing workflows; new LumiBot users should consider ThetaData first for the BotSpot10 promo and deeper coverage.

For more details, see the :ref:`ThetaData Backtesting <backtesting.thetadata>` section.
For more details, see the :ref:`Polygon.io Backtesting <backtesting.polygon>` section.

**4. Pandas (CSV or Other Custom Data)**

Expand Down
4 changes: 2 additions & 2 deletions docsrc/backtesting.polygon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Polygon.io Backtesting

.. important::

**You can get an API key at** `Polygon.io <https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10>`_. **Please use the full link to give us credit for the sale (https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10), it helps support this project. You can use the coupon code 'LUMI10' for 10% off.**
**ThetaData is our preferred data partner and the service we recommend to most LumiBot users—sign up at** `ThetaData <https://www.thetadata.net/>`_ **and use the promo code ``BotSpot10`` for 10% off the first order.** This section remains for teams that still need Polygon.io. If you require Polygon access you can create an account at `polygon.io <https://polygon.io/>`_.

Polygon.io backtester allows for flexible and robust backtesting. It uses the polygon.io API to fetch pricing data for stocks, options, forex, and cryptocurrencies. This backtester simplifies the process of getting pricing data; simply use the PolygonDataSource and it will automatically fetch pricing data when you call `get_last_price()` or `get_historical_prices()`.

Expand Down Expand Up @@ -104,7 +104,7 @@ Here's the full code (with explicit dates):

.. important::

**You can get an API key at** `Polygon.io <https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10>`_. **Please use the full link to give us credit for the sale (https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10), it helps support this project. You can use the coupon code 'LUMI10' for 10% off.**
**ThetaData remains our recommended vendor (promo code ``BotSpot10`` at `thetadata.net <https://www.thetadata.net/>`_). These Polygon instructions are provided for existing workflows that still rely on Polygon’s API.**

Optional: Environment Variables
-------------------------------
Expand Down
2 changes: 1 addition & 1 deletion docsrc/backtesting.thetadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ThetaData Backtesting

.. important::

**You can get a username and password at** `thetadata.net <https://www.thetadata.net/>`_. **Please use the full link to give us credit for the sale (https://www.thetadata.net), it helps support this project. You can use the coupon code 'LUMI' for 10% off.**
**Sign up at** `ThetaData <https://www.thetadata.net/>`_. **Use the promo code ``BotSpot10`` at checkout for 10% off the first order—ThetaData tracks the code so they can credit BotSpot for the referral.**

ThetaData backtester allows for flexible and robust backtesting. It uses the thetadata API to fetch pricing data for stocks, options, forex, and cryptocurrencies. This backtester simplifies the process of getting pricing data; simply use the thetadata DataSource and it will automatically fetch pricing data when you call `get_last_price()` or `get_historical_prices()`.

Expand Down
29 changes: 26 additions & 3 deletions lumibot/backtesting/backtesting_broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,25 @@ def get_historical_account_value(self):

# =========Internal functions==================

def _update_datetime(self, update_dt, cash=None, portfolio_value=None):
def _update_datetime(self, update_dt, cash=None, portfolio_value=None, positions=None, initial_budget=None, orders=None):
"""Works with either timedelta or datetime input
and updates the datetime of the broker"""
and updates the datetime of the broker.

Parameters
----------
update_dt : timedelta, int, float, or datetime
The time to advance by (if timedelta/int/float) or the new datetime
cash : float, optional
Current cash balance
portfolio_value : float, optional
Current portfolio value
positions : list, optional
List of minimal position dicts from Position.to_minimal_dict()
initial_budget : float, optional
Initial budget for calculating return percentage
orders : list, optional
List of minimal order dicts from Order.to_minimal_dict()
"""
tz = self.datetime.tzinfo
is_pytz = isinstance(tz, (pytz.tzinfo.StaticTzInfo, pytz.tzinfo.DstTzInfo))

Expand All @@ -281,7 +297,14 @@ def _update_datetime(self, update_dt, cash=None, portfolio_value=None):
if is_pytz:
new_datetime = tz.normalize(new_datetime)

self.data_source._update_datetime(new_datetime, cash=cash, portfolio_value=portfolio_value)
self.data_source._update_datetime(
new_datetime,
cash=cash,
portfolio_value=portfolio_value,
positions=positions,
initial_budget=initial_budget,
orders=orders
)
if self.option_source:
self.option_source._update_datetime(new_datetime, cash=cash, portfolio_value=portfolio_value)

Expand Down
6 changes: 4 additions & 2 deletions lumibot/backtesting/polygon_backtesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ def _update_pandas_data(self, asset, quote, length, timestep, start_dt=None):
msg = (
"Polygon Access Denied: Your subscription does not allow you to backtest that far back in time. "
f"Requested {asset_separated} {ts_unit} bars from {formatted_start_datetime} to {formatted_end_datetime}. "
"Consider starting later or upgrading your Polygon subscription (https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10, code 'LUMI10')."
"We strongly recommend switching to ThetaData (https://www.thetadata.net/ with promo code 'BotSpot10') for better coverage, speed, and LumiBot-native support. "
"If you must stay on Polygon, consider starting later or upgrading your Polygon plan (https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10, code 'LUMI10')."
)
logger.error(colored(msg, color="red"))
return
Expand All @@ -164,7 +165,8 @@ def _update_pandas_data(self, asset, quote, length, timestep, start_dt=None):
"Please check your API key and try again. "
"You can get an API key at https://polygon.io/?utm_source=affiliate&utm_campaign=lumi10 "
"Please use the full link to give us credit for the sale, it helps support this project. "
"You can use the coupon code 'LUMI10' for 10% off. ",
"You can use the coupon code 'LUMI10' for 10% off. "
"We recommend switching to ThetaData (https://www.thetadata.net/ with promo code 'BotSpot10') for higher-quality, faster data and first-class support in LumiBot. ",
color="red")
raise Exception(error_message) from e
else:
Expand Down
Loading
Loading