Skip to main content

Unified market data and account history with pluggable providers

Project description

bandl

One Python client for market data — crypto, Indian equities & options.
Same call everywhere. Get a pandas DataFrame or typed bars in three lines.

PyPI Python License


from bandl import Bandl, Interval

df = Bandl().crypto.get_ohlcv_dataframe("BTC/USDT", Interval.D1)   # no API key needed

One client, one API. Switch markets by changing the symbol — not your code.

  • 🟢 Zero-config crypto — Binance & CoinDCX public data, no keys.
  • 🇮🇳 Indian equities & indicesRELIANCE, NIFTY 50, BANKNIFTY via Zerodha.
  • 📈 Options, incl. expired contracts — NSE/BSE F&O + MCX commodities via Dhan.
  • 🐼 pandas or typed modelsget_ohlcv_dataframe(...) or get_ohlcv(...) -> list[OHLCV].
  • ⏱️ Normalized everywhere — UTC timestamps, Decimal prices, one Interval enum.
  • 🤖 Agent-ready — a dedicated AGENTS.md reference for LLM tools.

bandl demo


Install

pip install bandl

Python 3.10+. Dev setup: pip install -e ".[dev]" (CONTRIBUTING.md).


60-second start

No API key required — crypto works out of the box:

from bandl import Bandl, Interval

client = Bandl()

df = client.crypto.get_ohlcv_dataframe("BTC/USDT", Interval.D1)
print(df.tail())
#            timestamp     open     high      low    close       volume
#  2025-01-10 00:00:00  94000.1  95200.0  92800.5  94850.2   12930.4451

Want a window? Pass start / end (UTC). Want raw bars instead of pandas? Call get_ohlcv(...) — same arguments, returns list[OHLCV].

from datetime import datetime, timedelta, timezone

end = datetime.now(timezone.utc)
start = end - timedelta(days=30)
bars = client.crypto.get_ohlcv("ETHUSDT", Interval.H1, start, end)
print(bars[-1].close, bars[-1].source)

One API, every market

Facet Provider Auth Example symbols
client.crypto binance None BTC/USDT, ETHUSDT
client.crypto coindcx None BTCUSDT, ETHUSDT
client.equity zerodha Kite key + token RELIANCE, NIFTY 50, BANKNIFTY
client.derivatives dhan Dhan id + JWT GOLDM26JUN145000CE, NIFTY26JAN24000PE

Every facet exposes the same two callsget_ohlcv(...) and get_ohlcv_dataframe(...). Pick a provider with source="...", or rely on each facet's default.


Recipes

Indian equities & indices (Zerodha)

Add your Kite Connect credentials once; the rest is identical to crypto. Symbol aliases (NIFTY 50NIFTY50) are handled for you.

from bandl import Bandl, BandlConfig, Interval, ProviderSettings

client = Bandl(BandlConfig(providers={
    "zerodha": ProviderSettings(api_key="kite_api_key", access_token="daily_token"),
}))

reliance = client.equity.get_ohlcv_dataframe("RELIANCE", Interval.D1, source="zerodha")
nifty    = client.equity.get_ohlcv_dataframe("NIFTY 50", Interval.D1, source="zerodha")

Options & derivatives (Dhan)

client.derivatives serves option OHLCV across NSE/BSE F&O and MCX commodities — with open_interest on every bar. Give it a symbol string (auto-resolved against Dhan's scrip master) or a structured OptionContract.

from datetime import date, datetime, timezone
from decimal import Decimal
from bandl import Bandl, BandlConfig, Interval, ProviderSettings
from bandl.models.market import OptionContract, OptionType

client = Bandl(BandlConfig(providers={
    "dhan": ProviderSettings(api_key="dhan_client_id", access_token="dhan_jwt"),
}))

# 1) Symbol string — easiest
df = client.derivatives.get_ohlcv_dataframe(
    "GOLDM26JUL145000CE", Interval.M5, source="dhan", exchange="MCX",
)

# 2) Structured contract — explicit & unambiguous
contract = OptionContract(
    underlying="GOLDM", expiry=date(2026, 7, 29),
    strike=Decimal("145000"), option_type=OptionType.CALL, exchange="MCX",
)
bars = client.derivatives.get_ohlcv(contract, Interval.M1, source="dhan")

# What expiries exist for an underlying?
expiries = client.derivatives.list_expiries("GOLDM", source="dhan", exchange="MCX")

Need expired contracts? Most APIs drop them. bandl still fetches their minute candles — pass the native instrument_id once (look it up via Dhan, or the bundled examples/dhan_expired_probe.py):

bars = client.derivatives.get_ohlcv(
    "GOLDM26JUN143500CE", Interval.M1,
    datetime(2026, 6, 26, tzinfo=timezone.utc),
    datetime(2026, 6, 27, tzinfo=timezone.utc),
    source="dhan", exchange="MCX", instrument_id="570800",
)

Typed bars instead of pandas

from bandl import OHLCV

bars: list[OHLCV] = client.crypto.get_ohlcv("BTCUSDT", Interval.H1)
bars[-1].close      # Decimal — no float rounding
bars[-1].timestamp  # tz-aware UTC datetime

List tradable symbols

client.list_symbols(source="binance", search="BTC", limit=20)
client.list_symbols(source="zerodha", exchange="NSE",
                    instrument_types=("EQ",), search="RELI", limit=10)

Intervals & timezones

One enum maps to every provider's native interval. Timestamps come back UTC.

from bandl import Interval
Interval.M1, Interval.M5, Interval.H1, Interval.D1   # 1m / 5m / 1h / 1d

df["timestamp"] = df["timestamp"].dt.tz_convert("Asia/Kolkata")  # → IST for display

Configuration

from bandl import BandlConfig, ProviderSettings

config = BandlConfig(
    providers={
        "zerodha": ProviderSettings(api_key="...", access_token="..."),
        "dhan":    ProviderSettings(api_key="client_id", access_token="jwt"),
    },
    timeout_seconds=30,
    default_crypto_provider="binance",       # client.crypto default
    default_equity_provider="zerodha",       # client.equity default
    default_derivatives_provider="dhan",     # client.derivatives default
)
Provider api_key access_token Notes
zerodha Kite API key daily token Tokens expire daily — regenerate after login. 403 ⇒ expired/wrong token or no historical-API access.
dhan client id JWT JWT generated in the Dhan web/app. Expired contracts leave the scrip master — fetch by instrument_id.
binance / coindcx Public OHLCV needs no keys.

Binance HTTP 451? Binance blocks some regions/cloud IPs (US, Colab). Use source="coindcx" — same symbols, no key — or set default_crypto_provider="coindcx".

CoinDCX empty DataFrame? Its public feed can lag by months. A start/end entirely after the feed raises DataNotAvailableError with the available span; pick an overlapping window.


More

Account history — orders, fills & PnL via client.account
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)

Full guide: docs/ACCOUNT_HISTORY.md.

Futures 24h leaders — rolling ticker stats
from bandl import AssetType

tickers = client.crypto.get_24hr_tickers(source="coindcx", asset_type=AssetType.CRYPTO_PERP)
Runnable demos
cp examples/.env.example .env      # add ZERODHA_* / DHAN_* to test authed providers
python examples/main.py
python examples/dhan_options.py
python examples/futures_24hr_leaders.py --source coindcx

For AI agents

AGENTS.md is a purpose-built reference (provider matrix, recipes, errors) for LLM coding tools. It is not shipped in the PyPI wheel — point your agent at the GitHub link:

https://github.com/stockalgo/bandl/blob/master/AGENTS.md

Pin a tag (e.g. .../blob/v0.4.0/AGENTS.md) for a fixed version. See agents/README.md.


Docs & development

pytest tests/bandl/
ruff check lib/bandl tests/bandl

Roadmap

  • Live streams / WebSockets
  • More brokers & deeper commodity history
  • Richer SymbolInfo and fundamentals

Contributing

PRs welcome — read CONTRIBUTING.md and CODE_OF_CONDUCT.md first.

License

MIT

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

bandl-0.5.0.tar.gz (49.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bandl-0.5.0-py3-none-any.whl (64.1 kB view details)

Uploaded Python 3

File details

Details for the file bandl-0.5.0.tar.gz.

File metadata

  • Download URL: bandl-0.5.0.tar.gz
  • Upload date:
  • Size: 49.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for bandl-0.5.0.tar.gz
Algorithm Hash digest
SHA256 ff691bfef0fbe4f4decc5b71130df2adad690f7105ebf6988b4c111356d51f51
MD5 c3719a84b7696d9a0f424dfc3aedbafa
BLAKE2b-256 25404acc18b0ddcbdee534a0dcf7aab0b970efaeed242523bef08906f74ae9f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for bandl-0.5.0.tar.gz:

Publisher: publish.yml on stockalgo/bandl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bandl-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: bandl-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 64.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for bandl-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 82ab5957595eac76adf8a0292210d22fe8c1dba2ef22b864f179e05aa02cc648
MD5 7778c598c3441485fe33ce9e8b58ddd4
BLAKE2b-256 f8f3740d515532ec5f2e4fbd0a2366f86f8fe21956942ecd3ec5372293f6f4a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bandl-0.5.0-py3-none-any.whl:

Publisher: publish.yml on stockalgo/bandl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page