prefect-fxmacrodata 0.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.
- prefect_fxmacrodata-0.1.0/CAPABILITIES.md +95 -0
- prefect_fxmacrodata-0.1.0/LICENSE +21 -0
- prefect_fxmacrodata-0.1.0/MANIFEST.in +16 -0
- prefect_fxmacrodata-0.1.0/PKG-INFO +169 -0
- prefect_fxmacrodata-0.1.0/PUBLIC_FILES.json +20 -0
- prefect_fxmacrodata-0.1.0/README.md +154 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/__init__.py +19 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/credentials.py +30 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/flows.py +42 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/models.py +51 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/py.typed +0 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/tasks.py +197 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata/tasks.pyi +93 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata.egg-info/PKG-INFO +169 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata.egg-info/SOURCES.txt +22 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata.egg-info/dependency_links.txt +1 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata.egg-info/entry_points.txt +2 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata.egg-info/requires.txt +2 -0
- prefect_fxmacrodata-0.1.0/prefect_fxmacrodata.egg-info/top_level.txt +1 -0
- prefect_fxmacrodata-0.1.0/pyproject.toml +39 -0
- prefect_fxmacrodata-0.1.0/setup.cfg +4 -0
- prefect_fxmacrodata-0.1.0/tests/conftest.py +107 -0
- prefect_fxmacrodata-0.1.0/tests/test_runtime.py +127 -0
- prefect_fxmacrodata-0.1.0/tests/test_tasks.py +211 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Operation coverage
|
|
2
|
+
|
|
3
|
+
This release exposes all 79 operations in the public-client 0.1.1 inventory:
|
|
4
|
+
29 REST operations (28 GET, 1 POST) and 50 hosted MCP tools. Each is a named Prefect task
|
|
5
|
+
imported from `prefect_fxmacrodata.tasks`; exact input schemas are available through
|
|
6
|
+
`operation_schemas()`. This inventory is the service snapshot verified on 2026-09-11.
|
|
7
|
+
|
|
8
|
+
| Task | Transport and path | Complete history |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| `health` | `GET /v1/health` | Not offset-paginated |
|
|
11
|
+
| `ping` | `GET /v1/ping` | Not offset-paginated |
|
|
12
|
+
| `forex` | `GET /v1/forex/{base}/{quote}` | `complete_history` |
|
|
13
|
+
| `intraday_reference_rates` | `GET /v1/fx/intraday-reference-rates/{base}/{quote}` | Not offset-paginated |
|
|
14
|
+
| `fx_sources` | `GET /v1/fx/sources` | Not offset-paginated |
|
|
15
|
+
| `fx_source_universe` | `GET /v1/fx/source-universe` | Not offset-paginated |
|
|
16
|
+
| `data_catalogue` | `GET /v1/data_catalogue/{currency}` | Not offset-paginated |
|
|
17
|
+
| `release_calendar` | `GET /v1/calendar/{currency}` | Not offset-paginated |
|
|
18
|
+
| `market_sessions` | `GET /v1/market_sessions` | Not offset-paginated |
|
|
19
|
+
| `rate_differentials` | `GET /v1/rate_differentials/{base}/{quote}` | `complete_history` |
|
|
20
|
+
| `curves` | `GET /v1/curves/{currency}` | Not offset-paginated |
|
|
21
|
+
| `financial_prices` | `GET /v1/financial_prices/{currency}` | `complete_history` |
|
|
22
|
+
| `press_releases` | `GET /v1/press-releases/{currency}` | `complete_history` |
|
|
23
|
+
| `risk_sentiment` | `GET /v1/risk_sentiment` | `complete_history` |
|
|
24
|
+
| `factors` | `GET /v1/factors/{currency}/{factor}` | `complete_history` |
|
|
25
|
+
| `event_predictions` | `GET /v1/predictions/{currency}/{indicator}` | `complete_history` |
|
|
26
|
+
| `latest_announcements` | `GET /v1/announcements/{currency}/latest` | Not offset-paginated |
|
|
27
|
+
| `indicator_history` | `GET /v1/announcements/{currency}/{indicator}` | `complete_history` |
|
|
28
|
+
| `cot` | `GET /v1/cot/{currency}` | `complete_history` |
|
|
29
|
+
| `latest_commodities` | `GET /v1/commodities/latest` | Not offset-paginated |
|
|
30
|
+
| `commodities` | `GET /v1/commodities/{indicator}` | `complete_history` |
|
|
31
|
+
| `announcement_changes` | `GET /v1/announcements/changes` | Not offset-paginated |
|
|
32
|
+
| `stream_events` | `GET /v1/stream/events` | Not offset-paginated |
|
|
33
|
+
| `reference_rates` | `GET /v1/fx/reference-rates/{base}/{quote}` | `complete_history` |
|
|
34
|
+
| `session_rates` | `GET /v1/fx/session-rates/{base}/{quote}` | `complete_history` |
|
|
35
|
+
| `prediction_coverage` | `GET /v1/predictions/coverage` | Not offset-paginated |
|
|
36
|
+
| `currency_prediction_coverage` | `GET /v1/predictions/coverage/{currency}` | Not offset-paginated |
|
|
37
|
+
| `currency_predictions` | `GET /v1/predictions/{currency}` | Not offset-paginated |
|
|
38
|
+
| `research_panel` | `POST /v1/research/panel` | Not offset-paginated |
|
|
39
|
+
| `mcp_ping` | `MCP /mcp` | Not offset-paginated |
|
|
40
|
+
| `mcp_mcp_capabilities` | `MCP /mcp` | Not offset-paginated |
|
|
41
|
+
| `mcp_mcp_auth_guide` | `MCP /mcp` | Not offset-paginated |
|
|
42
|
+
| `mcp_subscribe_for_mcp_access` | `MCP /mcp` | Not offset-paginated |
|
|
43
|
+
| `mcp_data_catalogue` | `MCP /mcp` | Not offset-paginated |
|
|
44
|
+
| `mcp_risk_sentiment` | `MCP /mcp` | Not offset-paginated |
|
|
45
|
+
| `mcp_macro_news` | `MCP /mcp` | Not offset-paginated |
|
|
46
|
+
| `mcp_release_calendar` | `MCP /mcp` | Not offset-paginated |
|
|
47
|
+
| `mcp_release_calendar_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
48
|
+
| `mcp_event_predictions` | `MCP /mcp` | Not offset-paginated |
|
|
49
|
+
| `mcp_latest_announcements` | `MCP /mcp` | Not offset-paginated |
|
|
50
|
+
| `mcp_announcement_changes` | `MCP /mcp` | Not offset-paginated |
|
|
51
|
+
| `mcp_press_releases` | `MCP /mcp` | Not offset-paginated |
|
|
52
|
+
| `mcp_macro_factor` | `MCP /mcp` | Not offset-paginated |
|
|
53
|
+
| `mcp_fx_reference_sources` | `MCP /mcp` | Not offset-paginated |
|
|
54
|
+
| `mcp_fx_reference_universe` | `MCP /mcp` | Not offset-paginated |
|
|
55
|
+
| `mcp_fx_intraday_reference_rates` | `MCP /mcp` | Not offset-paginated |
|
|
56
|
+
| `mcp_rate_curve` | `MCP /mcp` | Not offset-paginated |
|
|
57
|
+
| `mcp_rate_differentials` | `MCP /mcp` | Not offset-paginated |
|
|
58
|
+
| `mcp_latest_commodities` | `MCP /mcp` | Not offset-paginated |
|
|
59
|
+
| `mcp_forex` | `MCP /mcp` | Not offset-paginated |
|
|
60
|
+
| `mcp_seasonality` | `MCP /mcp` | Not offset-paginated |
|
|
61
|
+
| `mcp_indicator_query` | `MCP /mcp` | Not offset-paginated |
|
|
62
|
+
| `mcp_plot_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
63
|
+
| `mcp_indicator_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
64
|
+
| `mcp_forex_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
65
|
+
| `mcp_commodities_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
66
|
+
| `mcp_cot_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
67
|
+
| `mcp_policy_rate_differential_visual_artifact` | `MCP /mcp` | Not offset-paginated |
|
|
68
|
+
| `mcp_macro_briefing_task` | `MCP /mcp` | Not offset-paginated |
|
|
69
|
+
| `mcp_indicator_intel_task` | `MCP /mcp` | Not offset-paginated |
|
|
70
|
+
| `mcp_pair_intel_task` | `MCP /mcp` | Not offset-paginated |
|
|
71
|
+
| `mcp_macro_heatmap_task` | `MCP /mcp` | Not offset-paginated |
|
|
72
|
+
| `mcp_policy_scenario_modeler_task` | `MCP /mcp` | Not offset-paginated |
|
|
73
|
+
| `mcp_macro_war_room_task` | `MCP /mcp` | Not offset-paginated |
|
|
74
|
+
| `mcp_event_impact_replay_task` | `MCP /mcp` | Not offset-paginated |
|
|
75
|
+
| `mcp_quant_scenario_lab_task` | `MCP /mcp` | Not offset-paginated |
|
|
76
|
+
| `mcp_known_at_time_task` | `MCP /mcp` | Not offset-paginated |
|
|
77
|
+
| `mcp_macro_regime_classifier_task` | `MCP /mcp` | Not offset-paginated |
|
|
78
|
+
| `mcp_release_risk_score_task` | `MCP /mcp` | Not offset-paginated |
|
|
79
|
+
| `mcp_portfolio_risk_engine_task` | `MCP /mcp` | Not offset-paginated |
|
|
80
|
+
| `mcp_fx_trade_setup_task` | `MCP /mcp` | Not offset-paginated |
|
|
81
|
+
| `mcp_fx_backtest_task` | `MCP /mcp` | Not offset-paginated |
|
|
82
|
+
| `mcp_macro_research_pack_task` | `MCP /mcp` | Not offset-paginated |
|
|
83
|
+
| `mcp_prediction_coverage` | `MCP /mcp` | Not offset-paginated |
|
|
84
|
+
| `mcp_market_sessions` | `MCP /mcp` | Not offset-paginated |
|
|
85
|
+
| `mcp_cot_data` | `MCP /mcp` | Not offset-paginated |
|
|
86
|
+
| `mcp_commodities` | `MCP /mcp` | Not offset-paginated |
|
|
87
|
+
| `mcp_financial_prices` | `MCP /mcp` | Not offset-paginated |
|
|
88
|
+
| `mcp_official_dataset_family` | `MCP /mcp` | Not offset-paginated |
|
|
89
|
+
|
|
90
|
+
All tasks return `FXMacroDataResult` with the original payload, provenance and an additive
|
|
91
|
+
record view. No endpoint payload is replaced with a target-specific schema. MCP artefact
|
|
92
|
+
content is retained in the result for downstream tasks; this collection does not execute
|
|
93
|
+
embedded HTML or scripts. Streaming remains a finite capture with completion metadata.
|
|
94
|
+
|
|
95
|
+
[FXMacroData reference](https://fxmacrodata.com/documentation/reference?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=docs)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Robert Tidball
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
include CAPABILITIES.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include MANIFEST.in
|
|
4
|
+
include PUBLIC_FILES.json
|
|
5
|
+
include README.md
|
|
6
|
+
include pyproject.toml
|
|
7
|
+
include prefect_fxmacrodata/__init__.py
|
|
8
|
+
include prefect_fxmacrodata/credentials.py
|
|
9
|
+
include prefect_fxmacrodata/flows.py
|
|
10
|
+
include prefect_fxmacrodata/models.py
|
|
11
|
+
include prefect_fxmacrodata/tasks.py
|
|
12
|
+
include prefect_fxmacrodata/tasks.pyi
|
|
13
|
+
include prefect_fxmacrodata/py.typed
|
|
14
|
+
include tests/conftest.py
|
|
15
|
+
include tests/test_tasks.py
|
|
16
|
+
include tests/test_runtime.py
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prefect-fxmacrodata
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: FXMacroData subscription data in Prefect tasks and research flows
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://fxmacrodata.com/?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=readme
|
|
7
|
+
Project-URL: Subscribe, https://fxmacrodata.com/subscribe?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=subscribe
|
|
8
|
+
Project-URL: Documentation, https://fxmacrodata.com/documentation/reference?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=docs
|
|
9
|
+
Requires-Python: <3.15,>=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: prefect<4,>=3.9.1
|
|
13
|
+
Requires-Dist: fxmacrodata-public-client==0.1.1
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# FXMacroData for Prefect
|
|
17
|
+
|
|
18
|
+
Bring your FXMacroData subscription into scheduled Prefect research workflows:
|
|
19
|
+
cross-currency indicators, complete available histories, FX reference rates,
|
|
20
|
+
commodities, positioning and release analysis. Store your API key in a Prefect
|
|
21
|
+
Credentials Block and pass its name to native tasks.
|
|
22
|
+
|
|
23
|
+
**[Subscribe to FXMacroData](https://fxmacrodata.com/subscribe?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=subscribe)**
|
|
24
|
+
for subscriber coverage and deeper available history. Public USD catalogue,
|
|
25
|
+
recent indicator history and calendar access let you evaluate the workflow
|
|
26
|
+
before subscribing without an API key. Availability varies by dataset.
|
|
27
|
+
|
|
28
|
+
## Install and connect
|
|
29
|
+
|
|
30
|
+
Use Python 3.10–3.14 and Prefect 3.9.1 or later within version 3. From the release artifacts directory,
|
|
31
|
+
install the adapter wheel into the environment that runs your flows. Its pinned
|
|
32
|
+
FXMacroData public client is available on PyPI and resolves automatically:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
python -m pip install ./prefect_fxmacrodata-0.1.0-py3-none-any.whl
|
|
36
|
+
prefect block register -m prefect_fxmacrodata
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The adapter uses the supplied release artifact; its public-client dependency
|
|
40
|
+
comes from PyPI. Configure your Prefect server or Cloud workspace through Prefect's
|
|
41
|
+
normal setup. In **Blocks**, create an **FXMacroData Credentials** block, enter
|
|
42
|
+
your subscription API key and save it as `fxmacrodata-research`. The key uses
|
|
43
|
+
Prefect's secret-field storage. The timeout controls each HTTP request, in seconds.
|
|
44
|
+
|
|
45
|
+
To create the same block interactively without putting a key in source code:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from getpass import getpass
|
|
49
|
+
from pydantic import SecretStr
|
|
50
|
+
from prefect_fxmacrodata import FXMacroDataCredentials
|
|
51
|
+
|
|
52
|
+
FXMacroDataCredentials(
|
|
53
|
+
api_key=SecretStr(getpass("FXMacroData API key: ")),
|
|
54
|
+
).save("fxmacrodata-research")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Create the block during setup, outside a flow. Flows and tasks take only its name;
|
|
58
|
+
do not put keys in flow parameters, operation arguments or logs. Omitting
|
|
59
|
+
`credentials_block` explicitly uses public evaluation access, even if an API-key
|
|
60
|
+
environment variable is set.
|
|
61
|
+
|
|
62
|
+
## Build a research flow
|
|
63
|
+
|
|
64
|
+
`macro_snapshot` is a Prefect subflow that collects every available history page
|
|
65
|
+
for the selected series and retrieves its release calendar. Pass the typed
|
|
66
|
+
snapshot to your own downstream task:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import asyncio
|
|
70
|
+
from prefect import flow, task
|
|
71
|
+
from prefect_fxmacrodata import MacroSnapshot, macro_snapshot
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@task(persist_result=False)
|
|
75
|
+
def count_observations(snapshot: MacroSnapshot) -> int:
|
|
76
|
+
return len(snapshot.history.records())
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@flow(persist_result=False)
|
|
80
|
+
async def research_run():
|
|
81
|
+
snapshot = await macro_snapshot(
|
|
82
|
+
"EUR",
|
|
83
|
+
"policy_rate",
|
|
84
|
+
credentials_block="fxmacrodata-research",
|
|
85
|
+
start_date="2020-01-01",
|
|
86
|
+
end_date="2026-01-01",
|
|
87
|
+
)
|
|
88
|
+
return count_observations(snapshot)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
asyncio.run(research_run())
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
To evaluate with USD, omit the credentials and historical date range:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
snapshot = await macro_snapshot("USD", "policy_rate")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Subscriber history can extend beyond the public evaluation window where the
|
|
102
|
+
series supports it.
|
|
103
|
+
Deploy or schedule this flow with your normal Prefect work pool and deployment process.
|
|
104
|
+
The date filters select indicator history. The calendar uses the API's current
|
|
105
|
+
release-calendar window for the currency; it is not filtered to the historical
|
|
106
|
+
range or one indicator. Use the `release_calendar` task directly for different
|
|
107
|
+
calendar filters.
|
|
108
|
+
|
|
109
|
+
## Use individual operations
|
|
110
|
+
|
|
111
|
+
Every packaged operation is a named Prefect task, with normal task states,
|
|
112
|
+
dependencies, `with_options`, retries and scheduling through its enclosing flow.
|
|
113
|
+
Both REST and hosted MCP operations are available:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from prefect_fxmacrodata import operation_schemas
|
|
117
|
+
from prefect_fxmacrodata.tasks import indicator_history, mcp_macro_briefing_task
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async def inspect_series():
|
|
121
|
+
page = await indicator_history(
|
|
122
|
+
{"currency": "GBP", "indicator": "inflation", "limit": 100},
|
|
123
|
+
credentials_block="fxmacrodata-research",
|
|
124
|
+
)
|
|
125
|
+
briefing = await mcp_macro_briefing_task(
|
|
126
|
+
{"currency": "GBP"},
|
|
127
|
+
credentials_block="fxmacrodata-research",
|
|
128
|
+
)
|
|
129
|
+
return page, briefing
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
schemas = {operation.name: operation.input_schema for operation in operation_schemas()}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
See [CAPABILITIES.md](CAPABILITIES.md) for the exact operation inventory. The
|
|
136
|
+
original input schemas are available through `operation_schemas()` or the native
|
|
137
|
+
`discover_operations` task. `OPERATION_TASKS[name]` supports configuration-driven
|
|
138
|
+
flows without losing operation-specific task names.
|
|
139
|
+
|
|
140
|
+
Results are `FXMacroDataResult` models. `payload` retains the entire service
|
|
141
|
+
response, including original units, provenance, unavailable values and MCP
|
|
142
|
+
content; `source_url` records the source endpoint. `records()` adds a convenient
|
|
143
|
+
row view without replacing the payload. No publication timestamps or missing
|
|
144
|
+
observations are inferred.
|
|
145
|
+
|
|
146
|
+
## History and failure behavior
|
|
147
|
+
|
|
148
|
+
Individual operation tasks return a single response using the API's pagination
|
|
149
|
+
rules. Use `complete_history("indicator_history", arguments, credentials_block)`
|
|
150
|
+
for a complete available dataset within the requested filters. It starts at
|
|
151
|
+
offset zero, verifies contiguous pages and dataset versions when supplied, and
|
|
152
|
+
fails if completion cannot be established. Its payload retains every page's
|
|
153
|
+
metadata and returns rows in chronological order. `max_pages` is an explicit
|
|
154
|
+
safety budget; an error never passes an incomplete history off as complete.
|
|
155
|
+
Applications that need resumable storage can persist individual page responses
|
|
156
|
+
and control `offset` and `dataset_version` through the named operation tasks.
|
|
157
|
+
|
|
158
|
+
Event streaming is a bounded capture using `max_events` and `max_seconds`.
|
|
159
|
+
The response retains the original completion flag and reason. Cancellation
|
|
160
|
+
finishes the current bounded HTTP request, closes the client, and stops before
|
|
161
|
+
the next history page. MCP sessions are closed after each task.
|
|
162
|
+
|
|
163
|
+
Tasks disable result persistence and caching by default. Opt in only when the
|
|
164
|
+
destination and access controls suit your data licence. Task errors omit raw
|
|
165
|
+
responses, authenticated URLs and credentials. Transient retries are opt-in with
|
|
166
|
+
Prefect's `with_options(retries=..., retry_delay_seconds=...)`.
|
|
167
|
+
|
|
168
|
+
[FXMacroData API reference](https://fxmacrodata.com/documentation/reference?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=docs)
|
|
169
|
+
describes access requirements and supported arguments for each dataset.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"files": [
|
|
3
|
+
"CAPABILITIES.md",
|
|
4
|
+
"LICENSE",
|
|
5
|
+
"MANIFEST.in",
|
|
6
|
+
"PUBLIC_FILES.json",
|
|
7
|
+
"README.md",
|
|
8
|
+
"pyproject.toml",
|
|
9
|
+
"prefect_fxmacrodata/__init__.py",
|
|
10
|
+
"prefect_fxmacrodata/credentials.py",
|
|
11
|
+
"prefect_fxmacrodata/flows.py",
|
|
12
|
+
"prefect_fxmacrodata/models.py",
|
|
13
|
+
"prefect_fxmacrodata/tasks.py",
|
|
14
|
+
"prefect_fxmacrodata/tasks.pyi",
|
|
15
|
+
"prefect_fxmacrodata/py.typed",
|
|
16
|
+
"tests/conftest.py",
|
|
17
|
+
"tests/test_tasks.py",
|
|
18
|
+
"tests/test_runtime.py"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# FXMacroData for Prefect
|
|
2
|
+
|
|
3
|
+
Bring your FXMacroData subscription into scheduled Prefect research workflows:
|
|
4
|
+
cross-currency indicators, complete available histories, FX reference rates,
|
|
5
|
+
commodities, positioning and release analysis. Store your API key in a Prefect
|
|
6
|
+
Credentials Block and pass its name to native tasks.
|
|
7
|
+
|
|
8
|
+
**[Subscribe to FXMacroData](https://fxmacrodata.com/subscribe?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=subscribe)**
|
|
9
|
+
for subscriber coverage and deeper available history. Public USD catalogue,
|
|
10
|
+
recent indicator history and calendar access let you evaluate the workflow
|
|
11
|
+
before subscribing without an API key. Availability varies by dataset.
|
|
12
|
+
|
|
13
|
+
## Install and connect
|
|
14
|
+
|
|
15
|
+
Use Python 3.10–3.14 and Prefect 3.9.1 or later within version 3. From the release artifacts directory,
|
|
16
|
+
install the adapter wheel into the environment that runs your flows. Its pinned
|
|
17
|
+
FXMacroData public client is available on PyPI and resolves automatically:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m pip install ./prefect_fxmacrodata-0.1.0-py3-none-any.whl
|
|
21
|
+
prefect block register -m prefect_fxmacrodata
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The adapter uses the supplied release artifact; its public-client dependency
|
|
25
|
+
comes from PyPI. Configure your Prefect server or Cloud workspace through Prefect's
|
|
26
|
+
normal setup. In **Blocks**, create an **FXMacroData Credentials** block, enter
|
|
27
|
+
your subscription API key and save it as `fxmacrodata-research`. The key uses
|
|
28
|
+
Prefect's secret-field storage. The timeout controls each HTTP request, in seconds.
|
|
29
|
+
|
|
30
|
+
To create the same block interactively without putting a key in source code:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from getpass import getpass
|
|
34
|
+
from pydantic import SecretStr
|
|
35
|
+
from prefect_fxmacrodata import FXMacroDataCredentials
|
|
36
|
+
|
|
37
|
+
FXMacroDataCredentials(
|
|
38
|
+
api_key=SecretStr(getpass("FXMacroData API key: ")),
|
|
39
|
+
).save("fxmacrodata-research")
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Create the block during setup, outside a flow. Flows and tasks take only its name;
|
|
43
|
+
do not put keys in flow parameters, operation arguments or logs. Omitting
|
|
44
|
+
`credentials_block` explicitly uses public evaluation access, even if an API-key
|
|
45
|
+
environment variable is set.
|
|
46
|
+
|
|
47
|
+
## Build a research flow
|
|
48
|
+
|
|
49
|
+
`macro_snapshot` is a Prefect subflow that collects every available history page
|
|
50
|
+
for the selected series and retrieves its release calendar. Pass the typed
|
|
51
|
+
snapshot to your own downstream task:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
import asyncio
|
|
55
|
+
from prefect import flow, task
|
|
56
|
+
from prefect_fxmacrodata import MacroSnapshot, macro_snapshot
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@task(persist_result=False)
|
|
60
|
+
def count_observations(snapshot: MacroSnapshot) -> int:
|
|
61
|
+
return len(snapshot.history.records())
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@flow(persist_result=False)
|
|
65
|
+
async def research_run():
|
|
66
|
+
snapshot = await macro_snapshot(
|
|
67
|
+
"EUR",
|
|
68
|
+
"policy_rate",
|
|
69
|
+
credentials_block="fxmacrodata-research",
|
|
70
|
+
start_date="2020-01-01",
|
|
71
|
+
end_date="2026-01-01",
|
|
72
|
+
)
|
|
73
|
+
return count_observations(snapshot)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
asyncio.run(research_run())
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To evaluate with USD, omit the credentials and historical date range:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
snapshot = await macro_snapshot("USD", "policy_rate")
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Subscriber history can extend beyond the public evaluation window where the
|
|
87
|
+
series supports it.
|
|
88
|
+
Deploy or schedule this flow with your normal Prefect work pool and deployment process.
|
|
89
|
+
The date filters select indicator history. The calendar uses the API's current
|
|
90
|
+
release-calendar window for the currency; it is not filtered to the historical
|
|
91
|
+
range or one indicator. Use the `release_calendar` task directly for different
|
|
92
|
+
calendar filters.
|
|
93
|
+
|
|
94
|
+
## Use individual operations
|
|
95
|
+
|
|
96
|
+
Every packaged operation is a named Prefect task, with normal task states,
|
|
97
|
+
dependencies, `with_options`, retries and scheduling through its enclosing flow.
|
|
98
|
+
Both REST and hosted MCP operations are available:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from prefect_fxmacrodata import operation_schemas
|
|
102
|
+
from prefect_fxmacrodata.tasks import indicator_history, mcp_macro_briefing_task
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def inspect_series():
|
|
106
|
+
page = await indicator_history(
|
|
107
|
+
{"currency": "GBP", "indicator": "inflation", "limit": 100},
|
|
108
|
+
credentials_block="fxmacrodata-research",
|
|
109
|
+
)
|
|
110
|
+
briefing = await mcp_macro_briefing_task(
|
|
111
|
+
{"currency": "GBP"},
|
|
112
|
+
credentials_block="fxmacrodata-research",
|
|
113
|
+
)
|
|
114
|
+
return page, briefing
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
schemas = {operation.name: operation.input_schema for operation in operation_schemas()}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
See [CAPABILITIES.md](CAPABILITIES.md) for the exact operation inventory. The
|
|
121
|
+
original input schemas are available through `operation_schemas()` or the native
|
|
122
|
+
`discover_operations` task. `OPERATION_TASKS[name]` supports configuration-driven
|
|
123
|
+
flows without losing operation-specific task names.
|
|
124
|
+
|
|
125
|
+
Results are `FXMacroDataResult` models. `payload` retains the entire service
|
|
126
|
+
response, including original units, provenance, unavailable values and MCP
|
|
127
|
+
content; `source_url` records the source endpoint. `records()` adds a convenient
|
|
128
|
+
row view without replacing the payload. No publication timestamps or missing
|
|
129
|
+
observations are inferred.
|
|
130
|
+
|
|
131
|
+
## History and failure behavior
|
|
132
|
+
|
|
133
|
+
Individual operation tasks return a single response using the API's pagination
|
|
134
|
+
rules. Use `complete_history("indicator_history", arguments, credentials_block)`
|
|
135
|
+
for a complete available dataset within the requested filters. It starts at
|
|
136
|
+
offset zero, verifies contiguous pages and dataset versions when supplied, and
|
|
137
|
+
fails if completion cannot be established. Its payload retains every page's
|
|
138
|
+
metadata and returns rows in chronological order. `max_pages` is an explicit
|
|
139
|
+
safety budget; an error never passes an incomplete history off as complete.
|
|
140
|
+
Applications that need resumable storage can persist individual page responses
|
|
141
|
+
and control `offset` and `dataset_version` through the named operation tasks.
|
|
142
|
+
|
|
143
|
+
Event streaming is a bounded capture using `max_events` and `max_seconds`.
|
|
144
|
+
The response retains the original completion flag and reason. Cancellation
|
|
145
|
+
finishes the current bounded HTTP request, closes the client, and stops before
|
|
146
|
+
the next history page. MCP sessions are closed after each task.
|
|
147
|
+
|
|
148
|
+
Tasks disable result persistence and caching by default. Opt in only when the
|
|
149
|
+
destination and access controls suit your data licence. Task errors omit raw
|
|
150
|
+
responses, authenticated URLs and credentials. Transient retries are opt-in with
|
|
151
|
+
Prefect's `with_options(retries=..., retry_delay_seconds=...)`.
|
|
152
|
+
|
|
153
|
+
[FXMacroData API reference](https://fxmacrodata.com/documentation/reference?utm_source=github&utm_medium=referral&utm_campaign=prefect&utm_content=docs)
|
|
154
|
+
describes access requirements and supported arguments for each dataset.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""FXMacroData credentials, tasks and research flows for Prefect."""
|
|
2
|
+
|
|
3
|
+
from .credentials import FXMacroDataCredentials
|
|
4
|
+
from .flows import macro_snapshot
|
|
5
|
+
from .models import FXMacroDataResult, MacroSnapshot, OperationSchema
|
|
6
|
+
from .tasks import OPERATION_TASKS, complete_history, discover_operations, operation_schemas
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
__all__ = [
|
|
10
|
+
"FXMacroDataCredentials",
|
|
11
|
+
"FXMacroDataResult",
|
|
12
|
+
"MacroSnapshot",
|
|
13
|
+
"OperationSchema",
|
|
14
|
+
"OPERATION_TASKS",
|
|
15
|
+
"complete_history",
|
|
16
|
+
"discover_operations",
|
|
17
|
+
"macro_snapshot",
|
|
18
|
+
"operation_schemas",
|
|
19
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Reusable FXMacroData connection configuration for Prefect."""
|
|
2
|
+
|
|
3
|
+
from fxmacrodata_public import FXMacroDataClient
|
|
4
|
+
from prefect.blocks.core import Block
|
|
5
|
+
from pydantic import Field, SecretStr
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FXMacroDataCredentials(Block):
|
|
9
|
+
"""Store a subscriber's API key using Prefect's encrypted secret field.
|
|
10
|
+
|
|
11
|
+
Tasks take the saved Block name and load this configuration inside the run.
|
|
12
|
+
An empty key explicitly selects public evaluation access.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
_block_type_name = "FXMacroData Credentials"
|
|
16
|
+
_documentation_url = (
|
|
17
|
+
"https://fxmacrodata.com/documentation/reference?utm_source=github"
|
|
18
|
+
"&utm_medium=referral&utm_campaign=prefect&utm_content=docs"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
api_key: SecretStr = Field(
|
|
22
|
+
default_factory=lambda: SecretStr(""),
|
|
23
|
+
description="Your FXMacroData subscription API key; leave empty for USD evaluation.",
|
|
24
|
+
repr=False,
|
|
25
|
+
)
|
|
26
|
+
timeout: float = Field(default=30, ge=1, le=120, allow_inf_nan=False)
|
|
27
|
+
|
|
28
|
+
def get_client(self) -> FXMacroDataClient:
|
|
29
|
+
"""Create a bounded client; use it as a context manager."""
|
|
30
|
+
return FXMacroDataClient(api_key=self.api_key.get_secret_value(), timeout=self.timeout)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Research workflows composed from ordinary Prefect tasks."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
from prefect import flow
|
|
6
|
+
|
|
7
|
+
from .models import MacroSnapshot
|
|
8
|
+
from .tasks import OPERATION_TASKS, complete_history
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@flow(name="fxmacrodata-macro-snapshot", persist_result=False, log_prints=False)
|
|
12
|
+
async def macro_snapshot(
|
|
13
|
+
currency: str,
|
|
14
|
+
indicator: str,
|
|
15
|
+
credentials_block: str | None = None,
|
|
16
|
+
start_date: str | None = None,
|
|
17
|
+
end_date: str | None = None,
|
|
18
|
+
max_pages: int = 10000,
|
|
19
|
+
) -> MacroSnapshot:
|
|
20
|
+
"""Fetch complete available indicator history and the release calendar.
|
|
21
|
+
|
|
22
|
+
The caller chooses the currency and history range; calendar dates use the
|
|
23
|
+
API's current release-calendar window independently of the history range.
|
|
24
|
+
Original source fields,
|
|
25
|
+
values, publication timestamps and unavailable states are retained.
|
|
26
|
+
"""
|
|
27
|
+
arguments = {"currency": currency, "indicator": indicator}
|
|
28
|
+
if start_date is not None:
|
|
29
|
+
arguments["start_date"] = start_date
|
|
30
|
+
if end_date is not None:
|
|
31
|
+
arguments["end_date"] = end_date
|
|
32
|
+
history, calendar = await asyncio.gather(
|
|
33
|
+
complete_history("indicator_history", arguments, credentials_block, max_pages),
|
|
34
|
+
OPERATION_TASKS["release_calendar"]({"currency": currency}, credentials_block),
|
|
35
|
+
)
|
|
36
|
+
return MacroSnapshot(
|
|
37
|
+
currency=currency,
|
|
38
|
+
indicator=indicator,
|
|
39
|
+
history=history,
|
|
40
|
+
calendar=calendar,
|
|
41
|
+
source_urls=list(dict.fromkeys([history.source_url, calendar.source_url])),
|
|
42
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Typed envelopes that retain FXMacroData's original responses."""
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from fxmacrodata_public import Result
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FXMacroDataResult(BaseModel):
|
|
11
|
+
"""Original payload and provenance plus an additive row-oriented view."""
|
|
12
|
+
|
|
13
|
+
model_config = ConfigDict(frozen=True)
|
|
14
|
+
|
|
15
|
+
operation: str
|
|
16
|
+
payload: Any = Field(repr=False)
|
|
17
|
+
source_url: str
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def from_result(cls, result: Result) -> "FXMacroDataResult":
|
|
21
|
+
"""Copy a client result without changing values or metadata."""
|
|
22
|
+
return cls(
|
|
23
|
+
operation=result.operation,
|
|
24
|
+
payload=deepcopy(result.payload),
|
|
25
|
+
source_url=result.source_url,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def records(self) -> list[dict[str, Any]]:
|
|
29
|
+
"""Return the public client's additive record view."""
|
|
30
|
+
return Result(self.operation, self.payload, self.source_url).records()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class OperationSchema(BaseModel):
|
|
34
|
+
"""Discover a native task and its unchanged API argument schema."""
|
|
35
|
+
|
|
36
|
+
name: str
|
|
37
|
+
description: str
|
|
38
|
+
method: str
|
|
39
|
+
path: str
|
|
40
|
+
input_schema: dict[str, Any]
|
|
41
|
+
supports_complete_history: bool
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class MacroSnapshot(BaseModel):
|
|
45
|
+
"""History and scheduled releases for a research flow's next task."""
|
|
46
|
+
|
|
47
|
+
currency: str
|
|
48
|
+
indicator: str
|
|
49
|
+
history: FXMacroDataResult
|
|
50
|
+
calendar: FXMacroDataResult
|
|
51
|
+
source_urls: list[str] = Field(default_factory=list)
|
|
File without changes
|