Comment créer un tableau de bord macro en Python avec pandas & Plotly banner image

By Language

Quick Start Guides

Comment créer un tableau de bord macro en Python avec pandas & Plotly

Guide étape par étape pour récupérer les indicateurs FXMacroData via Python, remodeler les séries temporelles avec des pandas et assembler un tableau de bord multi-panels interactif avec Plotly.

Également disponible en English

Un tableau de bord macro met les indicateurs économiques et bancaires les plus importants en un seul endroit, vous permettant ainsi de scanner les conditions du marché en quelques secondes au lieu de revenir à des terminaux de données. les pandas, et le rendre avec Je suis convaincu .Chaque panneau est mis à jour à partir d'une seule clé API et d'un petit nombre d'appels de fonctions.

Ce que vous allez construire

Un script Python autonome qui tire les taux de change, l'inflation, le chômage et le PMI pour quatre principales devises (USD, EUR, GBP, AUD), assemble un DataFrame panda propre pour chaque indicateur et rend un tableau de bord Plotly de quatre panneaux tout en moins de 150 lignes de code.

Pré-requis

Vous aurez besoin de ce qui suit avant de commencer:

  • Python 3.9+
  • Clé de l'API FXMacroData inscrivez-vous à / souscrivez et copiez votre clé du tableau de bord
  • Paquets PythonJe suis désolé . requestsJe suis désolé . pandasJe suis désolé . plotly

Installez les dépendances en une seule commande:

pip install requests pandas plotly

Stockez votre clé API comme une variable d'environnement jamais les identifiants de code dur dans les scripts:

export FXMD_API_KEY="YOUR_API_KEY"

Étape 1 Comprendre la forme du point final de l'indicateur

Chaque indicateur FXMacroData suit le même schéma REST, ce qui rend trivial la généralisation en une seule fonction de récupération.

GET https://fxmacrodata.com/api/v1/announcements/usd/policy_rate?api_key=YOUR_API_KEY&start=2020-01-01

La réponse JSON est un objet plat avec un data le tableau:

{
  "data": [
    { "date": "2025-03-19", "val": 4.25, "announcement_datetime": "2025-03-19T18:00:00Z" },
    { "date": "2025-01-29", "val": 4.25, "announcement_datetime": "2025-01-29T19:00:00Z" },
    { "date": "2024-12-18", "val": 4.25, "announcement_datetime": "2024-12-18T19:00:00Z" }
  ]
}

Chaque disque porte un date (ANAN-MM-DD), un chiffre val, et le cas échéant un UTC de deuxième niveau announcement_datetimeLa forme cohérente de tous les indicateurs permet à une fonction de servir tous les panneaux du tableau de bord.

Étape 2 Écrire une fonction de récupération réutilisable

Créez un module appelé macro_fetch.pyLa fonction ci-dessous demande n'importe quel indicateur pour n' importe quelle devise, convertit la réponse en une série de pandas et la renvoie indexée par date prête à être déposée directement dans un DataFrame.

import os
import requests
import pandas as pd

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


def fetch_indicator(currency: str, indicator: str, start: str = "2020-01-01") -> pd.Series:
    """
    Fetch a single indicator series from FXMacroData and return it as a
    pandas Series with a DatetimeIndex, named '{currency.upper()}_{indicator}'.
    """
    url = f"{BASE_URL}/announcements/{currency}/{indicator}"
    resp = requests.get(url, params={"api_key": API_KEY, "start": start}, timeout=15)
    resp.raise_for_status()

    records = resp.json().get("data", [])
    if not records:
        return pd.Series(name=f"{currency.upper()}_{indicator}", dtype=float)

    series = (
        pd.DataFrame(records)
        .assign(date=lambda df: pd.to_datetime(df["date"]))
        .set_index("date")["val"]
        .sort_index()
        .rename(f"{currency.upper()}_{indicator}")
    )
    return series

Pourquoi une série par indicateur ?

Les indicateurs de différentes devises sont publiés à des dates différentes, donc ils ne partagent jamais un indice parfaitement aligné. pd.concat(..., axis=1) permet aux pandas de gérer l'alignement de date automatiquement, remplissant les lacunes avec NaN où une monnaie n'a pas encore été déclarée.

Étape 3 Récupérer tous les indicateurs pour le tableau de bord

Avec l'aide de récupération en place, tirer quatre indicateurs pour quatre devises est une boucle concise.

import time

CURRENCIES = ["usd", "eur", "gbp", "aud"]
INDICATORS = {
    "policy_rate": "Policy Rate (%)",
    "inflation": "CPI Inflation (% YoY)",
    "unemployment": "Unemployment Rate (%)",
    "pmi": "Manufacturing PMI",
}


def fetch_all(start: str = "2020-01-01", retries: int = 3) -> dict[str, pd.DataFrame]:
    """
    Return a dict mapping each indicator slug to a wide DataFrame where
    each column is one currency (e.g. USD_policy_rate, EUR_policy_rate).
    """
    frames: dict[str, list[pd.Series]] = {ind: [] for ind in INDICATORS}

    for currency in CURRENCIES:
        for indicator in INDICATORS:
            for attempt in range(retries):
                try:
                    s = fetch_indicator(currency, indicator, start=start)
                    frames[indicator].append(s)
                    break
                except requests.HTTPError as exc:
                    if attempt == retries - 1:
                        print(f"Warning: could not fetch {currency}/{indicator}: {exc}")
                    else:
                        time.sleep(1.5 ** attempt)

    return {ind: pd.concat(series, axis=1) for ind, series in frames.items() if series}

Vous pouvez inspecter n'importe quel DataFrame de manière interactive pour vérifier l'apparence des données juste avant de les rendre:

data = fetch_all(start="2021-01-01")
print(data["policy_rate"].tail())
# Output (example):
#             USD_policy_rate  EUR_policy_rate  GBP_policy_rate  AUD_policy_rate
# date
# 2025-01-29             4.25              NaN              NaN              NaN
# 2025-02-06              NaN              NaN             4.50              NaN
# 2025-02-18              NaN              NaN              NaN             4.10
# 2025-03-06              NaN             2.50              NaN              NaN
# 2025-03-19             4.25              NaN              NaN              NaN

Étape 4 Faites des données pour la cartographie

Le complot fonctionne mieux avec ... remplis à l'avance pour les graphiques linéaires, de sorte que la valeur la plus récente connue est reportée jusqu'à la prochaine version.

def prepare_for_chart(df: pd.DataFrame) -> pd.DataFrame:
    """
    Forward-fill each column so lines in the chart step at each release date
    rather than showing gaps between announcements.
    Resample to a monthly frequency for a cleaner visual.
    """
    return (
        df
        .ffill()
        .resample("ME")      # month-end
        .last()
        .dropna(how="all")
    )

Pour l'indicateur PMI, qui est mensuel, le remplissage anticipé est moins pertinent mais la fonction le gère avec élégance en passant simplement les données déjà mensuelles inchangées.

Étape 5 Construisez le tableau de bord

Il est de Plotly. make_subplots L'utilitaire vous permet d'organiser plusieurs graphiques dans un seul objet de figure, que vous pouvez afficher dans un navigateur, exporter sous forme HTML, ou intégrer dans un bloc-notes Jupyter.

import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Palette aligned with FXMacroData brand colours
COLORS = {
    "usd": "#3B82F6",   # finance blue
    "eur": "#D97706",   # gold
    "gbp": "#16A34A",   # green
    "aud": "#7C3AED",   # purple
}

SUBPLOT_TITLES = list(INDICATORS.values())


def build_dashboard(data: dict[str, pd.DataFrame]) -> go.Figure:
    fig = make_subplots(
        rows=2, cols=2,
        subplot_titles=SUBPLOT_TITLES,
        shared_xaxes=False,
        vertical_spacing=0.12,
        horizontal_spacing=0.08,
    )

    positions = [(1, 1), (1, 2), (2, 1), (2, 2)]

    for (indicator, label), (row, col) in zip(INDICATORS.items(), positions):
        df = prepare_for_chart(data[indicator])
        for col_name in df.columns:
            currency = col_name.split("_")[0].lower()
            fig.add_trace(
                go.Scatter(
                    x=df.index,
                    y=df[col_name],
                    mode="lines",
                    name=currency.upper(),
                    line=dict(color=COLORS[currency], width=2),
                    legendgroup=currency,
                    showlegend=(indicator == "policy_rate"),  # one legend entry per currency
                    hovertemplate=f"%{{x|%b %Y}}: %{{y:.2f}}{monnaie.supérieure() }",
                ),
                row=row, col=col,
            )

    fig.update_layout(
        title=dict(
            text="G4 Central Bank Macro Dashboard",
            font=dict(size=22, color="#1e3a5f"),
            x=0.5,
        ),
        paper_bgcolor="#f8fafc",
        plot_bgcolor="#f1f5f9",
        font=dict(family="Inter, system-ui, sans-serif", size=12, color="#334155"),
        legend=dict(
            orientation="h",
            yanchor="bottom",
            y=1.04,
            xanchor="center",
            x=0.5,
        ),
        height=700,
        margin=dict(t=100, b=50, l=60, r=40),
    )

    fig.update_xaxes(showgrid=True, gridcolor="#e2e8f0", zeroline=False)
    fig.update_yaxes(showgrid=True, gridcolor="#e2e8f0", zeroline=False)

    return fig

Étape 6 Exécutez le tableau de bord

Connectez tout en un . dashboard.py Le script de l'entrée. fig.show() ouvre le tableau de bord dans votre navigateur par défaut. fig.write_html() enregistre un fichier HTML autonome que vous pouvez partager ou intégrer n'importe où.

if __name__ == "__main__":
    print("Fetching macro data …")
    data = fetch_all(start="2021-01-01")

    print("Building dashboard …")
    fig = build_dashboard(data)

    # Option A: open in browser
    fig.show()

    # Option B: save as portable HTML file
    fig.write_html("macro_dashboard.html", include_plotlyjs="cdn")
    print("Saved macro_dashboard.html")

Faites-le depuis le terminal:

python dashboard.py

Plotly ouvrira une fenêtre de navigateur montrant un tableau de bord à deux rangées et deux colonnes avec quatre panneaux en direct un pour chaque indicateur codé par couleur par devise.

Ajouter plus d'indicateurs en quelques secondes

Le tableau de bord est conçu pour être étalonné. INDICATORS dict par exemple "core_inflation": "Core CPI (% YoY)" ou ... "gdp_quarterly": "GDP Growth (% QoQ)" et les étapes de recherche, de forme et de graphique le prennent automatiquement. Documentation sur les APIJe suis désolé .

Étape 7 Ajouter des annotations de date de sortie (facultatif)

L' une des améliorations les plus utiles du tableau de bord est la superposition . marqueurs de libération lignes verticales ou points qui indiquent exactement quand chaque annonce a été faite. announcement_datetime les timbres, pour pouvoir les ajouter sans aucune conjecture:

def fetch_release_datetimes(currency: str, indicator: str, start: str) -> pd.Series:
    """Return a Series of UTC announcement datetimes for a given indicator."""
    url = f"{BASE_URL}/announcements/{currency}/{indicator}"
    resp = requests.get(url, params={"api_key": API_KEY, "start": start}, timeout=15)
    resp.raise_for_status()
    records = resp.json().get("data", [])
    if not records:
        return pd.Series(dtype="datetime64[ns, UTC]")
    df = pd.DataFrame(records)
    if "announcement_datetime" not in df.columns:
        return pd.Series(dtype="datetime64[ns, UTC]")
    return pd.to_datetime(df["announcement_datetime"], utc=True)


def add_release_markers(fig: go.Figure, currency: str, indicator: str,
                         start: str, row: int, col: int) -> None:
    """Overlay vertical dashed lines on a subplot at each release datetime."""
    datetimes = fetch_release_datetimes(currency, indicator, start)
    for dt in datetimes:
        fig.add_vline(
            x=dt.timestamp() * 1000,  # Plotly uses ms since epoch for datetime axes
            line_width=1,
            line_dash="dot",
            line_color=COLORS[currency],
            opacity=0.35,
            row=row, col=col,
        )

Appelez . add_release_markers Après . build_dashboard et avant . fig.show() Les marqueurs de libération sont particulièrement utiles sur le panneau des taux d'intérêt, où les dates de décision sont rares mais d'un impact important.

Étape 8 Exporter les panneaux comme images individuelles

Si vous souhaitez inclure des graphiques individuels dans un rapport ou un tableau de diapositives, Plotly peut exporter chaque sous-graphique sous forme de PNG via Le KaleidoJe suis désolé .

pip install kaleido
fig.write_image("macro_dashboard.png", width=1400, height=700, scale=2)

Pour les exportations par panneau, chaque indicateur doit être établi indépendamment go.Figure en utilisant la même go.Scatter Trace et appel . write_image Les fonctions de récupération et de forme développées dans les étapes précédentes fonctionnent inchangées pour les figures à un seul panneau.

Références complètes

Ci-dessous, le script complet, en soi, combinant toutes les étapes ci-dessus. dashboard.pyJe suis prêt . FXMD_API_KEYJe vais le faire.

"""
macro_dashboard.py — G4 Central Bank Macro Dashboard
Requires: requests, pandas, plotly
Usage:    FXMD_API_KEY=your_key python macro_dashboard.py
"""
import os
import time
import requests
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

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

CURRENCIES = ["usd", "eur", "gbp", "aud"]
INDICATORS = {
    "policy_rate": "Policy Rate (%)",
    "inflation": "CPI Inflation (% YoY)",
    "unemployment": "Unemployment Rate (%)",
    "pmi": "Manufacturing PMI",
}
COLORS = {"usd": "#3B82F6", "eur": "#D97706", "gbp": "#16A34A", "aud": "#7C3AED"}


def fetch_indicator(currency: str, indicator: str, start: str = "2020-01-01") -> pd.Series:
    url = f"{BASE_URL}/announcements/{currency}/{indicator}"
    resp = requests.get(url, params={"api_key": API_KEY, "start": start}, timeout=15)
    resp.raise_for_status()
    records = resp.json().get("data", [])
    if not records:
        return pd.Series(name=f"{currency.upper()}_{indicator}", dtype=float)
    return (
        pd.DataFrame(records)
        .assign(date=lambda df: pd.to_datetime(df["date"]))
        .set_index("date")["val"]
        .sort_index()
        .rename(f"{currency.upper()}_{indicator}")
    )


def fetch_all(start: str = "2020-01-01", retries: int = 3) -> dict[str, pd.DataFrame]:
    frames: dict[str, list[pd.Series]] = {ind: [] for ind in INDICATORS}
    for currency in CURRENCIES:
        for indicator in INDICATORS:
            for attempt in range(retries):
                try:
                    frames[indicator].append(fetch_indicator(currency, indicator, start))
                    break
                except requests.HTTPError as exc:
                    if attempt == retries - 1:
                        print(f"Warning: {currency}/{indicator}: {exc}")
                    else:
                        time.sleep(1.5 ** attempt)
    return {ind: pd.concat(series, axis=1) for ind, series in frames.items() if series}


def prepare_for_chart(df: pd.DataFrame) -> pd.DataFrame:
    return df.ffill().resample("ME").last().dropna(how="all")


def build_dashboard(data: dict[str, pd.DataFrame]) -> go.Figure:
    fig = make_subplots(
        rows=2, cols=2,
        subplot_titles=list(INDICATORS.values()),
        vertical_spacing=0.12,
        horizontal_spacing=0.08,
    )
    for (indicator, _), (row, col) in zip(INDICATORS.items(), [(1,1),(1,2),(2,1),(2,2)]):
        df = prepare_for_chart(data[indicator])
        for col_name in df.columns:
            currency = col_name.split("_")[0].lower()
            fig.add_trace(
                go.Scatter(
                    x=df.index, y=df[col_name], mode="lines",
                    name=currency.upper(),
                    line=dict(color=COLORS[currency], width=2),
                    legendgroup=currency,
                    showlegend=(indicator == "policy_rate"),
                    hovertemplate=f"%{{x|%b %Y}}: %{{y:.2f}}{monnaie.supérieure() }",
                ),
                row=row, col=col,
            )
    fig.update_layout(
        title=dict(text="G4 Central Bank Macro Dashboard", font=dict(size=22, color="#1e3a5f"), x=0.5),
        paper_bgcolor="#f8fafc", plot_bgcolor="#f1f5f9",
        font=dict(family="Inter, system-ui, sans-serif", size=12),
        legend=dict(orientation="h", yanchor="bottom", y=1.04, xanchor="center", x=0.5),
        height=700, margin=dict(t=100, b=50, l=60, r=40),
    )
    fig.update_xaxes(showgrid=True, gridcolor="#e2e8f0", zeroline=False)
    fig.update_yaxes(showgrid=True, gridcolor="#e2e8f0", zeroline=False)
    return fig


if __name__ == "__main__":
    print("Fetching macro data …")
    data = fetch_all(start="2021-01-01")
    print("Building dashboard …")
    fig = build_dashboard(data)
    fig.show()
    fig.write_html("macro_dashboard.html", include_plotlyjs="cdn")
    print("Saved macro_dashboard.html")

Résumé

Vous avez maintenant un tableau de bord de macro fonctionnel qui:

  • Il rapporte les taux directeurs, l'inflation, le chômage et les PMI pour les USD, EUR, GBP et AUD à partir de la Point de fin des annonces FXMacroData
  • Ressemble les données en pandas alignés et remplis vers l'avant
  • Rendre un tableau de bord interactif à quatre panneaux avec des lignes de devises colorées
  • Exporte un fichier HTML autonome que vous pouvez partager ou intégrer

De là, vous pouvez étendre le tableau de bord dans plusieurs directions: ajouter plus de devises, superposer le chômage Le catalogue complet des indicateurs incluant la balance commerciale, la croissance du crédit et le positionnement des COT est disponible à les données sur les données api-docsJe suis désolé .

Blogroll