Python traders often start with one of three backtesting styles: Backtrader for event-driven strategy development, vectorbt for fast vectorized experiments, and backtesting.py for compact OHLCV strategy tests. FXMacroData adds the macro event layer those frameworks do not provide out of the box.
https://api.fxmacrodata.com, normalizing them into timestamped features, and joining them to your OHLCV dataframe before the backtest. Use Backtrader for event-driven feeds, vectorbt for large parameter sweeps, and backtesting.py for small readable strategy tests.
The core idea is the same in every framework: price data is not enough. If a strategy trades through US CPI, Non-Farm Payrolls, central-bank decisions, or known liquidity windows, those events should be part of the test input.
Fit
Use this for
Macro-event filters, release-window tests, session features, and regime annotations in Python backtests.
Choose by workflow
Backtrader for event feeds, vectorbt for large sweeps, and backtesting.py for compact proof-of-concept tests.
Avoid
Changing macro inputs between runs without recording the source endpoint, export time, and snapshot file.
Which Framework Should You Use?
| Framework | Best for | FXMacroData pattern |
|---|---|---|
| Backtrader | Event-driven strategies, custom data feeds, analyzers, and broker-like simulation. | Load macro rows as an additional feed or dataframe column. |
| vectorbt | Vectorized experiments across many parameters, symbols, or windows. | Build boolean entry masks that exclude macro-risk windows. |
| backtesting.py | Readable OHLCV strategy prototypes with a small API surface. | Add macro columns to the dataframe before constructing the backtest. |
Workflow Shape
1. Export
Fetch calendar, announcement, session, or FX context from FXMacroData.
2. Normalize
Convert rows into timestamped features and event windows.
3. Join
Merge features into the OHLCV dataframe used by the backtester.
4. Compare
Run base, blocked-window, and sensitivity variants.
Step 1: Fetch and Normalize Macro Rows
Start with a small REST helper and a fixed export. Use production endpoints and query-parameter authentication.
import os
import requests
import pandas as pd
def fxmd(path: str, **params) -> dict:
params["api_key"] = os.environ["FXMD_API_KEY"]
url = f"https://api.fxmacrodata.com/v1{path}"
r = requests.get(url, params=params, timeout=20)
r.raise_for_status()
return r.json()
calendar = fxmd("/calendar/usd")
events = pd.DataFrame(calendar.get("events", []))
curl "https://api.fxmacrodata.com/v1/calendar/usd?api_key=YOUR_API_KEY"
curl "https://api.fxmacrodata.com/v1/announcements/usd/inflation?api_key=YOUR_API_KEY"
curl "https://api.fxmacrodata.com/v1/forex/eur/usd?api_key=YOUR_API_KEY"
Step 2: Join Events to OHLCV
Convert macro rows into features that the backtester can understand. A simple starting feature is a binary release window.
def add_macro_window(prices: pd.DataFrame, events: pd.DataFrame) -> pd.DataFrame:
prices = prices.copy()
prices["macro_window"] = False
for _, row in events.iterrows():
ts = pd.to_datetime(row["release_time"], utc=True)
start, end = ts - pd.Timedelta("60min"), ts + pd.Timedelta("30min")
prices.loc[(prices.index >= start) & (prices.index <= end), "macro_window"] = True
return prices
For richer studies, add event type, currency, surprise direction, session state, or a distance-to-event feature. Keep the first study simple enough to explain.
Step 3: Use the Feature in Each Framework
In vectorbt, the macro feature is a boolean mask around entries or exits.
import vectorbt as vbt
prices = add_macro_window(prices, events)
entries = (prices["fast_ma"] > prices["slow_ma"]) & ~prices["macro_window"]
exits = prices["fast_ma"] < prices["slow_ma"]
portfolio = vbt.Portfolio.from_signals(prices["close"], entries, exits)
print(portfolio.stats())
In backtesting.py, add the macro column to the dataframe before running the backtest, then read it inside the strategy.
from backtesting import Backtest, Strategy
class MacroBreakout(Strategy):
def next(self):
if self.data.macro_window[-1]:
return
if self.data.Close[-1] > self.data.Close[-20:].mean():
self.buy()
bt = Backtest(prices, MacroBreakout, cash=100000)
print(bt.run())
In Backtrader, you can either extend a data feed or pre-join the macro column into a Pandas feed. Use a dedicated custom feed when you need the event stream to behave like its own data source.
import backtrader as bt
class MacroPandasData(bt.feeds.PandasData):
lines = ("macro_window",)
params = (("macro_window", -1),)
data = MacroPandasData(dataname=prices)
cerebro = bt.Cerebro()
cerebro.adddata(data)
cerebro.run()
Optional AI Research Layer
An AI assistant can help explain strategy differences or generate first-pass code. Use FXMacroData MCP at https://mcp.fxmacrodata.com when the assistant host supports MCP, and keep the backtest input as fixed REST snapshots.
{
"servers": {
"FXMacroData": {
"type": "http",
"url": "https://mcp.fxmacrodata.com?api_key=YOUR_API_KEY"
}
}
}
Backtest Guardrails
Minimum controls
- Snapshot macro data for each test period.
- Use UTC internally for event windows.
- Compare base, filtered, and sensitivity-window variants.
- Record endpoint paths, export time, and file hashes.
- Never treat a backtest uplift as live trading permission.
Common Questions
Which Python backtesting framework is best for FXMacroData?
Use Backtrader when you want event-driven feeds, vectorbt when you need fast parameter sweeps, and backtesting.py when you want a compact readable prototype.
Should macro data be loaded live during a backtest?
No. Export a fixed macro snapshot first, then join it to the price data. That makes the test reproducible.
Can FXMacroData provide the price candles?
FXMacroData provides macro and FX context. Use your chosen market-data source for OHLCV candles, then join FXMacroData event features before running the backtest.
Sources