Data Providers
What Are Data Providers?
To show you stock prices and charts, the application needs to download historical price data from the internet. Different websites and services offer this data - these are called “data providers”.
Good news: The application uses Yahoo Finance, which is free and works great for most people. You don’t need to configure anything!
Yahoo Finance (Default)
Free - No API key required - Global coverage
Yahoo Finance is the default provider and works out of the box with no configuration.
Pros:
Free to use
No API key required
Good coverage for US and European stocks
Historical data going back many years
Cons:
End-of-day data only
Occasional reliability issues
No official API support
Has undocumented rate limits (the app handles this automatically)
Configuration:
# .env (optional — yahoo is the default)
PRICE_DATA_PROVIDER=yahoo
Ticker Resolution
DEGIRO transaction exports identify stocks by ISIN, but Yahoo Finance needs a ticker symbol (SAP.DE, SAVE.ST, KD, …). The application resolves the ISIN → ticker mapping automatically the first time it sees a stock, and caches the result in the yahoo_ticker column of the stocks table.
How resolution works
When a new stock is imported, resolve_ticker_from_isin() tries strategies in order:
Manual override. A small allowlist (
MANUAL_TICKER_MAPPINGinsrc/degiro_portfolio/ticker_resolver.py) for stocks where a specific listing must be pinned.Yahoo Finance Search (
yf.Search(isin)). The primary resolver. Yahoo indexes most listed equities and ETFs globally by ISIN; the search returns candidate listings across exchanges.Legacy prefix heuristic. Last-resort defensive path for US/NL/DE/FR/IT/ES ISINs, kept for offline or network-flaky environments.
Picking the right listing
The same ISIN can be listed on several Yahoo venues (Stockholm and Stuttgart, Athens and Amsterdam, etc.). To pick the right one, the resolver compares each candidate’s suffix against:
The stock’s trading currency. SEK →
.ST, NOK →.OL, CHF →.SW, GBP →.L, JPY →.T, PLN →.WA, HKD →.HK, AUD →.AX, CAD →.TO, BRL →.SA, INR →.NS, … (~30 currencies; USD is intentionally unmapped — US tickers have no suffix).If the currency hint doesn’t disambiguate (e.g. EUR is shared across Athens, Amsterdam, Paris, Milan, Madrid, …), the ISIN country prefix:
DE→.DE,FR→.PA,NL→.AS,GR→.AT,IE→.IR,AT→.VI,IT→.MI,ES→.MC,FI→.HE,BE→.BR,PT→.LS, …If neither matches, the first equity/ETF/mutual-fund result wins.
This covers 40+ ISIN country codes across Europe, Asia/Pacific, the Americas, the Middle East, and Africa. The complete maps live in CURRENCY_TO_SUFFIX and COUNTRY_TO_SUFFIX in ticker_resolver.py.
Examples
ISIN |
Currency |
Resolved ticker |
How |
|---|---|---|---|
SE0015192067 |
SEK |
|
Yahoo Search, |
GRS469003024 |
EUR |
|
Yahoo Search, |
CH0024608827 |
CHF |
|
Yahoo Search, |
GB00B1YW4409 |
GBP |
|
Yahoo Search, |
JP3389510003 |
JPY |
|
Yahoo Search, |
US50155Q1004 |
USD |
|
Yahoo Search (Kyndryl) |
DE0007164600 |
EUR |
|
Manual override |
Forcing a re-resolve
If you upgraded from a version that couldn’t resolve tickers for some markets, clear the cached tickers and trigger a refresh:
from src.degiro_portfolio.database import SessionLocal, Stock
db = SessionLocal()
db.query(Stock).update({Stock.yahoo_ticker: None})
db.commit()
Then click Update Market Data in the web UI (or POST /api/update-market-data).
Pinning a specific listing
If Yahoo’s first result is wrong for a particular stock, add an entry to MANUAL_TICKER_MAPPING:
MANUAL_TICKER_MAPPING: Dict[str, Dict[str, str]] = {
# ... existing mappings ...
"GB0005405286": {"GBP": "HSBA.L"}, # HSBC Holdings - London
}
Manual mappings are checked first, before any network call, and always win.
For deeper internals (full mapping tables, troubleshooting, migration from old hard-coded mappings), see TICKER_RESOLUTION.md in the project root.
Rate Limiting
Yahoo Finance has undocumented rate limits (~2000 requests/hour). The application automatically throttles requests (~20/minute) to stay within limits.
If you see rate limit errors:
Wait 60 seconds and try again
Exchange rates are cached daily to reduce API calls
The app falls back gracefully when limits are hit
Environment Variables
You can optionally create a .env file in the project root:
PRICE_DATA_PROVIDER=yahoo
# Optional: adjust fetch periods
INITIAL_FETCH_PERIOD=max
INDEX_FETCH_PERIOD=5y
UPDATE_FETCH_PERIOD=7d
Troubleshooting
“No data returned” for a stock
Check if the ticker symbol is correct
The stock might be delisted or only available on regional exchanges
Try clicking “Update Market Data” again
Rate limit errors
Wait 60 seconds and try again
The app auto-throttles, but rapid manual refreshes can hit limits
Notes
Historical data is stored in the local database
Switching data providers doesn’t affect stored data
You can re-fetch data at any time by clicking “Update Market Data”