Hermes logoHermes
Core Concepts

Features

Hermes turns raw datasets into derived intelligence through a tiered, dependency-aware feature engine that records lineage. ~57 features ship across five country-risk groups plus technical, fundamental, crypto-history and filing feature sets.

Feature groups at a glance

GroupCountSource(s)Status
Economic18World Bank + IMFWorking
Environmental6ND-GAIN + World BankPartial (2 placeholders)
Security7SIPRI / NATO datasetsPartial (4 placeholders)
Social6World Bank + HRS / FSI / HDIPartial (1 placeholder)
Geopolitical21GDELT / WGIStubbed
Technical (crypto)~50 per snapshotBinanceWorking
FundamentalCompanyFundamentalSEC + Finnhub + FRED + yfinanceWorking
Filing (crypto fam)SEC factsWorking

Country-risk features are the bread-and-butter: five groups covering the dimensions that matter when assessing a sovereign. Financial features layer market and company intelligence on top.

The feature engine

The core abstraction lives in hermes/features/. The features registry (constructed with features(os_api)) exposes five country-risk groups and list_features() returns every registered callable.

registry
class features:
    def __init__(self, os_api: str):
        self.eco = economic_features()
        self.env = enviromental_features()
        self.geo = geopolitical_features(os_api=os_api)
        self.sec = security_features()
        self.soc = social_features()

    def list_features(self) -> list[Callable]

@feature, LineageGraph & TieredPlan

Features register themselves through a @feature decorator that records their name, group, dependencies and compute expression into a module-level singleton lineagegraph = LineageGraph():

python
from hermes.features import feature

@feature(
    name="gdp_growth_5y",
    group="economic",
    deps=["economic:gdp_growth_yoy"],
    compute="rolling(5).mean()",
)
async def compute_growth(df, config):
    return df["gdp_growth"].rolling(5).mean()

LineageGraph.register_feature(name, group, deps, compute, fn) stores the record and appends the name to groups[group]. resolve_group(group) performs a topological layering: it repeatedly emits a tier of features whose cross-feature dependencies are already satisfied, producing a TieredPlan(tiers, all_features). The graph and tiers persist to JSON via save(path) / load(path) (functions are dropped on load).

Country-risk features

Every country-risk feature shares the signature async <feature>(country_code, mode="F"). mode="F" returns the latest scalar; mode="ML" returns a pd.Series indexed by year (2000–2025, forward-filled). Helper adjust_year_range(df, year_col, start, end, fill_method, fill_value) merges onto the full year range with value/ffill/bfill/linear fills.

Economic (18)

World Bank + IMF
economic
gdp_growth_yoy            NY.GDP.MKTP.KD.ZG        GDP growth YoY (%)
gdp_growth_qoq            NY.GDP.MKTP.KD          GDP growth QoQ
industrial_production_yoy NV.IND.MANF.KD.ZG       industrial production YoY
inflation_cpi_yoy         FP.CPI.TOTL.ZG          CPI inflation YoY
inflation_volatility_12m  FP.CPI.TOTL             CPI YoY rolled 12-period std
ppi_yoy                   IMF ...PPI.IX.A         producer price index YoY
inflation_yoy             IMF ...CPI._T.IX.M     inflation YoY (monthly)
unemployment_rate         SL.UEM.TOTL.ZS
youth_unemployment        SL.UEM.1524.ZS
labor_force_participation SL.TLF.CACT.ZS
current_account_gdp_ratio BN.CAB.XOKA.GD.ZS
fx_reserves_months_import FI.RES.TOTL.MO
external_debt_gdp_ratio   DT.DOD.DECT.GN.ZS
fiscal_deficit_gdp        IMF WEO GGXCNL_NGDP
government_debt_gdp       IMF WEO GGXWDG_NGDP
reer_misalignment         IMF ...EREER_IX.M
banking_sector_health     FB.AST.NPLN.ZS
gdp_per_capita_ppp        NY.GDP.PCAP.PP.CD

Environmental (6)

ND-GAIN + World Bank
  • climate_vulnerability_score — NDGAIN CVS dataset score (implemented)
  • climate_readiness_score — NDGAIN CRS dataset score (implemented)
  • energy_dependence_ratio — WB EG.IMP.CONS.ZS (implemented)
  • water_stress_index — WB ER.H2O.FWTL.ZS (implemented)
  • natural_disaster_risk — placeholder
  • food_price_index_change_yoy — placeholder

Security (7)

SIPRI / NATO datasets
  • military_spending_gdp — SIPRI military expenditure % of GDP (implemented)
  • military_spending_growth_yoy — SIPRI pct_change(1)*100 (implemented)
  • nato_member — NATO membership bool, deps=['nato:membership'] (implemented)
  • alliance_strength_score, arms_imports_12m, arms_exports_12m, peacekeeping_troops — placeholders

Social (6)

World Bank + HRS / FSI / HDI datasets
  • human_rights_score — HRS dataset human_right_score
  • fragile_state_index — FSI dataset Total (0–120)
  • human_development_index — HDI dataset score
  • gini_coefficient — WB SI.POV.GINI
  • poverty_headcount_ratio — WB SI.POV.DDAY
  • social_stability_index — placeholder

Geopolitical (21)

stubbed — NotImplementedError pending GDELT/WGI rebuild

The public API surface is preserved: conflict_event_count_30d/90d, conflict_trend, goldstein_scale_avg_30d, goldstein_scale_trend, battle_deaths_30d/90d, protest_event_count_30d, protest_violence_level, diplomatic_event_count_30d, diplomatic_intensity_avg, sanctions_count_active, sanctions_new_30d, sanctions_sector_coverage, governance_wgi_composite, corruption_perception_index, rule_of_law_score, regulatory_quality, democracy_index, regime_type (democracy | hybrid | autocracy), press_freedom_score.

The country-risk pipeline

The pipeline class coordinates the groups. get_country_risk_features(country) validates the ISO3 code, runs all features concurrently with asyncio.gather (a _safe_call swallows exceptions into None), and returns:

python
{
  "country": "USA",
  "economic": {...},     # feature -> value
  "geopolitical": {...},
  "security": {...},
  "social": {...},
  "environmental": {...},
  "metadata": {
    "last_updated": ...,
    "features_version": "1.0.0",
  },
}

build_training_panel(fns, countries) calls each function with mode="ML" across countries and stacks them into a pd.DataFrame with a MultiIndex of (country_iso3, date) — ready for supervised modeling.

Financial features

Technical analysis — TAfeatures (crypto, via Binance)

Helpers: _sma, _ema (pandas ewm, adjust=False), _zscore (sample std, ddof=1), _returns (log returns). Methods each return a dict of features:

MethodFeatures computed
calculate_price_features(candles)open, high, low, close, volume, quote_volume, ret_1b/5b/10b/60b, ret_open_to_close, hl_range, body_range, dist_sma_20/50/200, ema_diff_9_21, ema_diff_21_50, vol_20, vol_60, atr_14_norm, volume_rel_20, taker_buy_vol_ratio
trade_features(symbol, limit=1000)trades_count, trade_window_*, trade_buy_vol_ratio, avg_trade_size, median_trade_size, large_trade_vol_ratio (95th pct)
orderbook_features(symbol, limit=20)bid/ask price & qty, spread_abs, spread_bps, top_book_imbalance, depth_bid_total, depth_ask_total, depth_imbalance
day_features(symbol)high/low/last_24h, range_24h, pct_change_24h, pos_in_24h_range, volume_24h, quote_volume_24h
funding_features(symbol, limit=30)funding_rate, funding_rate_lag_3, funding_rate_change, funding_rate_zscore
oi_features(symbol)open_interest, oi_change_1h, oi_change_24h
positioning_features(symbol, period='1h', limit=30)trend_score, mean_reversion_score, liquidity_score, order_flow_score, sentiment_score

build_snapshot(symbol) (→ TechnicalSnapshot dataclass, ~50 fields) adds oi_to_volume_24h; get_technical(symbol) returns snapshots.

Crypto history — CryptoHistory

get_history(symbol, interval='1d', market='future', years=2) fetches Binance history and computes a vectorized rolling feature set ( TechnicalHistoryRow, ~90 fields) including: log returns ret_1b/3b/5b/10b/20b/60b, rsi_14 (Wilder), macd/macd_signal/macd_hist, Bollinger bb_upper/lower/width/pct, obv, returns_skew_20/returns_kurt_20, drawdown, amihud_illiquidity, plus extended volume/z-score/trend/ratio features.

Fundamental analysis — FAfeatures

Combines SEC facts + filing metadata + Finnhub metrics + FRED macro + yfinance estimates into a CompanyFundamental row via get_fundamentels(symbol). Notable helpers:

  • extract_funds_sec(data) — maps SEC us-gaap facts through SEC_TAG_MAP to most-recent values
  • extract_filing_meta(data) — filing_date, fiscal_year, fiscal_period, filing_type
  • macro() — FRED GDP, CPI, FEDFUNDS, UNRATE, GFDEBTN, exchange rates
  • Computes revenue_surprise = (revenue − revenue_estimate) / revenue_estimate
  • Ratio metadata aliases: P/E, P/S, P/B, EV/EBITDA, ROE, ROA, Debt/Equity

Company filings — CompanyFiling

get_history(quarters=8, symbols=None) fetches SEC facts for each ticker and computes filing-derived fundamentals with true YoY matching by fiscal period. Feature families: growth, margins, liquidity, leverage, cash-flow quality, efficiency, balance-sheet growth, shareholder (share_count/buyback/dividend change), and coverage (interest_coverage). get_candle_history pulls candles via Finnhub with automatic yfinance fallback when fewer than 100 rows.

Compute through the facade

python
from hermes import Hermes
hermes = Hermes(opensanction_api="x", new_data_api="x",
                sec_username="x", sec_email="x")

# Full country-risk scan
scan = await hermes.country_features.get_country_risk_features("USA")

# Single economic feature, ML-mode series
series = await hermes.lf.eco.gdp_growth_yoy("USA", mode="ML")

# Technical snapshot for a crypto symbol
snap = hermes.ta_feature.get_technical("BTCUSDT")
Feature catalog
View the full country-risk and financial feature inventories in hermes/features/, and the analysis deep-dives in the repo under docs/analysis/fundamentals.md and docs/analysis/technical.md.