A script that fetches exchange rates from one or more providers and sends a notification when the aggregated rate is above a defined threshold.
Currently supported providers:
- OpenExchangeRates
- ExchangeRate-API
- currencyapi
- apilayer exchangeratesapi
- fawazahmed0 exchange-api
- Bank Al-Maghrib (
CoursBBEandCoursVirementendpoints)
For multi-source mode, the script always collects per-source details and computes an aggregated rate using:
median(recommended default)mean
The script runs on a defined scheduled GitHub Actions workflow (in theory, but it will never be on the exact defined timing, see here for more information).
Note: This script was tested and used with Python 3.12
- Create a
.envfile based on.env.sample. - Configure at least one provider in
RATE_SOURCES. - Add required credentials for each selected provider:
openexchangerates->OER_APP_IDexchangerate_api->EXCHANGERATE_API_KEYcurrencyapi->CURRENCYAPI_API_KEYapilayer_exchangeratesapi->APILAYER_EXCHANGERATESAPI_ACCESS_KEYfawazahmed0_exchange_api-> no API key required (optionalFAWAZAHMED0_CURRENCY_API_DATE)bank_al_maghrib->BAM_SUBSCRIPTION_KEY
- Run the script as specified below in
Runstep.
- Create a GitHub Actions repository secret named
ENV_FILE_CONTENTand populate it with the same content as your local.env. - Create a GitHub Actions repository variable named
THRESHOLD_RATE(kept separate because it changes more frequently). - Either run manually or wait until scheduled time.
Core settings:
BASE_CURRENCYQUOTE_CURRENCYTHRESHOLD_RATERATE_SOURCES(comma separated)AGGREGATION_METHOD(median,mean)MIN_SUCCESSFUL_SOURCES(default1)HTTP_TIMEOUT_SECONDS,HTTP_MAX_RETRIES,HTTP_BACKOFF_BASE_SECONDS,HTTP_BACKOFF_MAX_SECONDSNOTIFY_ON_AGGREGATION_FAILURE(truerecommended)
Provider-specific settings:
- OpenExchangeRates:
OER_APP_ID - ExchangeRate-API:
EXCHANGERATE_API_KEY - currencyapi:
CURRENCYAPI_API_KEY - apilayer exchangeratesapi:
APILAYER_EXCHANGERATESAPI_ACCESS_KEY - fawazahmed0 exchange-api: optional
FAWAZAHMED0_CURRENCY_API_DATE(latestby default) - Bank Al-Maghrib:
BAM_SUBSCRIPTION_KEY, optionalBAM_ENDPOINT(CoursBBEby default)
Reliability recommendations:
HTTP_TIMEOUT_SECONDS=12HTTP_MAX_RETRIES=2HTTP_BACKOFF_BASE_SECONDS=0.5HTTP_BACKOFF_MAX_SECONDS=4NOTIFY_ON_AGGREGATION_FAILURE=true
Example configuration:
BASE_CURRENCY=EUR
QUOTE_CURRENCY=MAD
THRESHOLD_RATE=10.30
RATE_SOURCES=openexchangerates,exchangerate_api,currencyapi,apilayer_exchangeratesapi,fawazahmed0_exchange_api,bank_al_maghrib
AGGREGATION_METHOD=median
MIN_SUCCESSFUL_SOURCES=1
HTTP_TIMEOUT_SECONDS=12
HTTP_MAX_RETRIES=2
HTTP_BACKOFF_BASE_SECONDS=0.5
HTTP_BACKOFF_MAX_SECONDS=4
NOTIFY_ON_AGGREGATION_FAILURE=true
OER_APP_ID=your_openexchangerates_app_id
EXCHANGERATE_API_KEY=your_exchangerate_api_key
CURRENCYAPI_API_KEY=your_currencyapi_key
APILAYER_EXCHANGERATESAPI_ACCESS_KEY=your_apilayer_exchangeratesapi_key
FAWAZAHMED0_CURRENCY_API_DATE=latest
BAM_SUBSCRIPTION_KEY=your_bank_al_maghrib_key
BAM_ENDPOINT=CoursBBEUse src/rates/providers/template.py as a starting point.
- Copy it to
src/rates/providers/<provider_name>.py. - Rename
TemplateProviderand setsource_name. - Implement request/auth and map response fields to
rateand optional metadata. - Export it from
src/rates/providers/__init__.py. - Register it in
AVAILABLE_PROVIDERSinsidesrc/rates/service.py. - Add any required env vars to
.env.sampleand tests undertests/test_rates/providers/.
Install dependencies:
poetry installRun the script:
make runFormat:
make formatLint:
make lint