TradingView est la plateforme de graphique de choix pour la majorité des traders de détail FX, et Pine Script est le langage qui donne vie à des indicateurs personnalisés et à des signaux de stratégie sur ces graphiques. Le défi est que Pine Script fonctionne entièrement à l'intérieur du bac à sable de TradingVIEW il ne peut pas effectuer d'appels HTTP sortants vers des API externes à l 'exécution. Ce guide comble cet écart avec un flux de travail en deux parties: un petit script Python récupère les données d'annonce macro de FXMacroData, génère un code Pine Script prêt à coller, et l'indicateur résultant superpose ces points de données directement sur votre graphique TradingViews avec des marqueurs d'événements, une ligne de signal et une table de données macro en direct.
Ce que vous allez construire
- Un script Python qui récupère les annonces de taux directeur, d'IPC et de PMI pour n'importe quelle devise de FXMacroData et génère automatiquement le code source Pine Script
- Un indicateur Pine Script v5 qui marque les dates des événements macro sur votre graphique avec des diamants étiquetés, dessine une ligne de superposition de la valeur macro et affiche un tableau de données résumant les dernières impressions
- Une alerte TradingView → un pont webhook qui ping un petit point final de Flask chaque fois que votre condition de feu de script de pin, vous permettant de croisement de référence du signal avec le contexte frais FXMacroData automatiquement
Pré-requis
- Python 3.10+ avec
requestsinstallé - Clé de l'API FXMacroData inscrivez-vous à / souscrivez; les données de l' indicateur USD sont gratuites et ne nécessitent aucune clé
- Un compte TradingView le niveau gratuit prend en charge Pine Script v5 et les indicateurs personnalisés
- Familiarité avec le script Pine le Le code de la carte de crédit couvrir les concepts de base en moins d'une heure
- Passe 1 - Passez à la première étape
Étape 1 Comprendre le point final de l'annonce FXMacroData
Chaque indicateur dans FXMacroData suit la même forme REST. Une demande de taux de politique pour l'EUR ressemble à ceci utilisez votre clé API comme paramètre de requête:
curl "https://fxmacrodata.com/api/v1/announcements/eur/policy_rate?api_key=YOUR_API_KEY&start=2023-01-01"
La réponse JSON est un objet plat avec un data le tableau:
{
"currency": "eur",
"indicator": "policy_rate",
"data": [
{
"date": "2025-03-06",
"val": 2.65,
"announcement_datetime": "2025-03-06T13:15:00Z"
},
{
"date": "2025-01-30",
"val": 2.90,
"announcement_datetime": "2025-01-30T13:15:00Z"
},
{
"date": "2024-12-12",
"val": 3.15,
"announcement_datetime": "2024-12-12T13:15:00Z"
}
]
}
Chaque disque porte un date (ANAN-MM-DD date locale de la mise en circulation), un chiffre val, et un UTC de deuxième niveau announcement_datetimeLa forme cohérente de toutes les devises et indicateurs est ce qui rend le générateur de code simple à construire. Taux de référence en euros et explorez le catalogue des indicateurs pour votre devise cible.
- Passe 2 - Je suis désolé
Étape 2 Retrouver les données macro avec Python
Créez un fichier appelé generate_pine.py. Ce script récupère les données d'annonce pour une devise et un indicateur choisis, puis sérialise les résultats en tableaux Pine Script que vous collez dans le fichier indicateur.
"""
generate_pine.py — fetch FXMacroData announcements and output Pine Script arrays.
Usage:
python generate_pine.py --currency eur --indicator policy_rate --start 2023-01-01
"""
import argparse
import json
import os
from datetime import datetime, timezone
import requests
BASE_URL = "https://fxmacrodata.com/api/v1"
API_KEY = os.environ.get("FXMD_API_KEY", "")
def fetch_announcements(currency: str, indicator: str, start: str) -> list[dict]:
url = f"{BASE_URL}/announcements/{currency}/{indicator}"
params: dict = {"start": start}
if API_KEY:
params["api_key"] = API_KEY
resp = requests.get(url, params=params, timeout=15)
resp.raise_for_status()
return resp.json().get("data", [])
def ts_to_pine_timestamp(iso_str: str) -> int:
"""Convert an ISO-8601 UTC string to a Unix timestamp (milliseconds for Pine)."""
dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00"))
return int(dt.timestamp() * 1000)
def build_pine_arrays(records: list[dict]) -> str:
"""Render the data as Pine Script array literals."""
ts_list = []
val_list = []
for r in records:
ann = r.get("announcement_datetime") or f"{r['date']}T00:00:00Z"
ts_list.append(str(ts_to_pine_timestamp(ann)))
val_list.append(str(r["val"]))
ts_str = ", ".join(ts_list)
val_str = ", ".join(val_list)
n = len(records)
return f"""
// ── Auto-generated by generate_pine.py — do not edit manually ──
// Currency: {records[0].get('currency', '?').upper() if records else '?'}
// Indicator: {records[0].get('indicator', '?') if records else '?'}
// Records: {n}
var int[] _ann_ts = array.from({ts_str})
var float[] _ann_val = array.from({val_str})
"""
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--currency", required=True)
parser.add_argument("--indicator", required=True)
parser.add_argument("--start", default="2023-01-01")
args = parser.parse_args()
print(f"Fetching {args.indicator} for {args.currency.upper()} from {args.start} …")
records = fetch_announcements(args.currency, args.indicator, args.start)
print(f" {len(records)} records returned.")
pine = build_pine_arrays(records)
print(pine)
output_file = f"pine_data_{args.currency}_{args.indicator}.txt"
with open(output_file, "w") as f:
f.write(pine)
print(f"Arrays written to {output_file}")
if __name__ == "__main__":
main()
Enregistrez votre clé API et exécutez le script:
export FXMD_API_KEY="YOUR_API_KEY"
python generate_pine.py --currency eur --indicator policy_rate --start 2023-01-01
Le fichier de sortie . pine_data_eur_policy_rate.txt Vous pouvez exécuter le même script pour CPI (--indicator inflation), les PMI (--indicator pmi), ou tout autre indicateur de la
Catalogue de la société FXMacroDataJe suis désolé .
- Pas 3 - Je suis désolé
Étape 3 Construire l'indicateur de l'écriture Pine
Ouvrez TradingView, accédez à l'éditeur de script Pine (l'onglet "Pine Editor" au bas du graphique) et collez l'indicateur suivant. _ann_ts Je suis désolé . _ann_val les tableaux en haut avec la sortie de l'étape 2.
// @version=5
// FXMacroData Overlay — policy rate event markers + value line
// Replace the arrays below with output from generate_pine.py
indicator("FXMacroData Macro Overlay", overlay=true, max_labels_count=50, max_lines_count=50)
// ── User inputs ──
i_show_labels = input.bool(true, "Show event labels")
i_show_line = input.bool(true, "Show macro value line")
i_show_table = input.bool(true, "Show data table")
i_label_color = input.color(color.new(color.orange, 0), "Label colour")
i_line_color = input.color(color.new(color.orange, 30), "Line colour")
// ── Paste generated arrays here ──
// ---- BEGIN GENERATED SECTION ----
var int[] _ann_ts = array.from(1672531200000, 1675209600000, 1677628800000)
var float[] _ann_val = array.from(2.50, 2.65, 3.00)
// ---- END GENERATED SECTION ----
// ── Helper: find the most recent announcement value at or before this bar ──
f_current_val() =>
float result = na
int bar_t = time
for i = 0 to array.size(_ann_ts) - 1
if array.get(_ann_ts, i) <= bar_t
result := array.get(_ann_val, i)
break
result
// ── Macro overlay line ──
float macro_val = f_current_val()
plot(i_show_line ? macro_val : na, title="Macro value", color=i_line_color,
linewidth=2, style=plot.style_stepline)
// ── Event marker labels ──
if i_show_labels
for i = 0 to array.size(_ann_ts) - 1
int ts = array.get(_ann_ts, i)
float val = array.get(_ann_val, i)
if ts >= chart.left_visible_bar_time and ts <= chart.right_visible_bar_time
label.new(
x = ts,
y = high * 1.002,
text = str.tostring(val, "#.##"),
style = label.style_diamond,
color = i_label_color,
textcolor = color.white,
size = size.small,
xloc = xloc.bar_time
)
// ── Summary table (top-right corner) ──
var table t = table.new(position.top_right, 2, 6,
bgcolor = color.new(color.navy, 85),
border_width = 1,
border_color = color.new(color.gray, 60))
if i_show_table and barstate.islast
table.cell(t, 0, 0, "Date", text_color=color.silver, text_size=size.small)
table.cell(t, 1, 0, "Value", text_color=color.silver, text_size=size.small)
int rows = math.min(5, array.size(_ann_ts))
for i = 0 to rows - 1
int ts = array.get(_ann_ts, i)
float val = array.get(_ann_val, i)
string date_str = str.format("{0,date,yyyy-MM-dd}", ts)
table.cell(t, 0, i + 1, date_str, text_color=color.white, text_size=size.tiny)
table.cell(t, 1, i + 1, str.tostring(val, "#.##"), text_color=color.orange, text_size=size.tiny)
Pourquoi ? steplineJe suis désolé .
Les valeurs des indicateurs macro sont fonctions d'étape le taux directeur ne se transforme pas en douceur entre les réunions; il saute. plot.style_stepline maintient la superposition honnête: la ligne reste au même niveau jusqu'à ce qu'une nouvelle annonce soit imprimée, correspondant exactement aux données publiées.
Cliquez Ajouter au graphique. L'indicateur superposera une ligne pas à pas correspondant à la progression de la valeur macro et déposera un marqueur diamanté étiqueté à chaque date d'annonce. Faites défiler l'historique pour voir comment chaque impression de taux de politique s'aligne sur l'action des prix sur la paire de devises choisie.
- Passe 4 - Passez à la première étape
Étape 4 Couche dans plusieurs indicateurs
Un seul indicateur raconte une partie de l'histoire. Le véritable avantage provient de la superposition du taux de politique, de l 'IPC et du PMI. Répétez l'étape 2 pour chaque indicateur et ajoutez une section supplémentaire au script Pine, ou créez trois indicateurs distincts et empilés sur le même tableau.
Pour une recherche à trois indicateurs en une seule fois, étendre le script Python:
INDICATORS = ["policy_rate", "inflation", "pmi"]
CURRENCY = "eur"
START = "2023-01-01"
for ind in INDICATORS:
records = fetch_announcements(CURRENCY, ind, START)
pine = build_pine_arrays(records)
with open(f"pine_data_{CURRENCY}_{ind}.txt", "w") as f:
f.write(pine)
print(f"Written pine_data_{CURRENCY}_{ind}.txt ({len(records)} records)")
Chaque fichier de sortie vous donne une section déroulante pour un indicateur Pine Script séparé. Ajoutez-en chacun à votre graphique et attribuez une couleur distincte à chaque indicateur par exemple, orange pour le taux directeur, bleu pour l'IPC et vert pour le PMI afin de voir d'un coup d'œil quel régime macro est en vigueur. EUR PMI docs et le catalogue plus large des indicateurs.
- Passe 5 - Je suis désolé
Étape 5 Automatiser les mises à jour avec une vérification du calendrier de sortie
Les données macro dans les tableaux de Pine Script deviennent obsolètes au moment où une nouvelle annonce est imprimée. Automatiser la mise à jour en appelant le point de fin du calendrier de sortie de FXMacroData avant chaque session de négociation pour vérifier si quelque chose a été imprimé depuis votre dernière régénération. Si c'est le cas, redémarrez le générateur et mettez à jour votre Pine Script.
"""
check_and_refresh.py — Re-generate Pine arrays if new announcements have printed.
Run this before each session, e.g. via cron or GitHub Actions.
"""
import subprocess
import requests
import os
from datetime import date, timedelta
BASE_URL = "https://fxmacrodata.com/api/v1"
API_KEY = os.environ.get("FXMD_API_KEY", "")
PAIRS = [
("eur", "policy_rate"),
("eur", "inflation"),
("eur", "pmi"),
]
def latest_release_date(currency: str, indicator: str) -> str | None:
"""Return the most recent announcement date for this indicator."""
params: dict = {"start": str(date.today() - timedelta(days=7))}
if API_KEY:
params["api_key"] = API_KEY
r = requests.get(
f"{BASE_URL}/announcements/{currency}/{indicator}",
params=params, timeout=10
)
r.raise_for_status()
data = r.json().get("data", [])
return data[0]["date"] if data else None
def refresh_all() -> None:
for currency, indicator in PAIRS:
latest = latest_release_date(currency, indicator)
if latest and latest >= str(date.today() - timedelta(days=1)):
print(f"New print detected: {currency.upper()} {indicator} on {latest}. Regenerating …")
subprocess.run(
["python", "generate_pine.py",
"--currency", currency,
"--indicator", indicator,
"--start", "2023-01-01"],
check=True,
)
else:
print(f"{currency.upper()} {indicator}: no new prints since yesterday.")
if __name__ == "__main__":
refresh_all()
Planifiez ce script pour qu'il s'exécute du lundi au vendredi à 08:00 UTC, avant l'ouverture de Londres, en utilisant un travail cron, un flux de travail GitHub Actions ou tout autre planificateur de tâches.
pine_data_*.txt Le contenu dans l'éditeur de pins de TradingView et cliquez EnregistrerVos marqueurs de graphique refléteront immédiatement les dernières données d'annonce.
- Pas 6 - Je suis désolé
Étape 6 Envoyer les alertes TradingView dans le contexte FXMacroData
Le flux de travail jusqu'à présent pousse les données macro dans TradingView. L'étape 6 ferme la boucle dans l'autre sens: lorsque votre script Pine lance un signal de trading (par exemple une rupture au-dessus de la résistance après une impression de l'IPC), le système d'alerte webhook de TradingVIEW transmet cet événement à un petit point final Flask, qui interroge immédiatement FXMacroData pour un nouveau contexte la dernière tendance de l 'IPC, les prochaines versions et le positionnement actuel du COT et enregistre ou vous informe avec la macro-image complète.
Créer . webhook_server.pyLe texte est le suivant:
"""
webhook_server.py — Receive TradingView alert webhooks and enrich with FXMacroData context.
Run with: python webhook_server.py
Expose to the internet via ngrok or deploy to a cloud function / VPS.
"""
import os
import json
from datetime import date, timedelta
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
BASE_URL = "https://fxmacrodata.com/api/v1"
API_KEY = os.environ.get("FXMD_API_KEY", "")
def get_macro_context(currency: str) -> dict:
"""Fetch latest policy rate + CPI for the given currency."""
params: dict = {"start": str(date.today() - timedelta(days=90))}
if API_KEY:
params["api_key"] = API_KEY
ctx: dict = {}
for indicator in ("policy_rate", "inflation"):
try:
r = requests.get(
f"{BASE_URL}/announcements/{currency}/{indicator}",
params=params, timeout=10
)
r.raise_for_status()
data = r.json().get("data", [])
ctx[indicator] = data[0] if data else {}
except Exception as exc:
ctx[indicator] = {"error": str(exc)}
return ctx
@app.route("/tradingview/alert", methods=["POST"])
def receive_alert():
payload = request.get_json(force=True, silent=True) or {}
currency = payload.get("currency", "usd").lower()
signal = payload.get("signal", "unknown")
ctx = get_macro_context(currency)
result = {
"received_signal": signal,
"currency": currency.upper(),
"macro_context": ctx,
}
print(json.dumps(result, indent=2))
return jsonify(result), 200
if __name__ == "__main__":
app.run(port=5050, debug=False)
Installez Flask et exécutez le serveur:
pip install flask
python webhook_server.py
Exposez le port local à l'internet avec leJe suis désolé .
ngrok http 5050
Dans TradingView, ouvre Alertes → Créer une alerte, sélectionnez votre condition de script Pine, activez
URL du réseau, et collez l' URL HTTPS ngrok se terminant par /tradingview/alert. Configurez le message d' alerte sur une charge utile JSON:
{
"currency": "eur",
"signal": "breakout_long",
"ticker": "{{ticker}}",
"price": {{close}}
}
Chaque fois que la condition Pine Script est déclenchée, TradingView affiche ce JSON à votre point final. Le gestionnaire de webhook récupère le dernier taux de politique EUR et l'IPC de FXMacroData et enregistre le contexte macro complet avec le signal. Vous pouvez étendre cela pour envoyer une notification Telegram ou Slack à l'aide des données enrichies.
Conseils de production
Pour un déploiement permanent, hôte webhook_server.py sur une machine virtuelle cloud, Railway ou Render. Utilisez une variable d'environnement pour FXMD_API_KEY et ajouter la vérification HMAC de base sur la charge utile webhook pour éviter les alertes falsifiées. /tradingview/alert/SECRET_TOKENLe plus simple des gardes.
- Pas 7 - Je suis désolé
Étape 7 Extension avec positionnement COT et contexte de change au comptant
Pour un signal plus complet, ajoutez le positionnement de l'engagement des traders de la CFTC et le contexte de la tendance au comptant des devises de FXMacroData.
Positionnement de la COT pour les contrats à terme en euros:
curl "https://fxmacrodata.com/api/v1/cot/eur?api_key=YOUR_API_KEY&start=2024-01-01"
{
"currency": "eur",
"data": [
{
"date": "2025-03-18",
"net_noncommercial": 48320,
"long_noncommercial": 182500,
"short_noncommercial": 134180
}
]
}
Ajoutez une série de positionnement de filet COT à votre générateur de Pine Script en utilisant le même motif que l'étape 2.
net_noncommercial Les taux de change de la BCE sont en hausse de 0,1% par rapport à l'année précédente.
Tableau de bord du COT avant de l'intégrer dans votre indicateur.
Étendre le générateur Python pour inclure une section COT:
def fetch_cot(currency: str, start: str) -> list[dict]:
url = f"{BASE_URL}/cot/{currency}"
params: dict = {"start": start}
if API_KEY:
params["api_key"] = API_KEY
resp = requests.get(url, params=params, timeout=15)
resp.raise_for_status()
return resp.json().get("data", [])
def build_cot_pine_arrays(records: list[dict]) -> str:
ts_list = [str(int(datetime.fromisoformat(r["date"] + "T00:00:00+00:00").timestamp() * 1000)) for r in records]
net_list = [str(r.get("net_noncommercial", 0)) for r in records]
ts_str = ", ".join(ts_list)
net_str = ", ".join(net_list)
return f"""
var int[] _cot_ts = array.from({ts_str})
var float[] _cot_net = array.from({net_str})
"""
Dans le script Pine, l'intrigue _cot_net dans un panneau séparé (ensemble overlay=false Pour ce type d'indicateur, vous pouvez voir la tendance du positionnement spéculatif en même temps que les annonces de prix et macro.
- Résumé final
Ce que vous avez construit
- ✅ Un script Python qui récupère les annonces FXMacroData et génère des littéraux de tableau de Pine Script
- ✅ Un indicateur Pine Script v5 qui marque les dates des événements macro sur votre graphique TradingView avec des étiquettes, un superposition de ligne étape et un tableau de données
- ✅ Un script de rafraîchissement automatisé qui vérifie les nouvelles impressions avant chaque session et régénère les tableaux Pine en cas de besoin
- ✅ Un point de terminaison webhook Flask qui reçoit les alertes TradingView et les enrichit avec le contexte macro en direct de FXMacroData
- ✅ Une extension de positionnement COT qui ajoute du sentiment spéculatif à l'image
Les prochaines étapes: Étendre le gestionnaire de webhook pour publier sur Telegram ou Slack, ajouter une vérification de calendrier de sortie afin que l'indicateur se démarque à venir Les taux de change des deux devises (par exemple, les taux directeurs de l'EUR et de l"USD) sont calculés en fonction des événements et des évènements passés, ou en combinant deux devisas (par ex. les taux de référence de l'"EUR" et du "USD") pour obtenir un écart de taux sur l'euro/USD. /api-data-docs Il est temps de le faire. Pour trouver la série macro qui correspond le mieux à votre stratégie.