Backtrader integration for OpenAlgo (India) - stores, feeds, and brokers.
uv pip install openalgo-backtraderImport the package in your code as follows:
from openalgo_bt.stores.oa import OAStore
from openalgo_bt.feeds.oa import OADataopenalgo_bt/- Main packagestores/oa.py- OAStore for OpenAlgo APIfeeds/oa.py- OAData for Backtrader feedsbrokers/oabroker.py- OABroker for Backtrader brokers
Here is how to setup a Store/Broker (example tested with Zerodha backend at OpenAlgo). Both blocks are for "LIVE" setup
from openalgo_bt.stores.oa import OAStore
store = OAStore()
broker = store.getbroker(
product="MIS",
strategy="Live Consistent Trend Bracket",
debug=True,
simulate_fills=False, # Use real broker for live trading
use_funds=False # Use local cash management
)
cerebro.setbroker(broker)And to setup a Data (or multiple for that matter)
data = OAData(
symbol=symbol,
interval="1m", # Explicit OpenAlgo interval to bypass timeframe/compression mapping
compression=1, # 1-minute bars
fromdate=datetime.now() - timedelta(days=1), # Some historical data for warmup
live=True, # Enable live streaming
ws_url=ws_url,
ws_mode=2, # Quote mode
)
cerebro.adddata(data, name=symbol)When your backend only provides 1-minute data, OAData can now deliver higher intraday compressions by resampling locally:
- Historical:
- If you request Minutes/Hours with compression>1 and the OpenAlgo backend does not support that interval, OAData fetches 1m candles and aggregates them into N-minute buckets.
- Live:
- Websocket ticks are aggregated into the requested bucket size on the fly.
Notes:
- Bucket alignment is done in Asia/Kolkata time by flooring to the nearest multiple of the bucket size.
- Volume comes from per-tick last_quantity when available, or from deltas of cumulative session volume otherwise.
- If OpenAlgo supports the requested interval natively (e.g. 5m), OAData will use it. If not, it will fallback to 1m + local aggregation transparently.
Examples:
# Historical 5-minute bars (local 1m->5m if backend interval unsupported)
import backtrader as bt
from datetime import datetime, timedelta
from openalgo_bt.feeds.oa import OAData
TF_MINUTES = getattr(getattr(bt, "TimeFrame", object), "Minutes", 1)
data = OAData(
symbol="NSE:RELIANCE",
timeframe=TF_MINUTES,
compression=5,
fromdate=datetime.now() - timedelta(days=5),
todate=datetime.now(),
)# Live 15-minute bars (aggregated locally from 1m ticks)
import os
import backtrader as bt
from datetime import datetime
from openalgo_bt.feeds.oa import OAData
TF_MINUTES = getattr(getattr(bt, "TimeFrame", object), "Minutes", 1)
data = OAData(
symbol="NSE:RELIANCE",
timeframe=TF_MINUTES,
compression=15,
fromdate=datetime(2025, 8, 8), # optional historical warmup
live=True,
ws_url=os.getenv("WEBSOCKET_URL"),
ws_mode=2, # Quote mode
)Tip: Some editors’ type stubs don’t expose bt.TimeFrame.Minutes; use: TF_MINUTES = getattr(getattr(bt, "TimeFrame", object), "Minutes", 1)
- Python 3.8+
- python-dotenv
- backtrader (user must install)
- openalgo (user must install)
See LICENSE.