From 838e32388b18b7ef817ce7d76392b1ba5dc2d505 Mon Sep 17 00:00:00 2001 From: Robert Tidball Date: Wed, 8 Jul 2026 19:56:09 +1000 Subject: [PATCH] Add FXMacroData macro calendar integration --- pwb_toolbox/datasets/fxmacrodata.py | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 pwb_toolbox/datasets/fxmacrodata.py diff --git a/pwb_toolbox/datasets/fxmacrodata.py b/pwb_toolbox/datasets/fxmacrodata.py new file mode 100644 index 0000000..e4d48d1 --- /dev/null +++ b/pwb_toolbox/datasets/fxmacrodata.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +import os +from typing import Any + +import pandas as pd +import requests + + +def load_fxmacrodata_calendar( + currency: str = "usd", + start_date: str | None = None, + end_date: str | None = None, + api_key: str | None = None, + top_tier_only: bool = False, + base_url: str = "https://fxmacrodata.com/api/v1", +) -> pd.DataFrame: + """Load an FXMacroData release calendar as a pandas DataFrame.""" + + params: dict[str, Any] = {} + resolved_api_key = api_key if api_key is not None else os.getenv("FXMD_API_KEY") + if resolved_api_key: + params["api_key"] = resolved_api_key + if start_date: + params["start_date"] = start_date + if end_date: + params["end_date"] = end_date + + response = requests.get( + f"{base_url.rstrip('/')}/calendar/{currency.lower()}", + params=params, + headers={"Accept": "application/json"}, + timeout=30, + ) + response.raise_for_status() + rows = list((response.json() or {}).get("data") or []) + if top_tier_only: + rows = [row for row in rows if row.get("top_tier_for_currency") or row.get("market_tier") == 1] + + frame = pd.DataFrame(rows) + for column in ("announcement_datetime_utc", "announcement_datetime_local"): + if column in frame.columns: + frame[column] = pd.to_datetime(frame[column], errors="coerce") + return frame +