From fa2c4e6c022d4c60dabfa7d4eb0ed83ab6b6a2af Mon Sep 17 00:00:00 2001 From: Robert Tidball Date: Wed, 8 Jul 2026 19:55:58 +1000 Subject: [PATCH] Add FXMacroData macro calendar integration --- src/helpers/fxmacrodata.ts | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/helpers/fxmacrodata.ts diff --git a/src/helpers/fxmacrodata.ts b/src/helpers/fxmacrodata.ts new file mode 100644 index 0000000..cfeceae --- /dev/null +++ b/src/helpers/fxmacrodata.ts @@ -0,0 +1,66 @@ +import axios from "axios"; + +export interface FXMacroDataCalendarEvent { + announcement_datetime_utc?: string; + announcement_datetime_local?: string; + release?: string; + name?: string; + market_tier?: number; + top_tier_for_currency?: boolean; + actual?: number | string | null; + previous?: number | string | null; + consensus?: number | string | null; + [key: string]: unknown; +} + +export interface FXMacroDataCalendarOptions { + currency?: string; + startDate?: string; + endDate?: string; + apiKey?: string; + baseUrl?: string; + topTierOnly?: boolean; +} + +export async function fetchFXMacroDataCalendar( + options: FXMacroDataCalendarOptions = {} +): Promise { + const { + currency = "usd", + startDate, + endDate, + apiKey = process.env.FXMD_API_KEY, + baseUrl = "https://fxmacrodata.com/api/v1", + topTierOnly = false, + } = options; + + const response = await axios.get(`${baseUrl.replace(/\/$/, "")}/calendar/${currency.toLowerCase()}`, { + headers: { Accept: "application/json" }, + params: { + ...(apiKey ? { api_key: apiKey } : {}), + ...(startDate ? { start_date: startDate } : {}), + ...(endDate ? { end_date: endDate } : {}), + }, + timeout: 30000, + }); + + const rows = Array.isArray(response.data?.data) ? response.data.data : []; + if (!topTierOnly) return rows; + return rows.filter((row: FXMacroDataCalendarEvent) => row.top_tier_for_currency || row.market_tier === 1); +} + +export function hasFXMacroDataEventNear( + events: FXMacroDataCalendarEvent[], + timestamp: Date, + beforeMs = 4 * 60 * 60 * 1000, + afterMs = 2 * 60 * 60 * 1000 +): boolean { + const ts = timestamp.getTime(); + return events.some((event) => { + const value = event.announcement_datetime_utc || event.announcement_datetime_local; + if (!value) return false; + const eventTs = new Date(value).getTime(); + return eventTs - beforeMs <= ts && ts <= eventTs + afterMs; + }); +} +