Unified market data and account history with pluggable providers
Project description
Unified market data for Indian equities and crypto
One client, multiple providers — historical OHLCV as pandas or structured bars.
Install
pip install bandl
Requires Python 3.10+. For development: pip install -e ".[dev]" (see CONTRIBUTING.md).
Quick start
Import bandl, create a Bandl client, and fetch candles. Binance and CoinDCX public endpoints work without API keys.
from datetime import datetime, timedelta, timezone
from bandl import Bandl, Interval
client = Bandl()
end = datetime.now(timezone.utc)
start = end - timedelta(days=30)
# Crypto — daily BTC/USDT from Binance (default crypto provider)
df = client.crypto.get_ohlcv_dataframe("BTC/USDT", Interval.D1, start, end)
print(df[["timestamp", "open", "high", "low", "close", "volume"]].tail())
Indian equities (Zerodha Kite) need a Kite Connect API key and access token:
from bandl import Bandl, BandlConfig, Interval, ProviderSettings
client = Bandl(
BandlConfig(
providers={
"zerodha": ProviderSettings(
api_key="your_kite_api_key",
access_token="your_daily_access_token",
),
},
),
)
df = client.equity.get_ohlcv_dataframe(
"RELIANCE",
Interval.D1,
start,
end,
source="zerodha",
)
print(df.tail())
Indices use the same API (aliases like NIFTY 50 → NIFTY50 are handled for you):
nifty = client.equity.get_ohlcv_dataframe(
"NIFTY 50",
Interval.D1,
start,
end,
source="zerodha",
)
What you can fetch
| Market | Provider | Auth | Example symbols |
|---|---|---|---|
| Crypto spot | binance |
None (public klines) | BTC/USDT, BTCUSDT, ETHUSDT |
| Crypto spot | coindcx |
None (public candles) | BTCUSDT, ETHUSDT |
| NSE equities & indices | zerodha |
Kite API key + access token | RELIANCE, NIFTY 50, BANKNIFTY |
Switch provider with source="binance" | "coindcx" | "zerodha", or use client.crypto / client.equity (defaults per facet).
Binance HTTP 451 (restricted location)? Binance blocks many regions and cloud IPs (e.g. US, Google Colab). Use CoinDCX instead — same symbols, no API key:
df = client.crypto.get_ohlcv_dataframe("BTCUSDT", Interval.D1, start, end, source="coindcx")Or set
BandlConfig(default_crypto_provider="coindcx").CoinDCX empty
DataFrame? The public candles API can lag (latest daily bars may end months before “today”). If yourstart/endare entirely after the feed, bandl raisesDataNotAvailableErrorwith the available date span. Use a window that overlaps the feed, for example:end = datetime(2025, 7, 20, tzinfo=timezone.utc) start = end - timedelta(days=30) df = client.crypto.get_ohlcv_dataframe("BTCUSDT", Interval.D1, start, end, source="coindcx")
Common patterns
Pandas DataFrame (default for analysis)
df = client.crypto.get_ohlcv_dataframe("ETHUSDT", Interval.D1, start, end)
Typed list of bars (no pandas required in your pipeline)
from bandl import OHLCV
bars: list[OHLCV] = client.crypto.get_ohlcv("BTCUSDT", Interval.H1, start, end)
for bar in bars[-5:]:
print(bar.timestamp, bar.close, bar.source)
Another crypto exchange
df = client.crypto.get_ohlcv_dataframe(
"BTCUSDT",
Interval.D1,
start,
end,
source="coindcx",
)
List tradable symbols
# Crypto (Binance spot, trading status)
symbols = client.list_symbols(source="binance", search="BTC", limit=20)
# NSE equities + indices (Zerodha — requires credentials)
symbols = client.list_symbols(
source="zerodha",
exchange="NSE",
instrument_types=("EQ",),
search="RELI",
limit=10,
)
Intervals
Use Interval enums or provider-native strings where supported:
from bandl import Interval
Interval.M1 # 1m
Interval.H1 # 1h
Interval.D1 # 1d
Timestamps in responses are UTC. Convert for display if you need IST:
df["timestamp"] = df["timestamp"].dt.tz_convert("Asia/Kolkata")
Configuration
| Variable / setting | Purpose |
|---|---|
BandlConfig.providers["zerodha"] |
api_key, access_token for Kite |
BandlConfig.providers["binance"] |
Optional keys for future signed APIs |
BandlConfig.timeout_seconds |
HTTP timeout (default 30s) |
BandlConfig.default_crypto_provider |
Default for client.crypto (binance) |
BandlConfig.default_equity_provider |
Default for client.equity (zerodha) |
Zerodha: access tokens expire daily — regenerate after login. A 403 on historical data usually means an expired token, wrong API key, or missing historical API access on your Kite app.
Runnable demos:
cp examples/.env.example .env # add ZERODHA_* if testing Kite
python examples/main.py
python examples/v2_quickstart.py
Demo
Legacy modules (pre–V2)
Older helpers remain importable for NSE options, Yahoo Finance, legacy Binance wrappers, etc. New projects should use bandl (bandl.v2 is deprecated).
Account history (0.3+)
Fetch your orders, fills, and PnL with the client.account facet. See docs/ACCOUNT_HISTORY.md.
fills = client.account.get_fills(start, end, source="coindcx")
pnl = client.account.get_pnl(start, end, source="zerodha", prefer="auto")
bundle = client.account.export_analysis_bundle(start, end)
NSE, Nasdaq, Yahoo, legacy Binance/Coinbase
NSE (options & historical)
from bandl.nse_data import NseData
nd = NseData()
strikes = nd.get_oc_strike_prices("NIFTY")
oc_data = nd.get_option_data("NIFTY", strikes=strikes)
df = nd.get_data("RELIANCE", series="EQ", periods=30)
part_oi_df = nd.get_part_oi_df(periods=66)
Nasdaq
from bandl.nasdaq import Nasdaq
dfs = Nasdaq().get_data("AAPL", periods=15)
Yahoo Finance
from bandl.yfinance import Yfinance
yf = Yfinance()
us = yf.get_data("AAPL", is_indian=False)
india = yf.get_data("SBIN", start="21-Jan-2020")
Legacy Binance / Coinbase
from bandl.binance import Binance
from bandl.coinbase import Coinbase
Binance().get_data("ETHBTC", start="21-Jan-2020")
Coinbase().get_data("BTC-USD", start="21-Jan-2020", end="21-Jan-2021")
Documentation & development
- docs/BANDL_V2.md — design notes and provider behavior
- docs/PYPI_TRUSTED_PUBLISHING.md — release process for maintainers
- CONTRIBUTING.md — tests, Ruff, pull requests
- SECURITY.md — reporting vulnerabilities
pytest tests/v2/ # unit tests
ruff check lib/bandl/v2 tests/v2
Roadmap
- Live streams / WebSockets
- More brokers and MCX commodity history
- Broader
SymbolInfoand fundamentals
Contributing
Contributions are welcome. Please read CONTRIBUTING.md and CODE_OF_CONDUCT.md before opening a pull request.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bandl-0.3.0.tar.gz.
File metadata
- Download URL: bandl-0.3.0.tar.gz
- Upload date:
- Size: 65.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13db23ba844ecc8556b64892d8e88348138d20bdae463e162fef2139824c5ed0
|
|
| MD5 |
d4a8f06d59cf4309258495f7ec998599
|
|
| BLAKE2b-256 |
b320048c65ff3ece167ecd00b0edbb63484f097fa8a11d4e16558138c029429e
|
Provenance
The following attestation bundles were made for bandl-0.3.0.tar.gz:
Publisher:
publish.yml on stockalgo/bandl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bandl-0.3.0.tar.gz -
Subject digest:
13db23ba844ecc8556b64892d8e88348138d20bdae463e162fef2139824c5ed0 - Sigstore transparency entry: 1652977627
- Sigstore integration time:
-
Permalink:
stockalgo/bandl@7ae3bba2ec03fc6a132c4593e80e911079ca0dc5 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/stockalgo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7ae3bba2ec03fc6a132c4593e80e911079ca0dc5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bandl-0.3.0-py3-none-any.whl.
File metadata
- Download URL: bandl-0.3.0-py3-none-any.whl
- Upload date:
- Size: 89.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d63efef50b1ae5913bcb6d8a1f636259d4bceced4b1bd15aedb8c2c82022d331
|
|
| MD5 |
d2dd91e02098167629c21fd50df0f687
|
|
| BLAKE2b-256 |
a9db9431a73df002cb75299444e629ecfcd25c62c2b0f213d8cddb681f02c040
|
Provenance
The following attestation bundles were made for bandl-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on stockalgo/bandl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bandl-0.3.0-py3-none-any.whl -
Subject digest:
d63efef50b1ae5913bcb6d8a1f636259d4bceced4b1bd15aedb8c2c82022d331 - Sigstore transparency entry: 1652977864
- Sigstore integration time:
-
Permalink:
stockalgo/bandl@7ae3bba2ec03fc6a132c4593e80e911079ca0dc5 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/stockalgo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7ae3bba2ec03fc6a132c4593e80e911079ca0dc5 -
Trigger Event:
push
-
Statement type: