fxmacrodata 0.1.0__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,237 @@
1
+ Metadata-Version: 2.4
2
+ Name: fxmacrodata
3
+ Version: 1.1.0
4
+ Summary: Python client for the FXMacroData API, providing forex macroeconomic data for traders, quants, and analysts.
5
+ Author-email: FXMacroData <info@fxmacrodata.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://fxmacrodata.com/?utm_source=pypi&utm_medium=package&utm_campaign=python_sdk
8
+ Project-URL: Documentation, https://fxmacrodata.com/api/docs?utm_source=pypi&utm_medium=package&utm_campaign=python_sdk
9
+ Project-URL: Source, https://github.com/fxmacrodata/fxmacrodata
10
+ Project-URL: Issues, https://github.com/fxmacrodata/fxmacrodata
11
+ Keywords: forex,macro data,macroeconomics,trading,quant,economic indicators,fxmacrodata,rapidapi
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: requests>=2.28
16
+ Requires-Dist: aiohttp>=3.8
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest>=8.0; extra == "dev"
19
+ Requires-Dist: pytest-mock>=3.10; extra == "dev"
20
+ Requires-Dist: python-dotenv>=1.1; extra == "dev"
21
+ Requires-Dist: python-semantic-release>=7.23; extra == "dev"
22
+ Requires-Dist: twine>=4.0; extra == "dev"
23
+ Requires-Dist: build>=1.0; extra == "dev"
24
+ Requires-Dist: ruff>=0.0; extra == "dev"
25
+ Requires-Dist: mypy>=1.5; extra == "dev"
26
+ Requires-Dist: black>=24.0; extra == "dev"
27
+ Requires-Dist: types-requests>=2.28; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # FXMacroData Python SDK 🐍📊
31
+
32
+ ![PyPI Version](https://img.shields.io/pypi/v/fxmacrodata?color=blue&logo=python&style=flat-square)
33
+ ![Python Versions](https://img.shields.io/pypi/pyversions/fxmacrodata?style=flat-square)
34
+ ![License](https://img.shields.io/github/license/fxmacrodata/fxmacrodata?style=flat-square)
35
+ ![Build](https://img.shields.io/github/actions/workflow/status/fxmacrodata/fxmacrodata/ci-cd.yml?style=flat-square&logo=github)
36
+
37
+ The **FXMacroData Python SDK** provides a simple and efficient interface for fetching **macroeconomic indicators**, **forex prices**, **release calendars**, **COT positioning**, and **commodity prices** from [FXMacroData](https://fxmacrodata.com/?utm_source=github&utm_medium=readme&utm_campaign=python_sdk).
38
+
39
+ It includes both synchronous and asynchronous clients, supports free USD endpoints, and offers a free Forex Price API for exchange rate data.
40
+
41
+ ---
42
+
43
+ ## 🌟 Features
44
+
45
+ - Fetch:
46
+ - **Macroeconomic indicators** — policy rates, inflation, GDP, unemployment, bond yields, and 100+ more
47
+ - **FX spot rates** with optional technical indicators (SMA, RSI, MACD, Bollinger Bands)
48
+ - **Release calendars** — upcoming economic data release dates
49
+ - **Data catalogue** — discover available indicators per currency
50
+ - **COT data** — CFTC Commitment of Traders positioning
51
+ - **Commodity prices** — gold, silver, platinum
52
+ - Free access to **USD** macro data.
53
+ - Free **Forex Price API** (`get_fx_price`).
54
+ - API key required only for **non-USD** indicators.
55
+ - Full support for:
56
+ - **Synchronous client**
57
+ - **Asynchronous client**
58
+ - Lightweight: depends only on `requests` and `aiohttp`.
59
+
60
+ ---
61
+
62
+ ## 📦 Installation
63
+
64
+ Install from PyPI:
65
+
66
+ ```bash
67
+ pip install fxmacrodata
68
+ ```
69
+
70
+ Or install the latest version from GitHub:
71
+
72
+ ```bash
73
+ pip install git+https://github.com/fxmacrodata/fxmacrodata.git
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 🔧 Usage
79
+
80
+ ### Synchronous
81
+
82
+ ```python
83
+ from fxmacrodata import Client
84
+
85
+ client = Client(api_key="YOUR_API_KEY")
86
+
87
+ # Fetch macroeconomic indicators
88
+ data = client.get_indicator(
89
+ "aud", "policy_rate",
90
+ start_date="2023-01-01",
91
+ end_date="2023-11-01"
92
+ )
93
+ print(data)
94
+
95
+ # Free Forex Price Endpoint
96
+ fx = client.get_fx_price("usd", "gbp", start_date="2025-01-01")
97
+ print(fx)
98
+
99
+ # Forex with technical indicators
100
+ fx = client.get_fx_price("eur", "usd", indicators="sma_20,rsi_14,macd")
101
+ print(fx)
102
+
103
+ # Release calendar
104
+ calendar = client.get_calendar("usd")
105
+ print(calendar)
106
+
107
+ # Data catalogue — discover available indicators
108
+ catalogue = client.get_data_catalogue("usd")
109
+ print(catalogue)
110
+
111
+ # COT positioning data
112
+ cot = client.get_cot("eur", start_date="2025-01-01")
113
+ print(cot)
114
+
115
+ # Commodity prices
116
+ gold = client.get_commodities("gold", start_date="2026-01-01")
117
+ print(gold)
118
+ ```
119
+
120
+ ---
121
+
122
+ ### Asynchronous
123
+
124
+ ```python
125
+ import asyncio
126
+ from fxmacrodata import AsyncClient
127
+
128
+ async def main():
129
+ async with AsyncClient(api_key="YOUR_API_KEY") as client:
130
+ # Fetch macroeconomic indicators
131
+ data = await client.get_indicator("eur", "inflation")
132
+ print(data)
133
+
134
+ # Free Forex Price Endpoint
135
+ fx = await client.get_fx_price("usd", "jpy")
136
+ print(fx)
137
+
138
+ # Release calendar
139
+ calendar = await client.get_calendar("usd")
140
+ print(calendar)
141
+
142
+ # Data catalogue
143
+ catalogue = await client.get_data_catalogue("usd")
144
+ print(catalogue)
145
+
146
+ # COT positioning
147
+ cot = await client.get_cot("jpy")
148
+ print(cot)
149
+
150
+ # Commodity prices
151
+ gold = await client.get_commodities("gold")
152
+ print(gold)
153
+
154
+ asyncio.run(main())
155
+ ```
156
+
157
+ ---
158
+
159
+ ## 📘 API Overview
160
+
161
+ ### `get_indicator(currency, indicator, start_date=None, end_date=None)`
162
+ Fetches macroeconomic indicator time series data.
163
+
164
+ - `currency`: `"usd"`, `"aud"`, `"eur"`, `"gbp"`, `"cad"`, `"nok"`, `"nzd"`, `"jpy"`, `"brl"`, `"cny"`, `"dkk"`, `"pln"`, `"sek"`, `"sgd"`, etc.
165
+ - `indicator`: `"policy_rate"`, `"inflation"`, `"gdp"`, `"unemployment"`, `"trade_balance"`, `"current_account_balance"`, `"gov_bond_10y"`, etc.
166
+ - **API key required for non-USD.**
167
+
168
+ ### `get_fx_price(base, quote, start_date=None, end_date=None, indicators=None)`
169
+ Fetches daily FX spot rates (ECB reference rates) between two currencies.
170
+
171
+ - `indicators`: Optional comma-separated technical indicators — `"sma_20"`, `"sma_50"`, `"sma_200"`, `"rsi_14"`, `"macd"`, `"ema_12"`, `"ema_26"`, `"bollinger_bands"`, or `"all"`.
172
+ - **No API key needed.**
173
+
174
+ ### `get_calendar(currency, indicator=None)`
175
+ Fetches upcoming economic data release dates for a currency.
176
+
177
+ - `indicator`: Optional filter to a specific indicator slug.
178
+ - Returns `announcement_datetime` (Unix timestamp) and `release` (indicator slug).
179
+
180
+ ### `get_data_catalogue(currency, include_capabilities=False, include_coverage=False, indicator=None)`
181
+ Discovers available macroeconomic indicators for a given currency.
182
+
183
+ - Returns a dict keyed by indicator slug with `name`, `unit`, `frequency`, and `has_official_forecast`.
184
+ - **API key required for non-USD.**
185
+
186
+ ### `get_cot(currency, start_date=None, end_date=None)`
187
+ Fetches CFTC Commitment of Traders (COT) positioning data.
188
+
189
+ - Supported currencies: `AUD`, `CAD`, `CHF`, `EUR`, `GBP`, `JPY`, `NZD`, `USD`.
190
+ - **API key required for non-USD.**
191
+
192
+ ### `get_commodities(indicator, start_date=None, end_date=None)`
193
+ Fetches commodity price time series.
194
+
195
+ - `indicator`: `"gold"`, `"silver"`, or `"platinum"`.
196
+ - **API key required.**
197
+
198
+ ---
199
+
200
+ ## 💹 Supported Currencies & Indicators
201
+
202
+ | Category | Metric | USD | EUR | AUD | GBP |
203
+ |---------|--------|-----|-----|-----|-----|
204
+ | **Economy** | GDP Growth | ✓ | ✓ | ✓ | ✓ |
205
+ | | Inflation Rate | ✓ | ✓ | ✓ | ✓ |
206
+ | | Trade Balance | ✓ | ✓ | ✓ | ✓ |
207
+ | | Current Account Balance | ✓ | ✓ | ✓ | ✓ |
208
+ | **Labor Market** | Unemployment Rate | ✓ | ✓ | ✓ | ✓ |
209
+ | | Employment Level | ✓ | — | ✓ | ✓ |
210
+ | | Full-Time Employment | ✓ | — | ✓ | — |
211
+ | | Part-Time Employment | ✓ | — | ✓ | — |
212
+ | | Participation Rate | ✓ | — | ✓ | ✓ |
213
+ | | Non-Farm Payrolls | ✓ | — | — | — |
214
+ | **Monetary Policy** | Policy Rate | ✓ | ✓ | ✓ | ✓ |
215
+ | | Interbank Rate | ✓ | ✓ | ✓ | ✓ |
216
+ | **Government Bond Yields** | 2-Year Govt Bond | ✓ | ✓ | ✓ | — |
217
+ | | 3-Year Govt Bond | ✓ | ✓ | ✓ | — |
218
+ | | 5-Year Govt Bond | ✓ | ✓ | ✓ | ✓ |
219
+ | | 10-Year Govt Bond | ✓ | ✓ | ✓ | ✓ |
220
+ | | Inflation-Linked Bond | ✓ | — | ✓ | ✓ |
221
+
222
+ ---
223
+
224
+ ## 📄 License
225
+
226
+ MIT License © FXMacroData
227
+
228
+ ---
229
+
230
+ ## 🌐 Links
231
+
232
+ - Website: https://fxmacrodata.com
233
+ - API Docs: https://fxmacrodata.com/docs
234
+ - GitHub: https://github.com/fxmacrodata/fxmacrodata
235
+ - PyPI: https://pypi.org/project/fxmacrodata/
236
+ - Readthedocs: https://fxmacrodata.readthedocs.io/en/latest/
237
+ - Zenodo: https://zenodo.org/records/18280968
@@ -0,0 +1,208 @@
1
+ # FXMacroData Python SDK 🐍📊
2
+
3
+ ![PyPI Version](https://img.shields.io/pypi/v/fxmacrodata?color=blue&logo=python&style=flat-square)
4
+ ![Python Versions](https://img.shields.io/pypi/pyversions/fxmacrodata?style=flat-square)
5
+ ![License](https://img.shields.io/github/license/fxmacrodata/fxmacrodata?style=flat-square)
6
+ ![Build](https://img.shields.io/github/actions/workflow/status/fxmacrodata/fxmacrodata/ci-cd.yml?style=flat-square&logo=github)
7
+
8
+ The **FXMacroData Python SDK** provides a simple and efficient interface for fetching **macroeconomic indicators**, **forex prices**, **release calendars**, **COT positioning**, and **commodity prices** from [FXMacroData](https://fxmacrodata.com/?utm_source=github&utm_medium=readme&utm_campaign=python_sdk).
9
+
10
+ It includes both synchronous and asynchronous clients, supports free USD endpoints, and offers a free Forex Price API for exchange rate data.
11
+
12
+ ---
13
+
14
+ ## 🌟 Features
15
+
16
+ - Fetch:
17
+ - **Macroeconomic indicators** — policy rates, inflation, GDP, unemployment, bond yields, and 100+ more
18
+ - **FX spot rates** with optional technical indicators (SMA, RSI, MACD, Bollinger Bands)
19
+ - **Release calendars** — upcoming economic data release dates
20
+ - **Data catalogue** — discover available indicators per currency
21
+ - **COT data** — CFTC Commitment of Traders positioning
22
+ - **Commodity prices** — gold, silver, platinum
23
+ - Free access to **USD** macro data.
24
+ - Free **Forex Price API** (`get_fx_price`).
25
+ - API key required only for **non-USD** indicators.
26
+ - Full support for:
27
+ - **Synchronous client**
28
+ - **Asynchronous client**
29
+ - Lightweight: depends only on `requests` and `aiohttp`.
30
+
31
+ ---
32
+
33
+ ## 📦 Installation
34
+
35
+ Install from PyPI:
36
+
37
+ ```bash
38
+ pip install fxmacrodata
39
+ ```
40
+
41
+ Or install the latest version from GitHub:
42
+
43
+ ```bash
44
+ pip install git+https://github.com/fxmacrodata/fxmacrodata.git
45
+ ```
46
+
47
+ ---
48
+
49
+ ## 🔧 Usage
50
+
51
+ ### Synchronous
52
+
53
+ ```python
54
+ from fxmacrodata import Client
55
+
56
+ client = Client(api_key="YOUR_API_KEY")
57
+
58
+ # Fetch macroeconomic indicators
59
+ data = client.get_indicator(
60
+ "aud", "policy_rate",
61
+ start_date="2023-01-01",
62
+ end_date="2023-11-01"
63
+ )
64
+ print(data)
65
+
66
+ # Free Forex Price Endpoint
67
+ fx = client.get_fx_price("usd", "gbp", start_date="2025-01-01")
68
+ print(fx)
69
+
70
+ # Forex with technical indicators
71
+ fx = client.get_fx_price("eur", "usd", indicators="sma_20,rsi_14,macd")
72
+ print(fx)
73
+
74
+ # Release calendar
75
+ calendar = client.get_calendar("usd")
76
+ print(calendar)
77
+
78
+ # Data catalogue — discover available indicators
79
+ catalogue = client.get_data_catalogue("usd")
80
+ print(catalogue)
81
+
82
+ # COT positioning data
83
+ cot = client.get_cot("eur", start_date="2025-01-01")
84
+ print(cot)
85
+
86
+ # Commodity prices
87
+ gold = client.get_commodities("gold", start_date="2026-01-01")
88
+ print(gold)
89
+ ```
90
+
91
+ ---
92
+
93
+ ### Asynchronous
94
+
95
+ ```python
96
+ import asyncio
97
+ from fxmacrodata import AsyncClient
98
+
99
+ async def main():
100
+ async with AsyncClient(api_key="YOUR_API_KEY") as client:
101
+ # Fetch macroeconomic indicators
102
+ data = await client.get_indicator("eur", "inflation")
103
+ print(data)
104
+
105
+ # Free Forex Price Endpoint
106
+ fx = await client.get_fx_price("usd", "jpy")
107
+ print(fx)
108
+
109
+ # Release calendar
110
+ calendar = await client.get_calendar("usd")
111
+ print(calendar)
112
+
113
+ # Data catalogue
114
+ catalogue = await client.get_data_catalogue("usd")
115
+ print(catalogue)
116
+
117
+ # COT positioning
118
+ cot = await client.get_cot("jpy")
119
+ print(cot)
120
+
121
+ # Commodity prices
122
+ gold = await client.get_commodities("gold")
123
+ print(gold)
124
+
125
+ asyncio.run(main())
126
+ ```
127
+
128
+ ---
129
+
130
+ ## 📘 API Overview
131
+
132
+ ### `get_indicator(currency, indicator, start_date=None, end_date=None)`
133
+ Fetches macroeconomic indicator time series data.
134
+
135
+ - `currency`: `"usd"`, `"aud"`, `"eur"`, `"gbp"`, `"cad"`, `"nok"`, `"nzd"`, `"jpy"`, `"brl"`, `"cny"`, `"dkk"`, `"pln"`, `"sek"`, `"sgd"`, etc.
136
+ - `indicator`: `"policy_rate"`, `"inflation"`, `"gdp"`, `"unemployment"`, `"trade_balance"`, `"current_account_balance"`, `"gov_bond_10y"`, etc.
137
+ - **API key required for non-USD.**
138
+
139
+ ### `get_fx_price(base, quote, start_date=None, end_date=None, indicators=None)`
140
+ Fetches daily FX spot rates (ECB reference rates) between two currencies.
141
+
142
+ - `indicators`: Optional comma-separated technical indicators — `"sma_20"`, `"sma_50"`, `"sma_200"`, `"rsi_14"`, `"macd"`, `"ema_12"`, `"ema_26"`, `"bollinger_bands"`, or `"all"`.
143
+ - **No API key needed.**
144
+
145
+ ### `get_calendar(currency, indicator=None)`
146
+ Fetches upcoming economic data release dates for a currency.
147
+
148
+ - `indicator`: Optional filter to a specific indicator slug.
149
+ - Returns `announcement_datetime` (Unix timestamp) and `release` (indicator slug).
150
+
151
+ ### `get_data_catalogue(currency, include_capabilities=False, include_coverage=False, indicator=None)`
152
+ Discovers available macroeconomic indicators for a given currency.
153
+
154
+ - Returns a dict keyed by indicator slug with `name`, `unit`, `frequency`, and `has_official_forecast`.
155
+ - **API key required for non-USD.**
156
+
157
+ ### `get_cot(currency, start_date=None, end_date=None)`
158
+ Fetches CFTC Commitment of Traders (COT) positioning data.
159
+
160
+ - Supported currencies: `AUD`, `CAD`, `CHF`, `EUR`, `GBP`, `JPY`, `NZD`, `USD`.
161
+ - **API key required for non-USD.**
162
+
163
+ ### `get_commodities(indicator, start_date=None, end_date=None)`
164
+ Fetches commodity price time series.
165
+
166
+ - `indicator`: `"gold"`, `"silver"`, or `"platinum"`.
167
+ - **API key required.**
168
+
169
+ ---
170
+
171
+ ## 💹 Supported Currencies & Indicators
172
+
173
+ | Category | Metric | USD | EUR | AUD | GBP |
174
+ |---------|--------|-----|-----|-----|-----|
175
+ | **Economy** | GDP Growth | ✓ | ✓ | ✓ | ✓ |
176
+ | | Inflation Rate | ✓ | ✓ | ✓ | ✓ |
177
+ | | Trade Balance | ✓ | ✓ | ✓ | ✓ |
178
+ | | Current Account Balance | ✓ | ✓ | ✓ | ✓ |
179
+ | **Labor Market** | Unemployment Rate | ✓ | ✓ | ✓ | ✓ |
180
+ | | Employment Level | ✓ | — | ✓ | ✓ |
181
+ | | Full-Time Employment | ✓ | — | ✓ | — |
182
+ | | Part-Time Employment | ✓ | — | ✓ | — |
183
+ | | Participation Rate | ✓ | — | ✓ | ✓ |
184
+ | | Non-Farm Payrolls | ✓ | — | — | — |
185
+ | **Monetary Policy** | Policy Rate | ✓ | ✓ | ✓ | ✓ |
186
+ | | Interbank Rate | ✓ | ✓ | ✓ | ✓ |
187
+ | **Government Bond Yields** | 2-Year Govt Bond | ✓ | ✓ | ✓ | — |
188
+ | | 3-Year Govt Bond | ✓ | ✓ | ✓ | — |
189
+ | | 5-Year Govt Bond | ✓ | ✓ | ✓ | ✓ |
190
+ | | 10-Year Govt Bond | ✓ | ✓ | ✓ | ✓ |
191
+ | | Inflation-Linked Bond | ✓ | — | ✓ | ✓ |
192
+
193
+ ---
194
+
195
+ ## 📄 License
196
+
197
+ MIT License © FXMacroData
198
+
199
+ ---
200
+
201
+ ## 🌐 Links
202
+
203
+ - Website: https://fxmacrodata.com
204
+ - API Docs: https://fxmacrodata.com/docs
205
+ - GitHub: https://github.com/fxmacrodata/fxmacrodata
206
+ - PyPI: https://pypi.org/project/fxmacrodata/
207
+ - Readthedocs: https://fxmacrodata.readthedocs.io/en/latest/
208
+ - Zenodo: https://zenodo.org/records/18280968
@@ -0,0 +1,160 @@
1
+ import aiohttp # type: ignore
2
+ from typing import Optional
3
+ from .exceptions import FXMacroDataError
4
+
5
+
6
+ class AsyncClient:
7
+ BASE_URL = "https://fxmacrodata.com/api"
8
+
9
+ def __init__(self, api_key: Optional[str] = None):
10
+ self.api_key: Optional[str] = api_key
11
+ self.session: Optional[aiohttp.ClientSession] = None
12
+
13
+ async def __aenter__(self) -> "AsyncClient":
14
+ self.session = aiohttp.ClientSession()
15
+ return self
16
+
17
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
18
+ if self.session:
19
+ await self.session.close()
20
+ self.session = None
21
+
22
+ async def _request(self, url: str, params: dict, headers: dict) -> dict:
23
+ if not self.session:
24
+ self.session = aiohttp.ClientSession()
25
+ async with self.session.get(url, headers=headers, params=params) as resp:
26
+ if resp.status != 200:
27
+ text = await resp.text()
28
+ raise FXMacroDataError(f"{resp.status} - {text}")
29
+ return await resp.json()
30
+
31
+ def _auth_headers(self, currency: str, *, required: bool = True) -> dict:
32
+ headers: dict[str, str] = {}
33
+ if currency != "usd":
34
+ if required and not self.api_key:
35
+ raise FXMacroDataError(
36
+ f"API key required for {currency.upper()} endpoints."
37
+ )
38
+ if self.api_key:
39
+ headers["X-API-Key"] = self.api_key
40
+ return headers
41
+
42
+ # ------------------------------------------------------------------
43
+ # Macroeconomic indicator time-series
44
+ # ------------------------------------------------------------------
45
+ async def get_indicator(
46
+ self,
47
+ currency: str,
48
+ indicator: str,
49
+ start_date: Optional[str] = None,
50
+ end_date: Optional[str] = None,
51
+ ) -> dict:
52
+ currency = currency.lower()
53
+ url = f"{self.BASE_URL}/v1/announcements/{currency}/{indicator}"
54
+ headers = self._auth_headers(currency)
55
+ params: dict[str, str] = {}
56
+ if start_date:
57
+ params["start_date"] = start_date
58
+ if end_date:
59
+ params["end_date"] = end_date
60
+ return await self._request(url, params, headers)
61
+
62
+ # ------------------------------------------------------------------
63
+ # FX spot rates (free)
64
+ # ------------------------------------------------------------------
65
+ async def get_fx_price(
66
+ self,
67
+ base: str,
68
+ quote: str,
69
+ start_date: Optional[str] = None,
70
+ end_date: Optional[str] = None,
71
+ indicators: Optional[str] = None,
72
+ ) -> dict:
73
+ base = base.lower()
74
+ quote = quote.lower()
75
+ url = f"{self.BASE_URL}/v1/forex/{base}/{quote}"
76
+ params: dict[str, str] = {}
77
+ if start_date:
78
+ params["start_date"] = start_date
79
+ if end_date:
80
+ params["end_date"] = end_date
81
+ if indicators:
82
+ params["indicators"] = indicators
83
+ return await self._request(url, params, {})
84
+
85
+ # ------------------------------------------------------------------
86
+ # Release calendar
87
+ # ------------------------------------------------------------------
88
+ async def get_calendar(
89
+ self,
90
+ currency: str,
91
+ indicator: Optional[str] = None,
92
+ ) -> dict:
93
+ currency = currency.lower()
94
+ url = f"{self.BASE_URL}/v1/calendar/{currency}"
95
+ headers = self._auth_headers(currency, required=False)
96
+ params: dict[str, str] = {}
97
+ if indicator:
98
+ params["indicator"] = indicator
99
+ return await self._request(url, params, headers)
100
+
101
+ # ------------------------------------------------------------------
102
+ # Data catalogue — available indicators for a currency
103
+ # ------------------------------------------------------------------
104
+ async def get_data_catalogue(
105
+ self,
106
+ currency: str,
107
+ include_capabilities: bool = False,
108
+ include_coverage: bool = False,
109
+ indicator: Optional[str] = None,
110
+ ) -> dict:
111
+ currency = currency.lower()
112
+ url = f"{self.BASE_URL}/v1/data_catalogue/{currency}"
113
+ headers = self._auth_headers(currency)
114
+ params: dict[str, str] = {}
115
+ if include_capabilities:
116
+ params["include_capabilities"] = "true"
117
+ if include_coverage:
118
+ params["include_coverage"] = "true"
119
+ if indicator:
120
+ params["indicator"] = indicator
121
+ return await self._request(url, params, headers)
122
+
123
+ # ------------------------------------------------------------------
124
+ # CFTC Commitment of Traders (COT)
125
+ # ------------------------------------------------------------------
126
+ async def get_cot(
127
+ self,
128
+ currency: str,
129
+ start_date: Optional[str] = None,
130
+ end_date: Optional[str] = None,
131
+ ) -> dict:
132
+ currency = currency.lower()
133
+ url = f"{self.BASE_URL}/v1/cot/{currency}"
134
+ headers = self._auth_headers(currency)
135
+ params: dict[str, str] = {}
136
+ if start_date:
137
+ params["start_date"] = start_date
138
+ if end_date:
139
+ params["end_date"] = end_date
140
+ return await self._request(url, params, headers)
141
+
142
+ # ------------------------------------------------------------------
143
+ # Commodities (gold, silver, platinum)
144
+ # ------------------------------------------------------------------
145
+ async def get_commodities(
146
+ self,
147
+ indicator: str,
148
+ start_date: Optional[str] = None,
149
+ end_date: Optional[str] = None,
150
+ ) -> dict:
151
+ if not self.api_key:
152
+ raise FXMacroDataError("API key required for commodities endpoints.")
153
+ url = f"{self.BASE_URL}/v1/commodities/{indicator.lower()}"
154
+ headers: dict[str, str] = {"X-API-Key": self.api_key}
155
+ params: dict[str, str] = {}
156
+ if start_date:
157
+ params["start_date"] = start_date
158
+ if end_date:
159
+ params["end_date"] = end_date
160
+ return await self._request(url, params, headers)