Hermes logoHermes
Getting Started

Quickstart

Install Hermes, instantiate the facade, fetch data from a connector and compute features — no API keys required for the World Bank source.

What you'll walk away with
An installed hermes-plt environment, a working Hermes() facade, one fetched dataset, two computed country-risk features, and a peek inside the cache. Roughly 10 minutes start to finish.

1. Install

Hermes requires Python 3.11 or newer. It is distributed on PyPI as hermes-plt:

terminal
pip install hermes-plt

Runtime dependencies include aiohttp, pandas, pyarrow, fastparquet, pycountry, pydantic, sdmx, sec-cik-mapper and yfinance — installed automatically.

Sanity-check the install by importing the facade and listing what ships with it:

terminal
$ python -c "import hermes; print(hermes.__version__)"
0.2.14

$ python -c "from hermes import Hermes; print(Hermes.__name__)"
Hermes

2. Instantiate the facade

The Hermes class is the single entry point. Its constructor takes the API credentials it may need and sets up a shared cache:

python
from hermes import Hermes

hermes = Hermes(
    opensanction_api="",
    new_data_api="",
    fred_api="",
    sec_username="",
    sec_email="",
    finnhub_api="",
    cache_dir=None,   # defaults to ~/.hermes_cache/raw
    use_cache=True,
)
KeyError guard
The constructor raises KeyError if both opensanction_api and new_data_api are empty. Pass any placeholder to proceed — only connectors you actually use need real keys.

Setting use_cache=False disables the RawCache; otherwise all connectors share one RawCache(cache_dir).

3. Fetch a dataset

Connectors are async (built on aiohttp with exponential-backoff retries). Pull annual GDP growth for the US from the World Bank:

python
import asyncio
from hermes import Hermes

hermes = Hermes(
    opensanction_api="x",
    new_data_api="x",
    sec_username="me@example.com",
    sec_email="me@example.com",
)

# Annual GDP growth (%) for the United States
df = hermes.world_bank.fetch(
    country_code="US",
    indicator_code="NY.GDP.MKTP.KD.ZG",
    frequency="Y",
    per_page=1000,
)

print(df.head())
#       date indicator_id  ...   value   source
# 0  2023-01-01  NY.GDP.MKTP.KD.ZG  ...  2.54  world_bank

The returned DataFrame follows the canonical connector schema: date, indicator_id, indicator_name, country, value, source. Flag force=True to bypass the cache for a fresh pull.

4. Compute country-risk features

Feed a country through the country-risk pipeline to derive intelligence across all five feature groups. Each feature accepts mode="F" (latest scalar) or mode="ML" (a pd.Series indexed by year 2000–2025, forward-filled):

python
# Country-risk economic features for the US (mode="F" → scalar)
gdp = await hermes.country_features.get_country_risk_features("USA")

# Or compute a single economic feature directly
growth = await hermes.lf.eco.gdp_growth_yoy(
    country_code="USA",
    mode="F",          # "F" → float, "ML" → pd.Series indexed by year
)

print(growth)  # e.g. 2.54

5. Inspect the cache

Check per-source hit/miss statistics and purge entries older than a threshold:

python
stats = hermes.cache_stats()
print(stats)
# {
#   "total_files": 3,
#   "by_source": {"world_bank": 2, "imf": 1},
#   "hits": {"world_bank": 5},
#   "misses": {"world_bank": 2},
#   "hit_rate": {"world_bank": 0.71},
#}

# Purge cached files older than 7 days
hermes.clear_cache(older_than="7d")
Cache path
Files live under ~/.hermes_cache/raw/<source>/<hash>.parquet with a .meta.json sidecar. Keys are a 16-char sha256 of the source plus sorted JSON params.

Environment variables

Copy .env.example to .env and fill in the keys used by the connectors you need:

.env
OPEN_SANCTIONS_API=
NEWS_DATA_API=
FRED_API=
FINNHUB_API=
SEC_USERNAME=
SEC_EMAIL=
VariableUsed by
OPEN_SANCTIONS_APIOpenSanctions connector
NEWS_DATA_APIOpenSanctions connector
FRED_APIFRED connector (macro series)
FINNHUB_APIFinnhub connector + financial features
SEC_USERNAME / SEC_EMAILSEC EDGAR connector (User-Agent)

Troubleshooting

Stuck? Here are the most common snags and their fixes:

SymptomCause & fix
KeyError at constructionBoth opensanction_api and new_data_api empty — pass any placeholder
World Bank fetch returns emptyCheck country_code / indicator_code spelling; try force=True
Rate limited / timeoutsRetries are built in; raise retries or throttle with per-source TTL
Slow first fetchExpected — cache is cold; later calls hit the parquet cache
cached: 0 hitsYou haven't re-run after the first fetch; force=False reuses cache

Next steps

You now have a live pipeline. A few natural next moves: explore the other connectors, see how the feature engine turns this data into derived intelligence, or dive into the API reference for the full surface.