Skip to main content

Currency exchange rates and converter using live data from Banque Centrale du Congo (BCC)

Project description

🏦 BCC Rates

Python 3.12+ License: MIT

BCC Rates is a Python library and command-line tool for fetching real-time currency exchange rates from multiple sources including the Banque Centrale du Congo (BCC) and Open Exchange Rates (OXR). It provides both synchronous and asynchronous APIs for seamless integration into your applications.

🌟 Features

  • 📊 Multiple data sources: BCC official website and Open Exchange Rates API
  • 🔄 Synchronous and asynchronous API support
  • 💱 Currency conversion with precise calculations
  • 🔀 Backend comparison - Compare rates from different sources
  • 🖥️ Command-line interface for quick conversions
  • 🎯 Interactive mode for multiple conversions
  • Async mode for better performance
  • 🔧 Type hints for better development experience

🚀 Installation

From PyPI (recommended)

pip install bcc-rates

From GitHub

pip install git+https://github.com/oxiliere/bcc_rates.git

From source (development)

git clone https://github.com/oxiliere/bcc_rates.git
cd bcc_rates
pip install -e .

Using uv (recommended for development)

git clone https://github.com/oxiliere/bcc_rates.git
cd bcc_rates
uv sync

📖 Quick Start

Command Line Usage

After installation, use the bcc_exchange command:

# Show all available exchange rates (BCC by default)
bcc_exchange --list

# Convert currencies
bcc_exchange 100 USD EUR

# Use OXR backend
bcc_exchange --backend oxr 100 USD EUR

# Compare rates from both sources
bcc_exchange --compare

# Interactive mode
bcc_exchange --interactive

# Async mode for better performance
bcc_exchange --async-mode 100 USD EUR

# Quiet mode (result only)
bcc_exchange --quiet 1000 EUR CDF

Python API

Synchronous Usage

from bcc_rates import BCCBankSource, OXRBankSource
from dinero import Dinero, currencies

# Initialize the BCC source
bcc = BCCBankSource()

# Get all exchange rates
rates = bcc.sync()
print(f"Found {len(rates)} exchange rates")

# Get specific currency rate
usd_rate = bcc.get_value("USD")
print(f"1 USD = {usd_rate.amount} CDF")

# Currency conversion
amount = Dinero(100, currencies.USD)
converted = bcc.to(amount, "EUR")
print(f"100 USD = {converted.amount} EUR")

# Using OXR backend
import os
os.environ['OXR_API_KEY'] = 'your_api_key_here'

oxr = OXRBankSource()
rates = oxr.sync()
oxr.set_cdf_as_base()  # Convert to CDF base
usd_rate = oxr.get_value("USD")
print(f"1 USD = {usd_rate.amount} CDF (from OXR)")

Asynchronous Usage

import asyncio
from bcc_rates import AsyncBCCBankSource, AsyncOXRBankSource
from dinero import Dinero, currencies

async def main():
    # Initialize async BCC source
    bcc = AsyncBCCBankSource()
    
    # Get all exchange rates
    rates = await bcc.sync()
    print(f"Found {len(rates)} exchange rates")
    
    # Get specific currency rate
    eur_rate = await bcc.get_value("EUR")
    print(f"1 EUR = {eur_rate.amount} CDF")
    
    # Currency conversion
    amount = Dinero(50, currencies.GBP)
    converted = await bcc.to(amount, "USD")
    print(f"50 GBP = {converted.amount} USD")
    
    # Parallel fetching from multiple sources
    oxr = AsyncOXRBankSource()
    bcc_rates, oxr_rates = await asyncio.gather(
        bcc.sync(),
        oxr.sync()
    )
    print(f"BCC: {len(bcc_rates)} rates, OXR: {len(oxr_rates)} rates")

# Run async function
asyncio.run(main())

🛠️ Command Line Interface

The bcc_exchange command provides a powerful CLI for currency operations:

Basic Commands

# Show help
bcc_exchange --help

# List all available currencies and rates
bcc_exchange --list

# Convert 100 USD to EUR
bcc_exchange 100 USD EUR

# Convert 1000 EUR to CDF (Congolese Franc)
bcc_exchange 1000 EUR CDF

# Use async mode for better performance
bcc_exchange --async-mode 50 GBP USD

Backend Selection

# Use BCC backend (default)
bcc_exchange --backend bcc --list
bcc_exchange -b bcc 100 USD EUR

# Use OXR backend (requires API key)
export OXR_API_KEY="your_api_key_here"
bcc_exchange --backend oxr --list
bcc_exchange -b oxr 100 USD CDF

# Compare rates from both sources
bcc_exchange --compare
bcc_exchange -c

# Compare with async mode (faster)
bcc_exchange --compare --async-mode
bcc_exchange -c -a

Interactive Mode

# Interactive mode with BCC
bcc_exchange --interactive

# Interactive mode with OXR
bcc_exchange --backend oxr --interactive

This starts an interactive session where you can perform multiple conversions:

🔄 Interactive Currency Converter (BCC)
Enter 'quit' to exit
------------------------------
Available currencies: AOA, AUD, BIF, CAD, CDF, CHF, CNY, EUR, GBP, JPY, RWF, TZS, UGX, USD, XAF, XDR, ZAR, ZMW

Enter amount (or 'quit'): 100
From currency: USD
To currency: EUR
✅ 100.00 USD = 86.15 EUR

Enter amount (or 'quit'): quit

Quiet Mode

For scripting and automation:

# Returns only the conversion result
bcc_exchange --quiet 100 USD EUR
# Output: 86.1487

📚 API Reference

Classes

BCCBankSource (Synchronous)

class BCCBankSource:
    def __init__(self, url: str = "https://www.bcc.cd/"):
        """Initialize BCC source with optional custom URL."""
    
    def sync(self, cache: bool = True) -> List[SourceValue]:
        """Fetch all exchange rates from BCC."""
    
    def get_value(self, currency: str) -> SourceValue:
        """Get exchange rate for specific currency."""
    
    def get_values(self, currencies: List[str] = None) -> List[SourceValue]:
        """Get exchange rates for multiple currencies."""
    
    def to(self, base: Dinero, target: str | Currency) -> Dinero:
        """Convert currency amount to target currency."""

OXRBankSource (Synchronous)

class OXRBankSource:
    def __init__(self, api_key: str = None):
        """Initialize OXR source with API key (or from OXR_API_KEY env var)."""
    
    def sync(self, cache: bool = True) -> List[SourceValue]:
        """Fetch all exchange rates from OXR API."""
    
    def set_cdf_as_base(self):
        """Convert rates to use CDF as base currency (same format as BCC)."""
    
    def get_value(self, currency: str) -> SourceValue:
        """Get exchange rate for specific currency."""
    
    def get_values(self, currencies: List[str] = None) -> List[SourceValue]:
        """Get exchange rates for multiple currencies."""
    
    def to(self, base: Dinero, target: str | Currency) -> Dinero:
        """Convert currency amount to target currency."""

AsyncBCCBankSource (Asynchronous)

class AsyncBCCBankSource:
    def __init__(self, url: str = "https://www.bcc.cd/"):
        """Initialize async BCC source with optional custom URL."""
    
    async def sync(self, cache: bool = True) -> List[SourceValue]:
        """Fetch all exchange rates from BCC."""
    
    async def get_value(self, currency: str) -> SourceValue:
        """Get exchange rate for specific currency."""
    
    async def get_values(self, currencies: List[str] = None) -> List[SourceValue]:
        """Get exchange rates for multiple currencies."""
    
    async def to(self, base: Dinero, target: str | Currency) -> Dinero:
        """Convert currency amount to target currency."""

AsyncOXRBankSource (Asynchronous)

class AsyncOXRBankSource:
    def __init__(self, api_key: str = None):
        """Initialize async OXR source with API key (or from OXR_API_KEY env var)."""
    
    async def sync(self, cache: bool = True) -> List[SourceValue]:
        """Fetch all exchange rates from OXR API."""
    
    def set_cdf_as_base(self):
        """Convert rates to use CDF as base currency (same format as BCC)."""
    
    async def get_value(self, currency: str) -> SourceValue:
        """Get exchange rate for specific currency."""
    
    async def get_values(self, currencies: List[str] = None) -> List[SourceValue]:
        """Get exchange rates for multiple currencies."""
    
    async def to(self, base: Dinero, target: str | Currency) -> Dinero:
        """Convert currency amount to target currency."""

SourceValue

@dataclass
class SourceValue:
    currency: str  # Currency code (e.g., "USD", "EUR")
    amount: Decimal  # Exchange rate in CDF

Supported Currencies

BCC Backend

Supports all currencies available on the BCC website (~17 currencies):

  • USD - US Dollar
  • EUR - Euro
  • GBP - British Pound
  • CAD - Canadian Dollar
  • CHF - Swiss Franc
  • JPY - Japanese Yen
  • CNY - Chinese Yuan
  • AUD - Australian Dollar
  • ZAR - South African Rand
  • CDF - Congolese Franc (base currency)
  • And more...

OXR Backend

Supports 170+ currencies from Open Exchange Rates API, including all major world currencies.

Note: OXR requires an API key. Get one free at openexchangerates.org

🧪 Development

Setting up Development Environment

# Clone the repository
git clone https://github.com/oxiliere/bcc_rates.git
cd bcc_rates

# Install with uv (recommended)
uv sync

# Or with pip
pip install -e ".[dev]"

Running Tests

# Run all tests
uv run python -m pytest

# Run with coverage
uv run python -m pytest --cov=bcc_rates

# Run specific test file
uv run python src/tests.py

Running CLI in Development

# Using uv (recommended)
uv run python -m bcc_rates --help
uv run python -m bcc_rates 100 USD EUR

# Direct execution
uv run python src/bcc_rates/cli.py --help

Code Quality

# Format code
uv run black src/

# Type checking
uv run mypy src/

# Linting
uv run flake8 src/

📋 Examples

Basic Currency Conversion

from bcc_rates import BCCBankSource
from dinero import currencies, Dinero

bcc = BCCBankSource()

# Convert 100 USD to EUR
usd_amount = Dinero(100, currencies.USD)
eur_amount = bcc.to(usd_amount, "EUR")
print(f"100 USD = {eur_amount.amount:.2f} EUR")

# Convert 1000 EUR to CDF
eur_amount = Dinero(1000, currencies.EUR)
cdf_amount = bcc.to(eur_amount, "CDF")
print(f"1000 EUR = {cdf_amount.amount:,.2f} CDF")

Batch Processing

from bcc_rates import BCCBankSource

bcc = BCCBankSource()

# Get rates for specific currencies
currencies_of_interest = ["USD", "EUR", "GBP", "CAD"]
rates = bcc.get_values(currencies_of_interest)

for rate in rates:
    print(f"1 {rate.currency} = {rate.amount:,.4f} CDF")

Async Batch Processing

import asyncio
from bcc_rates import AsyncBCCBankSource

async def get_multiple_rates():
    bcc = AsyncBCCBankSource()
    
    # Fetch all rates
    rates = await bcc.sync()
    
    # Process rates
    major_currencies = ["USD", "EUR", "GBP", "JPY"]
    for currency in major_currencies:
        try:
            rate = await bcc.get_value(currency)
            print(f"1 {currency} = {rate.amount:,.4f} CDF")
        except ValueError:
            print(f"{currency} not available")

asyncio.run(get_multiple_rates())

Comparing Multiple Sources

import asyncio
from bcc_rates import AsyncBCCBankSource, AsyncOXRBankSource

async def compare_sources():
    bcc = AsyncBCCBankSource()
    oxr = AsyncOXRBankSource()
    
    # Fetch from both sources in parallel
    bcc_rates, oxr_rates = await asyncio.gather(
        bcc.sync(),
        oxr.sync()
    )
    
    # Convert OXR to CDF base
    oxr.set_cdf_as_base()
    
    # Compare USD rates
    bcc_usd = await bcc.get_value("USD")
    oxr_usd = await oxr.get_value("USD")
    
    print(f"BCC: 1 USD = {bcc_usd.amount:,.4f} CDF")
    print(f"OXR: 1 USD = {oxr_usd.amount:,.4f} CDF")
    print(f"Difference: {abs(bcc_usd.amount - oxr_usd.amount):,.4f} CDF")

asyncio.run(compare_sources())

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Guidelines

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for your changes
  4. Ensure all tests pass
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Banque Centrale du Congo (BCC) for providing the exchange rate data
  • Open Exchange Rates for their comprehensive currency API
  • Dinero library for currency handling
  • BeautifulSoup for HTML parsing
  • aiohttp for async HTTP requests
  • requests for synchronous HTTP requests

📞 Support

If you encounter any issues or have questions:

  1. Check the Issues page
  2. Create a new issue if your problem isn't already reported
  3. Provide detailed information about your environment and the issue

🔗 Links


Made with ❤️ for the Congolese developer community

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

bcc_rates-1.1.0.tar.gz (10.9 kB view details)

Uploaded Source

Built Distribution

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

bcc_rates-1.1.0-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file bcc_rates-1.1.0.tar.gz.

File metadata

  • Download URL: bcc_rates-1.1.0.tar.gz
  • Upload date:
  • Size: 10.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for bcc_rates-1.1.0.tar.gz
Algorithm Hash digest
SHA256 89303a4641b257eeaa664c1ccb9add8f79a7cd83e60ec6f1b964fb7cf6080f3d
MD5 712c63f960a5800b3b56ae90ae5c0da8
BLAKE2b-256 252a3d4d6d83d49b1146288a620be141c290a490304a344c058ac4dc64d6f57d

See more details on using hashes here.

File details

Details for the file bcc_rates-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: bcc_rates-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for bcc_rates-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 121c0c9d23007780ba4ccb9db98b694faf1260b456d4e7a521dbbc97a3483880
MD5 cf0f1fa8e19300a2e8c1e36f1675accd
BLAKE2b-256 0445e68f14c2443883ba84b7ba9b19df194ba1e77df0f6687d9152f3b9d773ec

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