Skip to main content

High-performance async Bangladesh stock market data library with batch processing

Project description

bdfinance

High-performance async Python library for fetching Bangladesh stock market data from the Dhaka Stock Exchange (DSE).

Inspired by yfinance, bdfinance provides a familiar Ticker-based API backed by async HTTP, automatic caching, structured logging, and Pydantic-validated models.


Features

  • Async-first — built on httpx with HTTP/2 and connection pooling
  • Ticker API — unified interface per symbol: quote, history, info, depth, news, fundamentals
  • Batch processing — fetch data for multiple symbols concurrently
  • Caching — pluggable memory or Redis cache with configurable TTL
  • Pydantic models — strongly typed, auto-validated data models
  • Retry & rate limiting — exponential backoff with configurable rate limits
  • Structured logging — powered by structlog
  • Treasury bonds — coupon rates, approximate YTM calculations

Installation

Requires Python 3.12+.

pip install bdfinance

Or install from source:

git clone https://github.com/your-username/bdfinance.git
cd bdfinance
pip install .

Dependencies

Package Purpose
httpx[http2] Async HTTP client with HTTP/2
beautifulsoup4 + lxml HTML parsing
pandas DataFrames for historical/tabular data
pydantic + pydantic-settings Data models and configuration
tenacity Retry logic
structlog Structured logging
aiocache + msgpack Caching layer

Quick Start

import asyncio
from bdfinance import BDStockClient

async def main():
    async with BDStockClient() as client:
        ticker = client.ticker("GP")

        # Current quote
        quote = await ticker.quote()
        print(f"{quote.symbol}: LTP {quote.ltp}, Change {quote.change}")

        # Historical data (returns pandas DataFrame)
        df = await ticker.history(period="1y")
        print(df.head())

        # Company information
        info = await ticker.info()
        print(info.basic_information.company_name)

        # Market depth
        depth = await ticker.depth()
        print(f"Buy: {depth.buy_price} | Sell: {depth.sell_price}")

        # Fundamentals (quote + info + PE combined)
        fundamentals = await ticker.fundamentals()

asyncio.run(main())

Multiple Tickers

async with BDStockClient() as client:
    tickers = client.tickers(["GP", "BEXIMCO", "ACI"])

    for symbol, ticker in tickers.items():
        quote = await ticker.quote()
        print(f"{symbol}: {quote.ltp}")

Configuration

Both ClientConfig and CacheConfig use pydantic-settings and can be configured via constructor arguments or environment variables (prefixed with BDFINANCE_ / BDFINANCE_CACHE_).

from bdfinance import BDStockClient, ClientConfig, CacheConfig

config = ClientConfig(
    timeout=60.0,
    max_retries=5,
    rate_limit=20,
    enable_cache=True,
)

cache_config = CacheConfig(
    backend="memory",   # or "redis"
    ttl=600,            # seconds
)

async with BDStockClient(config=config, cache_config=cache_config) as client:
    ...
Env Variable Default Description
BDFINANCE_TIMEOUT 30.0 Request timeout (seconds)
BDFINANCE_MAX_RETRIES 3 Max retry attempts
BDFINANCE_RATE_LIMIT 10 Max requests per second
BDFINANCE_ENABLE_CACHE true Enable response caching
BDFINANCE_CACHE_BACKEND memory memory or redis
BDFINANCE_CACHE_TTL 300 Cache TTL (seconds)
BDFINANCE_CACHE_REDIS_URL redis://localhost:6379/0 Redis URL

See docs/configuration.md for the full reference.


Documentation

Document Description
Client & Ticker BDStockClient and Ticker API reference
Configuration ClientConfig and CacheConfig details
Models Pydantic data models (trading, market, news, company)
Repositories Low-level TradingRepository, MarketRepository, NewsRepository
Caching Cache backends, key generation, TTL management
Utilities Data cleaners, date helpers, HTML parsers

Usage Examples

Historical Data

# By date range
df = await ticker.history(start="2024-01-01", end="2024-12-31")

# By period shorthand
df = await ticker.history(period="6mo")   # 6 months
df = await ticker.history(period="1y")    # 1 year
df = await ticker.history(period="30d")   # 30 days

Market Data (via repositories)

async with BDStockClient() as client:
    # Market overview
    overview = await client.market.get_market_overview(period="7d")

    # Latest P/E ratios
    pe = await client.market.get_latest_pe()

    # Top stocks / gainers / losers
    top = await client.market.get_top_stocks()
    gainers = await client.market.get_top_10_gainers()
    losers = await client.market.get_top_10_losers()

    # Sector listing
    sectors = await client.market.get_sector_listed()

    # Treasury bond yields
    bonds = await client.market.get_tbond_yields(tenor="10Y")

News

async with BDStockClient() as client:
    ticker = client.ticker("GP")

    # Company-specific news
    news = await ticker.news()

    # AGM news for this company
    agm = await ticker.agm_news()

    # All DSE news (via repository)
    all_news = await client.news.get_all_news()

Cache Management

async with BDStockClient() as client:
    # Clear all cached data
    await client.clear_cache()

Project Structure

bdfinance/
├── __init__.py          # Public API exports
├── client.py            # BDStockClient entry point
├── ticker.py            # Unified Ticker interface
├── config.py            # ClientConfig / CacheConfig
├── constants.py         # DSE URLs and endpoints
├── http_client.py       # Async HTTP client
├── cache.py             # Cache backends (memory / redis)
├── parsers.py           # HTML parsing utilities
├── models/
│   ├── trading.py       # CurrentTradeData, BasicHistoricalData, ...
│   ├── market.py        # MarketInfo, MarketDepth, CompanyInfo, TBondInfo
│   ├── news.py          # AGMNews, News
│   └── company.py       # DSECompanyData and sub-models
├── repositories/
│   ├── base.py          # BaseRepository with get_data / get_dataframe
│   ├── trading.py       # TradingRepository
│   ├── market.py        # MarketRepository
│   └── news.py          # NewsRepository
└── utils/
    ├── common.py         # Dict helpers
    ├── data_cleaners.py  # clean_float, clean_int, clean_symbol, ...
    ├── date_helper.py    # Period parsing, date conversion
    └── parse_com_info.py # DSE company page parser

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

bdfinance-0.5.0.tar.gz (44.2 kB view details)

Uploaded Source

Built Distribution

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

bdfinance-0.5.0-py3-none-any.whl (42.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: bdfinance-0.5.0.tar.gz
  • Upload date:
  • Size: 44.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bdfinance-0.5.0.tar.gz
Algorithm Hash digest
SHA256 289b81fba8c3515bfd34dc1ec52dce2f5a2bf7f5d345b5b46f77caf6b31745f7
MD5 3d49c3b2bee0bd727bc6a5423af8270a
BLAKE2b-256 afd5b55dcd9f055a878100f4777b4a34e836d7530ee57cf8635740421d4864aa

See more details on using hashes here.

File details

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

File metadata

  • Download URL: bdfinance-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 42.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bdfinance-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 42181adce31174487c206f80c79ecaa3f526bb1b716278174c2d6fb6b64d0ff6
MD5 3e11c4d0630d56c5f571f84f15909f80
BLAKE2b-256 88877e7853505ed2058c4d3dc6d26a15420b85233cb91ac659dc481a9c633e26

See more details on using hashes here.

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