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.1.0.tar.gz (42.7 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.1.0-py3-none-any.whl (40.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: bdfinance-0.1.0.tar.gz
  • Upload date:
  • Size: 42.7 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.1.0.tar.gz
Algorithm Hash digest
SHA256 5a2170f60fd4161395101b62e323559c318550fd7e6453378015fce848ada509
MD5 e50c01d805d082941b4436e072179bf8
BLAKE2b-256 5a8244301f8b4e55359b517e0829dba0dda6832188541818f231aecb13985097

See more details on using hashes here.

File details

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

File metadata

  • Download URL: bdfinance-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 40.9 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2b0c5da05ff0e17e7a4b0f2c1aa8f28585cec2a31580a8f874c7ebc0e4b19aca
MD5 e895b95e75173d55720a560c07966f7d
BLAKE2b-256 7a1af2a04740f8c1a2b95160ac4e9614ac8f88aaaf8add61db440bd45ab84b6e

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