Build a Real-Time FX Event Agent That Front-Runs Your Morning Prep banner image

Implementation

How-To Guides

Build a Real-Time FX Event Agent That Front-Runs Your Morning Prep

Replace 45 minutes of manual pre-market prep with an always-on AI agent that scans the FXMacroData release calendar, ranks today's events by market impact, and delivers a structured briefing before London open.

Également disponible en English

Pourquoi un agent de préparation du matin est le robot à retour sur investissement le plus élevé que vous pouvez construire en premier

Si vous négociez des devises discrétionnairement ou si vous utilisez un bookmaker semi-automatisé, les 45 minutes les plus chères de votre journée sont celles avant l'ouverture de Londres. calendrier de sortie, vérifier les empreintes de niveau 1, voir si elles sont d'accord, scanner les mouvements du jour au lendemain. USD/JPYJe suis désolé . Le taux de changeJe suis désolé . Le taux de changeIl est répétitif, sujet aux erreurs, et vous oblige à reconstruire le contexte chaque matin à partir de zéro.

C'est exactement le genre de tâche qu'un agent d'IA fait mieux qu'une personne: portée limitée, entrées structurées, sortie déterministe. agent d'événements FX en temps réel qui s'exécute avant votre journée de négociation, tire les données d'événements en direct de FXMacroData, classe les sorties d'aujourd'hui par impact probable sur le marché, et fournit un briefing structuré que vous pouvez lire en 90 secondes.

À la fin, vous aurez un script que vous pouvez programmer sur n'importe quelle machine ordinateur portable, Raspberry Pi, cloud VM qui transforme la préparation du matin d'une corvée en une liste de contrôle.

Ce que vous allez construire
Un agent Python qui s'exécute à 06:30 UTC quotidiennement, interroge le calendrier de sortie FXMacroData pour les 24 prochaines heures dans le G10, classe les événements par impact, les résume à travers un LLM et envoie un briefing structuré sur Telegram ou Slack.

Pré-requis

  • Python 3.10+ et pip.
  • Une clé d'API FXMacroData de Gestion des APIJe suis désolé .
  • Un point final LLM que vous contrôlez.
    • Claude anthropique (recommandé pour la qualité du raisonnement).
    • Il est de la classe OpenAI GPT-4.
    • Hermes/Llama local via Ollama pour des trajets à coût nul.
  • Un jeton de bot Telegram (via @BotFather) ou une URL de webhook entrant Slack fonctionne comme le canal de livraison.
  • Un planificateur. cron sur Linux/macOS, le planificateur de tâches sur Windows, ou n'importe quel cron en nuage fera l'affaire.

Installer des dépendances:

pip install requests python-dotenv

Créez un .env Un dossier avec vos secrets:

FXMD_API_KEY=your_fxmacrodata_key
LLM_PROVIDER=anthropic           # or "openai" or "ollama"
ANTHROPIC_API_KEY=sk-ant-...
TELEGRAM_BOT_TOKEN=...
TELEGRAM_CHAT_ID=...

Étape 1: extraire les prochaines 24 heures du calendrier de sortie de FXMacroData

Le premier travail de l'agent est de savoir ce qui est réellement prévu. FXMacroData est une société les données relatives aux dates de sortie, au calendrier des dates de fin et aux sorties prévues par devise, y compris le nom de l'indicateur, l'heure UTC prévue, la valeur antérieure et le classement de l"importance, le cas échéant.

Demandez-le pour chaque monnaie importante que vous négociez:

curl "https://fxmacrodata.com/api/v1/calendar/usd?api_key=YOUR_API_KEY"
curl "https://fxmacrodata.com/api/v1/calendar/eur?api_key=YOUR_API_KEY"
curl "https://fxmacrodata.com/api/v1/calendar/gbp?api_key=YOUR_API_KEY"
curl "https://fxmacrodata.com/api/v1/calendar/jpy?api_key=YOUR_API_KEY"

Enveloppez ceci en Python pour que l'agent puisse itérer sur une liste de devises configurable:

import os
import requests
from datetime import datetime, timedelta, timezone
from dotenv import load_dotenv

load_dotenv()

API = "https://fxmacrodata.com/api/v1"
KEY = os.environ["FXMD_API_KEY"]
CURRENCIES = ["usd", "eur", "gbp", "jpy", "aud", "cad", "chf", "nzd"]


def fxmd_get(path, **params):
    r = requests.get(
        f"{API}{path}",
        params={"api_key": KEY, **params},
        timeout=25,
    )
    r.raise_for_status()
    return r.json()


def upcoming_releases(hours_ahead: int = 24):
    now = datetime.now(timezone.utc)
    cutoff = now + timedelta(hours=hours_ahead)
    releases = []
    for ccy in CURRENCIES:
        try:
            data = fxmd_get(f"/calendar/{ccy}").get("data", [])
        except requests.HTTPError:
            continue
        for ev in data:
            try:
                ts = datetime.fromisoformat(
                    ev["announcement_datetime"].replace("Z", "+00:00")
                )
            except (KeyError, ValueError):
                continue
            if now <= ts <= cutoff:
                releases.append({
                    "currency": ccy.upper(),
                    "indicator": ev.get("indicator") or ev.get("name"),
                    "scheduled_utc": ts.isoformat(),
                    "prior": ev.get("prior_value"),
                    "consensus": ev.get("consensus") or ev.get("market_consensus"),
                    "importance": ev.get("importance") or ev.get("impact"),
                })
    releases.sort(key=lambda r: r["scheduled_utc"])
    return releases

Étape 2: Classement des communiqués selon l'impact probable sur le marché

Toutes les impressions ne bougent pas les marchés. Salaires non agricolesJe suis désolé . PCE de baseJe suis désolé . Taux de la FedJe suis désolé . Indice des prix à la consommation de la zone euroJe suis désolé . IPC britannique, et Taux de référence de la Banque de Grèce Les échanges de détail sont très rares dans une économie de petite taille.

C'est la pièce la plus puissante de tout le système vos poids, votre avantage.

TIER_1 = {
    ("USD", "non_farm_payrolls"), ("USD", "core_pce"), ("USD", "policy_rate"),
    ("USD", "inflation"), ("USD", "fomc_minutes"),
    ("EUR", "inflation"), ("EUR", "policy_rate"),
    ("GBP", "inflation"), ("GBP", "policy_rate"),
    ("JPY", "policy_rate"), ("JPY", "inflation"),
    ("AUD", "policy_rate"), ("CAD", "policy_rate"),
    ("CHF", "policy_rate"), ("NZD", "policy_rate"),
}

TIER_2 = {
    ("USD", "retail_sales"), ("USD", "ism_manufacturing"),
    ("EUR", "gdp"), ("EUR", "unemployment"),
    ("GBP", "gdp"), ("GBP", "retail_sales"),
    ("AUD", "inflation"), ("CAD", "inflation"),
}


def impact_score(event: dict) -> int:
    key = (event["currency"], (event["indicator"] or "").lower())
    if key in TIER_1:
        return 3
    if key in TIER_2:
        return 2
    return 1


def rank(releases):
    return sorted(
        releases,
        key=lambda r: (-impact_score(r), r["scheduled_utc"]),
    )

Maintenant, vous pouvez décomposer la journée en une liste structurée où les événements de niveau 1 apparaissent en premier indépendamment de l'heure UTC.


Étape 3: Ajouter le contexte de nuit pour que l'agent sache ce qui a déjà été déplacé

Une séance d'information matinale est incomplète sans un instantané des mouvements de change du jour au lendemain.

PAIRS = [("USD", "JPY"), ("EUR", "USD"), ("GBP", "USD"), ("AUD", "USD")]


def overnight_moves():
    moves = []
    for base, quote in PAIRS:
        try:
            data = fxmd_get(
                "/forex",
                base=base,
                quote=quote,
            ).get("data", [])
        except requests.HTTPError:
            continue
        if len(data) < 2:
            continue
        last = data[-1]["value"]
        prev = data[-25]["value"] if len(data) >= 25 else data[0]["value"]
        change_pct = (last - prev) / prev * 100
        moves.append({
            "pair": f"{base}/{quote}",
            "last": round(last, 5),
            "change_pct_24h": round(change_pct, 2),
        })
    return moves

Si vous voulez également un contexte de positionnement pour les transactions swing, ajoutez un Le COT Gardez ça en option, le briefing devrait fonctionner sans.


Étape 4: Générer le briefing avec un LLM

L'agent dispose désormais de trois entrées structurées: événements classés, mouvements FX du jour au lendemain et l'horodatage UTC actuel. Passez-les dans le modèle avec un contrat de sortie strict afin que le briefing soit parsable et cohérent chaque matin.

import json
from anthropic import Anthropic

claude = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

SYSTEM_PROMPT = """You are an FX morning-prep analyst.
Given today's ranked releases and overnight moves, produce a briefing that:
- leads with the single most important event of the day,
- groups events by impact tier,
- flags 1-2 specific pairs to watch and why,
- ends with one disciplined risk caveat.
Do not give buy/sell instructions. Stay factual. Max 220 words."""


def generate_briefing(events, moves):
    payload = json.dumps({
        "utc_now": datetime.now(timezone.utc).isoformat(),
        "ranked_events": events,
        "overnight_moves": moves,
    })
    resp = claude.messages.create(
        model="claude-3-5-sonnet-latest",
        max_tokens=600,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": payload}],
    )
    return resp.content[0].text

Trois choses rendent cette demande fiable:

  • Entrée structurée. Le modèle reçoit JSON, pas le langage naturel, donc il n'a jamais à extraire des dates ou des chiffres du texte.
  • Une vue d'ensemble. L'invite de système interdit les recommandations commerciales, ce qui maintient la sortie conforme et utile même les jours volatiles.
  • Le plafond de longueur. 220 mots forcent la densité du signal, de longues séances d'information vous entraînent à déchiffrer, ce qui défait le but.

Étape 5: Envoyer à Telegram (ou Slack)

Le briefing doit arriver là où vous regardez dès le matin.

def send_telegram(text: str):
    token = os.environ["TELEGRAM_BOT_TOKEN"]
    chat_id = os.environ["TELEGRAM_CHAT_ID"]
    requests.post(
        f"https://api.telegram.org/bot{token}/sendMessage",
        json={
            "chat_id": chat_id,
            "text": text,
            "parse_mode": "Markdown",
            "disable_web_page_preview": True,
        },
        timeout=15,
    )


def run():
    events = rank(upcoming_releases(hours_ahead=24))
    moves = overnight_moves()
    briefing = generate_briefing(events, moves)
    header = f"*FX Morning Briefing — {datetime.now(timezone.utc):%a %d %b %Y}*\n\n"
    send_telegram(header + briefing)


if __name__ == "__main__":
    run()

Planifiez-le. Sur Linux/macOS, une seule entrée crontab exécute l'agent tous les jours de la semaine à 06:30 UTC:

30 6 * * 1-5 /usr/bin/python3 /opt/fx-agent/morning_brief.py >> /var/log/fx-agent.log 2>&1

À quoi ressemble le briefing ?

Exemple de sortie produite par l'agent au cours d'une semaine récente d'IPC:

FX Morning Briefing — Thu 22 May 2026

Today's anchor: US Core PCE at 12:30 UTC. Consensus 0.2% MoM,
prior 0.0%. A second sub-0.1 print would cement the disinflation
narrative; a 0.3+ surprise resets Fed pricing.

Tier 1:
- 12:30 UTC USD Core PCE  prior +0.0%  cons +0.2%
- 13:30 UTC USD Initial Jobless Claims  prior 228k  cons 225k

Tier 2:
- 06:00 UTC GBP Retail Sales MoM  prior -0.1%  cons +0.4%
- 09:00 UTC EUR ECB Minutes (qualitative)

Pairs to watch:
- USD/JPY hovering 158.40 after a quiet Asia. PCE miss → 156s
  back in play.
- GBP/USD coiled below 1.2700. Stronger UK retail + soft PCE is
  the cleanest setup of the day.

Risk caveat: thin EU liquidity ahead of US data; expect outsized
moves on any surprise print.

C'est une lecture complète en moins de 90 secondes, tous les jours de la semaine, sans grattage manuel du calendrier.


Une liste de contrôle de durcissement avant de lui faire confiance

  • Un détective de données. Ne pas envoyer le briefing si un événement de niveau 1 manque à une heure prévue.
  • Essayez à nouveau avec le backoff. Trois tentatives, 2s/4s/8s, puis échoue fort.
  • Validateur de sortie. Rejetez toute réponse contenant les mots "acheter", "vendre" ou "long" / "short".
  • Alerte de battement de cœur. Si l'agent ne parvient pas à envoyer un briefing avant 07:00 UTC, ping vous-même séparément afin que vous ne perdez pas silencieusement le flux de travail.
  • Le plafond de coût. Je suis prêt . max_tokens=600 Les séances devraient coûter des cents par jour.

Où le prendre ensuite ?

Le même échafaudage s'étend facilement une fois que la boucle du matin est fiable:

  • Alertes de surprise intraday. Le sondage les annonces des points de fin toutes les 15 minutes après une libération de niveau 1; alerter lorsque le taux réel dépasse le seuil de consensus.
  • Des briefings spécifiques à chaque couple. Génère un plus serré . USD/JPY- Seulement ou ? Le taux de change- version pour les jours d'activité.
  • Positionnement de la couche. Tirez ! Données sur le COT Il faut le faire chaque semaine et le mettre dans le même message pour que le briefing sache quand le marché est unilatéral.
  • En mode voix. Passez le briefing à travers un modèle TTS et faites-le lire à haute voix pendant que vous faites du café.

La victoire n'est pas dans le briefing lui-même, mais dans le contexte discipliné et reproductible avec lequel vous entrez dans votre journée de trading.

Blogroll