Cómo configurar alertas de macros con FXMacroData y Webhooks banner image

Implementation

How-To Guides

Cómo configurar alertas de macros con FXMacroData y Webhooks

Construye un sistema de alerta macro confiable utilizando la encuesta FXMacroData y la entrega webhook.

Disponible también en English

Las publicaciones de datos macro se encuentran entre los catalizadores más confiables en los mercados de divisas. Una impresión del IPC del 0.2% por encima del consenso puede enviar un deslizamiento del EUR/USD de 60 pips antes de que el titular de las noticias se cargue. Si su sistema de alerta se basa en comprobaciones manuales del calendario o encuestas basadas en un amplio temporizador, ya está atrasado. Esta guía le muestra cómo construir una tubería de alertas precisa y basada en webhook que detecta nuevas publicaciones FXMacroData en el momento en que aparecen y entrega notificaciones a Slack, Discord o cualquier punto final HTTP todo en menos de 80 líneas de Python.

Lo que construirás

  • Un ciclo de votación que comprueba el punto final de anuncios de FXMacroData en un intervalo configurable y detecta valores publicados recientemente
  • Un despachador de webhook que dispara un POST HTTP a Slack, Discord o un punto final personalizado cada vez que se detecta una nueva versión
  • Una alerta previa del calendario de lanzamiento que te avisa minutos antes de que un evento de alto impacto se debe así que estás listo antes de la impresión de números
  • Persistencia del estado usando un archivo JSON ligero para que el bot nunca vuelva a disparar la misma alerta en reinicios

Los requisitos previos

  • Python 3.9+
  • La clave de la API de FXMacroData inscribirse en / suscribirse y copia tu llave del tablero de instrumentos
  • Una URL de webhook crear un Slack webhook entrante en Aplicación de las instrucciones de acceso, o agarra un canal de Discord en el sub Configuración → Integraciones → Webhooks
  • Paquetes de Python¿ Qué ? requests¿ Qué ? schedule
pip install requests schedule

Almacenar todas las credenciales como variables de entorno nunca claves de código duro en archivos fuente:

export FXMACRO_API_KEY="YOUR_FXMACRODATA_KEY"
export WEBHOOK_URL="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
¿Por qué las encuestas y los ganchos?

Encuestas frente a presiones: elegir el patrón correcto

Las suscripciones puras de webhook requieren un punto final de servidor público y un proveedor de datos que envía notificaciones salientes. circuito de votación ligero (su código le pide a la API periódicamente) con un Dispatcher de conexión web (su código empuja el resultado río abajo en el momento en que aparece algo nuevo).

Esto le da la fiabilidad de los datos basados en pull (sin empujones perdidos si su servidor está caído) con la inmediatez de la entrega de webhook a las herramientas que su equipo ya utiliza Slack, Discord, PagerDuty, n8n, o cualquier objetivo HTTP.


- ¿ Qué pasa ?

Paso 1 Obtener el valor de anuncio más reciente

El Anuncios punto final devuelve el valor más reciente publicado para cualquier indicador y moneda. announcement_datetime una marca de tiempo UTC de segundo nivel que le indica exactamente cuándo se publicó este valor. Utilizará esta marca de hora como clave de deduplicación: si ha cambiado desde su última comprobación, se ha impreso una nueva versión.

import os
import requests

BASE_URL = "https://fxmacrodata.com/api/v1"
API_KEY  = os.environ["FXMACRO_API_KEY"]


def fetch_latest(currency: str, indicator: str) -> dict | None:
    """Return the most recent announcement record, or None on failure."""
    try:
        resp = requests.get(
            f"{BASE_URL}/announcements/{currency}/{indicator}",
            params={"api_key": API_KEY},
            timeout=10,
        )
        resp.raise_for_status()
        data = resp.json().get("data", [])
        return data[0] if data else None
    except requests.RequestException as exc:
        print(f"[WARN] fetch failed for {currency}/{indicator}: {exc}")
        return None

Una muestra de respuesta se ve como:

{
  "date": "2026-04-02",
  "val": 4.35,
  "prior": 4.10,
  "announcement_datetime": "2026-04-02T02:30:00Z",
  "currency": "aud",
  "indicator": "policy_rate"
}
- ¿ Qué pasa ?

Paso 2 Estado de seguimiento para evitar duplicaciones de alertas

Si reinicia el proceso, no debe volver a disparar alertas de versiones que ya haya visto. announcement_datetime Para cada indicador observado en un simple archivo JSON. Al iniciar el bot carga este archivo; después de cada nueva alerta escribe la marca de tiempo actualizada.

import json
from pathlib import Path

STATE_FILE = Path("alert_state.json")


def load_state() -> dict:
    if STATE_FILE.exists():
        return json.loads(STATE_FILE.read_text())
    return {}


def save_state(state: dict) -> None:
    STATE_FILE.write_text(json.dumps(state, indent=2))


def is_new_release(state: dict, key: str, record: dict) -> bool:
    """Return True if the announcement_datetime is newer than what we last saw."""
    last_seen = state.get(key)
    current   = record.get("announcement_datetime")
    return current is not None and current != last_seen
- ¿ Qué pasa ?

Paso 3 Enviar una notificación de webhook

Tanto los webhooks entrantes de Slack como los web hooks de Discord aceptan un POST HTTP con una carga útil JSON. La función de abajo construye un mensaje formateado y lo envía. text El campo de discordia utiliza contentEl ayudante se adapta automáticamente basado en el prefijo de la URL.

def send_webhook(webhook_url: str, record: dict, currency: str, indicator: str) -> None:
    """POST a formatted macro-alert message to a Slack or Discord webhook."""
    value    = record.get("val")
    prior    = record.get("prior")
    dt       = record.get("announcement_datetime", "")
    ccy      = currency.upper()
    ind      = indicator.replace("_", " ").title()

    lines = [
        f"📣  *{ccy} {ind}* just printed",
        f"  Value : *{value}*   |   Prior: {prior}",
        f"  Released: {dt}",
    ]
    message = "\n".join(lines)

    # Discord uses "content", Slack uses "text"
    if "discord.com" in webhook_url:
        payload = {"content": message.replace("*", "**")}
    else:
        payload = {"text": message}

    try:
        resp = requests.post(webhook_url, json=payload, timeout=10)
        resp.raise_for_status()
        print(f"[OK] alert sent for {ccy} {ind}")
    except requests.RequestException as exc:
        print(f"[ERROR] webhook delivery failed: {exc}")

Consejo: objetivos HTTP personalizados

Lo mismo . send_webhook Función funciona con cualquier punto final HTTP que acepte POST n8n flujos de trabajo de automatización, escenarios Make (Integromat), APIs de eventos PagerDuty, o su propio receptor Flask / FastAPI. WEBHOOK_URL a la URL de destino y ajustar la forma de la carga útil.

- ¿ Qué pasa ?

Paso 4 Observar varios indicadores en un ciclo de encuestas

Define los pares de divisas/indicadores que te interesan y ejecuta la comprobación en intervalos regulares. schedule La biblioteca hace esto sencillo sin un daemon cron.

import schedule
import time

WEBHOOK_URL = os.environ["WEBHOOK_URL"]

# Pairs to monitor — add or remove as needed
WATCHLIST = [
    ("usd", "policy_rate"),
    ("usd", "inflation"),
    ("usd", "non_farm_payrolls"),
    ("eur", "policy_rate"),
    ("eur", "inflation"),
    ("aud", "policy_rate"),
    ("gbp", "policy_rate"),
]


def check_all(state: dict) -> None:
    for currency, indicator in WATCHLIST:
        key    = f"{currency}/{indicator}"
        record = fetch_latest(currency, indicator)
        if record and is_new_release(state, key, record):
            send_webhook(WEBHOOK_URL, record, currency, indicator)
            state[key] = record["announcement_datetime"]
            save_state(state)


def main():
    state = load_state()
    # Run immediately on start, then every 5 minutes
    check_all(state)
    schedule.every(5).minutes.do(check_all, state=state)
    while True:
        schedule.run_pending()
        time.sleep(30)


if __name__ == "__main__":
    main()

Ejecuta el bot desde tu terminal:

python macro_alert_bot.py

La primera ronda se llena . alert_state.json Con los valores actuales más recientes, el futuro sólo corre fuego cuando aparece algo genuinamente nuevo.

- ¿ Qué pasa ?

Paso 5 Añadir alertas de cuenta regresiva antes de la publicación

Saber que una liberación ha ocurrido es útil; saberlo es Está a punto de suceder. Es valioso. punto final del calendario de liberación expone el programa announcement_datetime Para los eventos futuros, incluyendo los valores de consenso esperados.

from datetime import datetime, timezone, timedelta

LEAD_MINUTES = 10   # fire a pre-alert this many minutes before the release


def fetch_calendar(currency: str) -> list[dict]:
    try:
        resp = requests.get(
            f"{BASE_URL}/calendar/{currency}",
            params={"api_key": API_KEY},
            timeout=10,
        )
        resp.raise_for_status()
        return resp.json().get("data", [])
    except requests.RequestException as exc:
        print(f"[WARN] calendar fetch failed for {currency}: {exc}")
        return []


def check_upcoming(state: dict) -> None:
    now = datetime.now(tz=timezone.utc)
    for currency, _ in WATCHLIST:
        for event in fetch_calendar(currency):
            scheduled = event.get("announcement_datetime")
            if not scheduled:
                continue
            try:
                event_dt = datetime.fromisoformat(scheduled.replace("Z", "+00:00"))
            except ValueError:
                continue
            # Fire pre-alert if the event is within the lead window and not yet fired
            pre_key = f"pre:{currency}/{event.get('indicator')}:{scheduled}"
            delta   = event_dt - now
            if timedelta(0) < delta <= timedelta(minutes=LEAD_MINUTES):
                if pre_key not in state:
                    send_pre_alert(WEBHOOK_URL, event, currency, delta)
                    state[pre_key] = True
                    save_state(state)


def send_pre_alert(webhook_url: str, event: dict, currency: str, delta: timedelta) -> None:
    ccy      = currency.upper()
    ind      = event.get("indicator", "").replace("_", " ").title()
    expected = event.get("expected")
    prior    = event.get("prior")
    mins     = int(delta.total_seconds() / 60)

    lines = [
        f"⏰  *{ccy} {ind}* due in ~{mins} min",
        f"  Expected: {expected}   |   Prior: {prior}",
    ]
    message = "\n".join(lines)
    if "discord.com" in webhook_url:
        payload = {"content": message.replace("*", "**")}
    else:
        payload = {"text": message}
    try:
        resp = requests.post(webhook_url, json=payload, timeout=10)
        resp.raise_for_status()
        print(f"[OK] pre-alert sent for {ccy} {ind}")
    except requests.RequestException as exc:
        print(f"[ERROR] pre-alert delivery failed: {exc}")

Añadir check_upcoming a la agenda de votación junto con check_all¿ Qué ?

def main():
    state = load_state()
    check_all(state)
    check_upcoming(state)
    schedule.every(5).minutes.do(check_all,      state=state)
    schedule.every(5).minutes.do(check_upcoming, state=state)
    while True:
        schedule.run_pending()
        time.sleep(30)
- ¿ Qué pasa ?

Paso 6 Implementar como servicio de larga duración

Para uso en producción, querrá que el bot se ejecute continuamente sin una sesión de terminal.

Opción A unidad de sistema (servidor Linux / VPS)

# /etc/systemd/system/macro-alert-bot.service
[Unit]
Description=FXMacroData Alert Bot
After=network.target

[Service]
Type=simple
User=youruser
WorkingDirectory=/opt/macro-alert-bot
ExecStart=/opt/macro-alert-bot/.venv/bin/python macro_alert_bot.py
Restart=always
RestartSec=30
Environment="FXMACRO_API_KEY=YOUR_FXMACRODATA_KEY"
Environment="WEBHOOK_URL=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now macro-alert-bot

Opción B Contenedor Docker

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY macro_alert_bot.py .
CMD ["python", "macro_alert_bot.py"]
docker build -t macro-alert-bot .
docker run -d --name macro-alert-bot --restart unless-stopped \
  -e FXMACRO_API_KEY="YOUR_FXMACRODATA_KEY" \
  -e WEBHOOK_URL="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK" \
  macro-alert-bot

Está llena . requirements.txt

requests>=2.31
schedule>=1.2
- ¿ Qué es lo que está pasando ?

Resumen de las actividades

Ahora tiene un sistema de alerta macro.

  • ✅ Encuestas de FXMacroData Anuncios punto final cada 5 minutos para nuevas versiones en su lista de vigilancia
  • ✅ Estado persistente para evitar alertas duplicadas en los reinicios
  • ✅ Envía mensajes de webhook formateados a Slack, Discord o cualquier destino HTTP
  • ✅ Los incendios alertan de la cuenta regresiva previa a la liberación mediante el calendario de liberación con tiempo de entrega configurable
  • ✅ Se ejecuta continuamente como un servicio de sistema o contenedor Docker

Los siguientes pasos

  • → Ampliar la lista de vigilancia con indicadores adicionales de la Documento de la API IPC, empleo, balanza comercial y más
  • → Añadir un filtro sorpresa: sólo alerta cuando val se desvía de expected por encima de un umbral para reducir el ruido
  • → Combinar con Datos de posicionamiento del COT Para contextualizar si el mercado ya está posicionado para la sorpresa
  • → Alertas a un agente de IA (ver el Guía de integración de OpenClaw) para que pueda interpretar la liberación en el contexto

Blogroll