Como integrar FXMacroData com TradingView através do Pine Script banner image

Implementation

How-To Guides

Como integrar FXMacroData com TradingView através do Pine Script

Um guia passo a passo para sobrepor os anúncios de macro FXMacroData, as taxas de política e o posicionamento COT nos gráficos TradingView usando um gerador de código Python e o Pine Script v5.

Também disponível em English

O TradingView é a plataforma de gráficos escolhida pela maioria dos traders de varejo FX, e o Pine Script é a linguagem que traz indicadores personalizados e sinais de estratégia para a vida nesses gráficos. O desafio é que o PineScript é executado inteiramente dentro da caixa de areia do TradingVIEW não pode fazer chamadas HTTP para API externas em tempo de execução. Este guia preenche essa lacuna com um fluxo de trabalho de duas partes: um pequeno script Python obtém dados de anúncio macro do FXMacroData, gera código Pine Script pronto para colar e o indicador resultante sobrepõe esses pontos de dados diretamente no gráfico do Trading VIEW com marcadores de eventos, uma linha de sinal e uma tabela de dados macro ao vivo.

O que você vai construir

  • Um script Python que recupera os anúncios de taxa de política, CPI e PMI para qualquer moeda do FXMacroData e gera código fonte Pine Script automaticamente
  • Indicador de Pine Script v5 que marca datas de eventos macro em seu gráfico com diamantes rotulados, desenha uma linha de sobreposição de valores macro e mostra uma tabela de dados que resume as últimas impressões
  • Alerta do TradingView → ponte do webhook que pings um pequeno ponto final Flask sempre que o seu Pine Script condição disparos, permitindo-lhe cruzar referência do sinal com o contexto FXMacroData fresco automaticamente

Requisitos prévios

  • Python 3.10+ Com requests instalado
  • Chave da API do FXMacroData Inscreva-se em / subscrever; os dados do indicador USD são gratuitos e não requerem chave
  • Uma conta TradingView a camada gratuita suporta o Pine Script v5 e indicadores personalizados
  • Familiarização básica com o Pine Script o Pine Script v5 docs cobrir os conceitos básicos em menos de uma hora

- Passo 1 -

Passo 1 Compreender o ponto final do anúncio FXMacroData

Cada indicador no FXMacroData segue a mesma forma REST. Uma solicitação de taxa de política para o EUR parece assim use sua chave API como um parâmetro de consulta:

curl "https://fxmacrodata.com/api/v1/announcements/eur/policy_rate?api_key=YOUR_API_KEY&start=2023-01-01"

A resposta JSON é um objeto plano com um data Arquivo:

{
  "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"
    }
  ]
}

Cada disco tem um date (AAAA-MM-DD data local de lançamento), numérica val, e um UTC de segundo nível announcement_datetimeA forma consistente em todas as moedas e indicadores é o que torna o gerador de códigos simples de construir. Docs de taxas de juro de política monetária e explore o catálogo de indicadores para a sua moeda-alvo.


- O passo 2 .

Passo 2 Obter dados de macro com Python

Crie um arquivo chamado generate_pine.pyEste script recupera dados de anúncio para uma moeda e indicador escolhido, em seguida, serializa os resultados em matrizes de Pine Script que você colar no arquivo do indicador.

"""
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()

Guarde a sua chave de API e execute o script:

export FXMD_API_KEY="YOUR_API_KEY"
python generate_pine.py --currency eur --indicator policy_rate --start 2023-01-01

O ficheiro de saída . pine_data_eur_policy_rate.txt Você pode executar o mesmo script para CPI (--indicator inflation), PMI (--indicator pmi), ou qualquer outro indicador do Catálogo FXMacroData- Não .


- Passo 3 -

Passo 3 Construir o indicador de Pine Script

Abra o TradingView, navegar para o editor de script de pinho (a guia "Pine Editor" na parte inferior do gráfico), e colar o seguinte indicador. _ann_ts E ... _ann_val matrizes no topo com a saída do passo 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)

Porquê ? stepline- Não .

Os valores dos indicadores macro são funções de passo a taxa de juro não interpola de forma suave entre as reuniões; salta. plot.style_stepline mantém a sobreposição honesta: a linha mantém o seu nível até que um novo anúncio seja impresso, correspondendo exatamente aos dados publicados.

Clique . Adicionar ao gráficoO indicador irá sobrepor uma linha de passo correspondente à progressão do valor macro e deixar cair um marcador de diamante rotulado em cada data de anúncio. Desloque-se através do histórico para ver como cada taxa de política de impressão alinhada com a ação de preço no par de moedas escolhido.


- Passo 4 -

Etapa 4 Capa em múltiplos indicadores

Um único indicador conta parte da história. A vantagem real vem da camada de taxa de política, IPC e PMI juntos. Repita o passo 2 para cada indicador e adicione uma seção adicional ao Pine Script, ou crie três indicadores separados e empilhe-os no mesmo painel de gráfico.

Para uma busca de três indicadores de uma só vez, estenda o 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)")

Cada ficheiro de saída dá-lhe uma secção de entrada para um indicador Pine Script separado. Adicione cada um ao seu gráfico e atribui uma cor distinta a cada indicador por exemplo, laranja para taxa de juro, azul para IPC e verde para PMI para que possa ver de uma só vez qual o regime macro em vigor. EUR PMI docs e o catálogo mais amplo de indicadores.


- Passo 5 -

Passo 5 Automatizar atualizações com uma verificação do calendário de lançamento

Os dados macro nas matrias do Pine Script ficam obsoletos no momento em que um novo anúncio é impresso. Automatize a atualização ligando para o ponto final do calendário de lançamento do FXMacroData antes de cada sessão de negociação para verificar se alguma coisa foi impressa desde a última regeneração. Se houver, re-execute o gerador e atualize o seu 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()

Agende este script para ser executado de segunda a sexta-feira às 08:00 UTC, antes da abertura de Londres, usando um cron job, um fluxo de trabalho do GitHub Actions ou qualquer agendador de tarefas. pine_data_*.txt conteúdo no Editor de Pinhos do TradingView e clique SalvarOs marcadores do gráfico vão refletir imediatamente os dados mais recentes.


- O passo 6 .

Passo 6 Enviar alertas do TradingView de volta para o contexto FXMacroData

O fluxo de trabalho até agora empurra dados macro em TradingView. Passo 6 fecha o ciclo na outra direção: quando o seu Pine Script dispara um sinal de negociação (por exemplo, uma quebra acima da resistência após uma impressão do IPC), o sistema de alerta do webhook do TradingVIEW encaminha esse evento para um pequeno endpoint Flask, que consulta imediatamente o FXMacroData para um contexto novo a última tendência do IPc, lançamentos futuros e posicionamento atual do COT e registra ou notifica com a imagem macro completa.

Criar . webhook_server.py- Não .

"""
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)

Instale o Flask e execute o servidor:

pip install flask
python webhook_server.py

Expõe a porta local à Internet com ngrok- Não .

ngrok http 5050

Em TradingView, abrir Alertas → Criar Alerta, selecione a condição do Pine Script, habilite URL do Webhook, e colar a URL HTTPS ngrok terminando com /tradingview/alert. Configure a mensagem de alerta para uma carga útil JSON:

{
  "currency": "eur",
  "signal": "breakout_long",
  "ticker": "{{ticker}}",
  "price": {{close}}
}

Cada vez que a condição Pine Script é ativada, o TradingView publica esse JSON no seu endpoint. O manipulador de webhook obtém a taxa de política EUR mais recente e o CPI do FXMacroData e registra o contexto macro completo ao lado do sinal. Você pode estender isso para enviar uma notificação Telegram ou Slack usando os dados enriquecidos.

Dica de produção

Para uma missão permanente, anfitrião. webhook_server.py Em uma nuvem VM, Railway, ou Render. FXMD_API_KEY TradingView não assina as cargas úteis do webhook de forma nativa, então o seu próprio segredo compartilhado no caminho do URL (por exemplo /tradingview/alert/SECRET_TOKENÉ o guarda mais simples.


- O passo 7 .

Passo 7 Extensão com posicionamento COT e contexto spot FX

Os dados de anúncio macro são uma camada da imagem. Para um sinal mais completo, adicione o posicionamento do Compromisso dos Traders da CFTC e o contexto da tendência spot FX do FXMacroData.

Posicionamento do Fetch COT para futuros de EUR:

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
    }
  ]
}

Adicionar uma série de posicionamento da rede COT para o seu gerador de Pine Script usando o mesmo padrão do passo 2. net_noncommercial A taxa de juro de mercado é a taxa de câmbio mais elevada do que a taxa nominal de câmpio. Painel de instrumentos COT antes de o incorporar no indicador.

Estender o gerador Python para incluir uma seção 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})
"""

Em Pine Script, trama. _cot_net num painel separado (conjunto overlay=false para esse indicador) para que possa ver a tendência de posicionamento especulativo ao lado dos anúncios de preços e macro.


- Resumo final - Resumindo

O que construíste

  • ✅ Um script Python que recupera anúncios FXMacroData e gera literais de arrays Pine Script
  • ✅ Um indicador de Pine Script v5 que marca datas de eventos macro no gráfico TradingView com rótulos, uma sobreposição de linha de passo e uma tabela de dados
  • ✅ Um script de atualização automático que verifica novas impressões antes de cada sessão e regenera as matrias Pine quando necessário
  • ✅ Um ponto final de webhook Flask que recebe alertas TradingView e os enriquece com contexto macro ao vivo do FXMacroData
  • ✅ Uma extensão de posicionamento COT que adiciona sentimento especulativo ao quadro

Próximos passos: Estender o webhook para postar no Telegram ou Slack, adicionar um calendário de lançamento para que o indicador destaque Próximo Os indicadores de preços são baseados em dados de preços, em valores de mercado e em valores dos mercados de valores. /api-data-docs para encontrar a série macro que melhor se encaixa na sua estratégia.

Blogroll