Self-hostable FastAPI service for Egyptian Exchange (EGX) market data. borsa ships a broad EGX symbol catalog and a consistent REST API over user-configured data providers.
Egyptian Exchange data is fragmented. Different providers cover different symbols, return them
in incompatible formats (COMI, COMI.CA, CIB.EGX), and there is no clean Python-friendly
interface that fails over when a source is unavailable. borsa unifies the symbol catalog and
normalizes responses across multiple providers behind one REST API you can run yourself.
Legal note: borsa is software, not a market-data license. Provider terms, rate limits, permitted use, and redistribution rules remain the operator's responsibility. Yahoo Finance/yfinance support is disabled by default in
.env.examplebecause it uses unofficial Yahoo access.
cp .env.example .env
$EDITOR .env # add your Alpha Vantage and/or Finnhub key
docker compose up --build
# In another terminal:
curl http://localhost:8000/v1/quote/COMIThe API runs at http://localhost:8000. Interactive docs are at http://localhost:8000/docs.
Published Docker images are available at ghcr.io/7ashraf/borsa:latest.
Example response
$ curl http://localhost:8000/v1/quote/COMI{
"symbol": "COMI",
"company": "Commercial International Bank Egypt (CIB) S.A.E.",
"price": 136.0,
"change": null,
"change_percent": null,
"volume": 3579806,
"high": 136.49,
"low": 132.5,
"currency": "EGP",
"source": "Yahoo Finance (COMI.CA)",
"api_symbol": "COMI.CA",
"fetch_duration": 1.212,
"timestamp": "2026-05-25T23:16:07.747635",
"attribution": {
"provider": "Yahoo Finance",
"url": "https://finance.yahoo.com"
}
}| Method | Path | Description |
|---|---|---|
GET |
/v1/health |
Service health and configured providers |
GET |
/v1/stocks |
EGX symbol catalog |
GET |
/v1/quote/{symbol} |
One live quote |
GET |
/v1/quotes |
All currently retrievable quotes |
GET |
/v1/quotes/batch?symbols=COMI,ETEL |
Batch quote lookup |
GET |
/v1/quote/by-company/{name} |
Quote lookup by company-name fragment |
GET |
/v1/status |
Provider, cache, and request counters |
GET |
/demo/quote/{symbol} |
Optional demo endpoint with global daily limit |
Yahoo doesn't cover all EGX symbols, symbol formats vary by provider, and there's no fallback
when one source fails or rate-limits you. borsa unifies the symbol catalog, normalizes
responses, and falls back across providers automatically — so a request for COMI resolves
the same way whether the underlying answer comes from Alpha Vantage, Finnhub, or Yahoo.
- Alpha Vantage and Finnhub require the operator's own API keys (both have free tiers).
- Yahoo Finance via
yfinanceis an optional, unofficial provider. Enable it only if your use complies with Yahoo and yfinance terms. - Startup quote warmup and scheduled refresh are configurable via
.env. - Responses include provider attribution in the response body and the
X-Data-Sourceheader.
| Variable | Default | Description |
|---|---|---|
ALPHA_VANTAGE_KEY |
empty | Alpha Vantage key — provider skipped if empty |
FINNHUB_KEY |
empty | Finnhub key — provider skipped if empty |
ENABLE_YAHOO_FINANCE |
false |
Enable unofficial Yahoo Finance/yfinance fetching |
CACHE_TTL_SECONDS |
300 |
Quote cache TTL and auto-refresh interval |
FETCH_QUOTES_ON_STARTUP |
true |
Fetch all quotes when the app starts |
AUTO_REFRESH_QUOTES |
true |
Force-refresh all quotes every cache TTL |
CACHE_MAX_SIZE |
512 |
Maximum cache entries |
LOG_LEVEL |
info |
debug, info, warning, error |
Contributions are welcome — see CONTRIBUTING.md. Good first issues:
- Adding new EGX symbols to the catalog
- Additional provider adapters (Mubasher, Investing.com scraping with their ToS in mind, etc.)
- Expanding test coverage
- Documentation improvements and translations
MIT — see LICENSE. borsa is provided as-is, with no warranty, and is not financial, investment, legal, or tax advice. Data accuracy and availability depend on third-party providers. See DISCLAIMER.md.
