Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/AI_AGENT_BUILTIN_TOOLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ FRED macro tools:

Built-in FRED tools require `FRED_API_KEY` so Lumibot can request official FRED/ALFRED observations with `realtime_start` and `realtime_end`. Lumibot does not use public CSV fallbacks for macro data, because those endpoints can contain revised values and are not a safe default for historical simulations.

FXMacroData tools:

- `list_fxmacrodata_indicators`
- `get_fxmacrodata_series`
- `get_fxmacrodata_latest`
- `get_fxmacrodata_snapshot`

FXMacroData tools fetch FX-focused macro announcement rows from FXMacroData. USD announcement data is public. Set `FXMD_API_KEY` or `FXMACRODATA_API_KEY` for non-USD and paid endpoint access. Lumibot sends the key as an `X-API-Key` header rather than adding it to request URLs.

Memory tools:

- `remember`
Expand Down
2 changes: 1 addition & 1 deletion docs/AI_TRADING_AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ if __name__ == "__main__":
)
```

The agent gets Lumibot's built-in `get_fred_series` tool automatically when `FRED_API_KEY` is configured. During backtests the tool defaults `as_of` to the strategy datetime and uses FRED/ALFRED realtime parameters, so the agent does not see future macro revisions.
The agent gets Lumibot's built-in macro tools automatically. `get_fred_series` is exposed when `FRED_API_KEY` is configured and uses FRED/ALFRED realtime parameters during backtests. FXMacroData tools such as `get_fxmacrodata_series` are also available for FX-focused macro announcement rows; set `FXMD_API_KEY` or `FXMACRODATA_API_KEY` for non-USD access.

No local MCP server scripts. No npm installs. No explicit built-in tool lists. Lumibot includes all built-in tools by default, and you can add custom `@agent_tool` functions when you need proprietary APIs or special research logic.

Expand Down
18 changes: 18 additions & 0 deletions docs/ENV_VARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,24 @@ Notes:
- Purpose: Override the local FRED macro data cache.
- Default: `~/.lumibot/cache/fred`.

### `FXMD_API_KEY`
- Purpose: Optional FXMacroData API key for non-USD and paid macro announcement endpoints.
- Default: unset.
- Notes: Lumibot sends this key as an `X-API-Key` header. `FXMACRODATA_API_KEY` is also accepted. USD announcement data can be fetched without a key.

### `FXMACRODATA_API_KEY`
- Purpose: Alternate environment variable for the FXMacroData API key.
- Default: unset.
- Notes: Used when `FXMD_API_KEY` is not set.

### `LUMIBOT_FXMACRODATA_API_BASE_URL`
- Purpose: Override the FXMacroData API base URL.
- Default: `https://api.fxmacrodata.com/v1`.

### `LUMIBOT_FXMACRODATA_CACHE_DIR`
- Purpose: Override the local FXMacroData macro release cache.
- Default: `~/.lumibot/cache/fxmacrodata`.

### `LUMIBOT_MEMORY_DIR`
- Purpose: Override the local SQLite agent memory root.
- Default: `.lumibot/memory` under the current working directory.
Expand Down
34 changes: 34 additions & 0 deletions docs/FRED_MACRO_DATA.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,37 @@ export LUMIBOT_FRED_CACHE_DIR=/path/to/cache
```

Backtests should fetch each series once and reuse the local cache instead of hitting FRED on every trading iteration.

## FXMacroData Macro Releases

Lumibot also includes an FXMacroData provider for FX-focused macro announcement rows:

```python
self.macro.fxmacrodata.list_indicators()
self.macro.fxmacrodata.get_series("eur", "inflation")
self.macro.fxmacrodata.get_latest("jpy", "policy_rate")
self.macro.fxmacrodata.get_snapshot("gbp", ["inflation", "policy_rate", "unemployment"])
```

Agents receive these read-only built-ins automatically:

- `list_fxmacrodata_indicators`
- `get_fxmacrodata_series`
- `get_fxmacrodata_latest`
- `get_fxmacrodata_snapshot`

USD announcement data is public. Set `FXMD_API_KEY` or `FXMACRODATA_API_KEY` for non-USD and paid endpoint access. Lumibot sends the key as an `X-API-Key` header, not as an `api_key` query parameter.

In a backtest, `as_of` defaults to `self.get_datetime()`. Lumibot filters release rows by `announcement_datetime` so the strategy does not see macro releases after the simulated datetime.

FXMacroData responses are cached under:

```text
~/.lumibot/cache/fxmacrodata
```

Override with:

```bash
export LUMIBOT_FXMACRODATA_CACHE_DIR=/path/to/cache
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
2 changes: 1 addition & 1 deletion docsrc/agents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Here is a complete AI trading agent strategy that uses Lumibot's built-in FRED m
benchmark_asset="SPY",
)

That is the entire strategy file. No local MCP server scripts, no npm installs, and no explicit built-in tool lists. LumiBot includes built-in tools by default, including ``get_fred_series`` when ``FRED_API_KEY`` is configured.
That is the entire strategy file. No local MCP server scripts, no npm installs, and no explicit built-in tool lists. LumiBot includes built-in tools by default, including ``get_fred_series`` when ``FRED_API_KEY`` is configured and FXMacroData tools such as ``get_fxmacrodata_series`` for FX-focused macro announcement rows.

How ``@agent_tool`` Works
-------------------------
Expand Down
14 changes: 14 additions & 0 deletions docsrc/agents_builtin_tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ using realtime parameters. LumiBot's built-in FRED tools do not use public CSV
fallbacks; macro tool output should either come from the official API or fail
clearly.

FXMacroData
-----------

FXMacroData tools expose FX-focused macro announcement rows to agents:

- ``list_fxmacrodata_indicators``
- ``get_fxmacrodata_series``
- ``get_fxmacrodata_latest``
- ``get_fxmacrodata_snapshot``

USD announcement data is public. Set ``FXMD_API_KEY`` or
``FXMACRODATA_API_KEY`` for non-USD and paid endpoint access. LumiBot sends the
key as an ``X-API-Key`` header rather than adding it to request URLs.

News
----

Expand Down
29 changes: 29 additions & 0 deletions docsrc/environment_variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,35 @@ LUMIBOT_FRED_CACHE_DIR
- Purpose: Override local FRED macro data cache.
- Default: ``~/.lumibot/cache/fred``.

FXMD_API_KEY
^^^^^^^^^^^^

- Purpose: Optional FXMacroData API key for non-USD and paid macro announcement
endpoints.
- Default: unset.
- Notes: LumiBot sends this key as an ``X-API-Key`` header.
``FXMACRODATA_API_KEY`` is also accepted. USD announcement data can be fetched
without a key.

FXMACRODATA_API_KEY
^^^^^^^^^^^^^^^^^^^

- Purpose: Alternate environment variable for the FXMacroData API key.
- Default: unset.
- Notes: Used when ``FXMD_API_KEY`` is not set.

LUMIBOT_FXMACRODATA_API_BASE_URL
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Purpose: Override the FXMacroData API base URL.
- Default: ``https://api.fxmacrodata.com/v1``.

LUMIBOT_FXMACRODATA_CACHE_DIR
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Purpose: Override local FXMacroData macro release cache.
- Default: ``~/.lumibot/cache/fxmacrodata``.

LUMIBOT_MEMORY_DIR
^^^^^^^^^^^^^^^^^^

Expand Down
31 changes: 31 additions & 0 deletions docsrc/macro_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,34 @@ Cache

FRED data is cached under ``~/.lumibot/cache/fred`` by default. Override this
with ``LUMIBOT_FRED_CACHE_DIR``.

FXMacroData Macro Releases
==========================

LumiBot also includes an FXMacroData provider for FX-focused macro announcement
rows:

.. code-block:: python

self.macro.fxmacrodata.list_indicators()
self.macro.fxmacrodata.get_series("eur", "inflation")
self.macro.fxmacrodata.get_latest("jpy", "policy_rate")
self.macro.fxmacrodata.get_snapshot("gbp", ["inflation", "policy_rate", "unemployment"])

Agents receive these read-only built-ins automatically:

- ``list_fxmacrodata_indicators``
- ``get_fxmacrodata_series``
- ``get_fxmacrodata_latest``
- ``get_fxmacrodata_snapshot``

USD announcement data is public. Set ``FXMD_API_KEY`` or
``FXMACRODATA_API_KEY`` for non-USD and paid endpoint access. LumiBot sends the
key as an ``X-API-Key`` header, not as an ``api_key`` query parameter.

In a backtest, ``as_of`` defaults to ``self.get_datetime()``. LumiBot filters
release rows by ``announcement_datetime`` so the strategy does not see macro
releases after the simulated datetime.

FXMacroData responses are cached under ``~/.lumibot/cache/fxmacrodata`` by
default. Override this with ``LUMIBOT_FXMACRODATA_CACHE_DIR``.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
123 changes: 123 additions & 0 deletions lumibot/components/agents/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,97 @@ def get_fred_snapshot(series_ids: list[str] | str, as_of: str | None = None) ->
)


def _fxmacrodata_client(strategy: Any) -> Any:
macro = getattr(strategy, "macro", None)
client = getattr(macro, "fxmacrodata", None) or getattr(macro, "fxmd", None)
if client is None:
raise ValueError("FXMacroData is not configured on strategy.macro.")
return client


def _bind_list_fxmacrodata_indicators(strategy: Any, manager: Any) -> BoundTool:
def list_fxmacrodata_indicators(category: str | None = None) -> dict[str, Any]:
return _fxmacrodata_client(strategy).list_indicators(category=category)

return BoundTool(
name="list_fxmacrodata_indicators",
description=(
"List common FXMacroData macro announcement indicators for FX-focused event-risk research. "
"Use this before requesting inflation, policy-rate, labor, growth, trade, or sentiment series."
),
function=list_fxmacrodata_indicators,
source="builtin",
metadata={"kind": "macro", "cache_scope": "strategy_day"},
)


def _bind_get_fxmacrodata_series(strategy: Any, manager: Any) -> BoundTool:
def get_fxmacrodata_series(
currency: str,
indicator: str,
start: str | None = None,
end: str | None = None,
as_of: str | None = None,
limit: int | None = None,
) -> dict[str, Any]:
return _fxmacrodata_client(strategy).get_series(
currency,
indicator,
start=start,
end=end,
as_of=as_of,
limit=limit,
)

return BoundTool(
name="get_fxmacrodata_series",
description=(
"Get an FXMacroData macro announcement series for a currency and indicator. "
"In backtests, as_of defaults to the strategy datetime and release rows are gated by announcement time. "
"USD is public; set FXMD_API_KEY or FXMACRODATA_API_KEY for non-USD and paid endpoint access."
),
function=get_fxmacrodata_series,
source="builtin",
metadata={"kind": "macro", "cache_scope": "strategy_day"},
)


def _bind_get_fxmacrodata_latest(strategy: Any, manager: Any) -> BoundTool:
def get_fxmacrodata_latest(currency: str, indicator: str, as_of: str | None = None) -> dict[str, Any]:
return _fxmacrodata_client(strategy).get_latest(currency, indicator, as_of=as_of)

return BoundTool(
name="get_fxmacrodata_latest",
description=(
"Get the latest FXMacroData release row for a currency and indicator available as of the strategy datetime "
"or explicit as_of timestamp."
),
function=get_fxmacrodata_latest,
source="builtin",
metadata={"kind": "macro", "cache_scope": "strategy_day"},
)


def _bind_get_fxmacrodata_snapshot(strategy: Any, manager: Any) -> BoundTool:
def get_fxmacrodata_snapshot(
currency: str,
indicators: list[str] | str,
as_of: str | None = None,
) -> dict[str, Any]:
return _fxmacrodata_client(strategy).get_snapshot(currency, indicators, as_of=as_of)

return BoundTool(
name="get_fxmacrodata_snapshot",
description=(
"Get latest FXMacroData release rows for several indicators in one currency. "
"Pass indicators as a list or comma-separated string such as inflation,policy_rate,unemployment."
),
function=get_fxmacrodata_snapshot,
source="builtin",
metadata={"kind": "macro", "cache_scope": "strategy_day"},
)


def _bind_notify_user(strategy: Any, manager: Any) -> BoundTool:
def notify_user(title: str, message: str, severity: str = "info", enabled: bool | None = None) -> dict[str, Any]:
results = strategy.notify(title, message, severity=severity, enabled=enabled)
Expand Down Expand Up @@ -1554,6 +1645,34 @@ def get_fred_latest(self) -> ToolDefinition:
def get_fred_snapshot(self) -> ToolDefinition:
return ToolDefinition(name="get_fred_snapshot", description="Get a multi-series FRED macro snapshot.", binder=_bind_get_fred_snapshot)

def list_fxmacrodata_indicators(self) -> ToolDefinition:
return ToolDefinition(
name="list_fxmacrodata_indicators",
description="List common FXMacroData announcement indicators.",
binder=_bind_list_fxmacrodata_indicators,
)

def get_fxmacrodata_series(self) -> ToolDefinition:
return ToolDefinition(
name="get_fxmacrodata_series",
description="Get an FXMacroData macro announcement series.",
binder=_bind_get_fxmacrodata_series,
)

def get_fxmacrodata_latest(self) -> ToolDefinition:
return ToolDefinition(
name="get_fxmacrodata_latest",
description="Get the latest FXMacroData macro release row.",
binder=_bind_get_fxmacrodata_latest,
)

def get_fxmacrodata_snapshot(self) -> ToolDefinition:
return ToolDefinition(
name="get_fxmacrodata_snapshot",
description="Get a multi-indicator FXMacroData macro snapshot.",
binder=_bind_get_fxmacrodata_snapshot,
)


class _NotificationTools:
def notify_user(self) -> ToolDefinition:
Expand Down Expand Up @@ -1662,6 +1781,10 @@ def all(self) -> list[ToolDefinition]:
self.macro.get_fred_series(),
self.macro.get_fred_latest(),
self.macro.get_fred_snapshot(),
self.macro.list_fxmacrodata_indicators(),
self.macro.get_fxmacrodata_series(),
self.macro.get_fxmacrodata_latest(),
self.macro.get_fxmacrodata_snapshot(),
self.notifications.notify_user(),
self.memory.remember(),
self.memory.search(),
Expand Down
4 changes: 4 additions & 0 deletions lumibot/components/agents/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,10 @@ def _derive_warnings(self, result: AgentRunResult, runtime_context: dict[str, An
"get_fred_series",
"get_fred_latest",
"get_fred_snapshot",
"list_fxmacrodata_indicators",
"get_fxmacrodata_series",
"get_fxmacrodata_latest",
"get_fxmacrodata_snapshot",
}
for name in tool_names
)
Expand Down
7 changes: 7 additions & 0 deletions lumibot/components/agents/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,13 @@ def _build_user_text(self, request: RuntimeRequest) -> str:
fred_tools = sorted(name for name in tool_names if name.startswith("get_fred_") or name == "list_fred_series")
if fred_tools:
required_categories.append(" or ".join(fred_tools))
fxmacrodata_tools = sorted(
name
for name in tool_names
if name.startswith("get_fxmacrodata_") or name == "list_fxmacrodata_indicators"
)
if fxmacrodata_tools:
required_categories.append(" or ".join(fxmacrodata_tools))
required_categories.extend(
[
"get_income_statement, get_balance_sheet, get_cash_flow, or get_company_facts",
Expand Down
4 changes: 3 additions & 1 deletion lumibot/macro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Per-strategy macroeconomic data helpers."""

from .fred import FREDMacroData
from .fxmacrodata import FXMacroData
from .macro_data import MacroData

__all__ = ["FREDMacroData"]
__all__ = ["FREDMacroData", "FXMacroData", "MacroData"]
Loading