TradingView adalah platform grafik pilihan bagi sebagian besar pedagang FX ritel, dan Pine Script adalah bahasa yang membawa indikator kustom dan sinyal strategi ke kehidupan pada grafik tersebut. Tantangannya adalah bahwa Pine Script berjalan sepenuhnya di dalam kotak pasir TradingVview tidak dapat melakukan panggilan HTTP keluar ke API eksternal pada saat runtime. Panduan ini menjembatani kesenjangan itu dengan alur kerja dua bagian: skrip Python kecil mengambil data pengumuman makro dari FXMacroData, menghasilkan kode Pine Script siap tempel, dan indikator yang dihasilkan menumpuk poin data tersebut langsung ke grafik TradingVisual Anda dengan penanda acara, garis sinyal, dan tabel data makro langsung.
Apa yang akan Anda bangun
- Skrip Python yang mengambil kebijakan tingkat, CPI, dan PMI pengumuman untuk mata uang apa pun dari FXMacroData dan menghasilkan kode sumber Pine Script secara otomatis
- Sebuah indikator Pine Script v5 yang menandai tanggal peristiwa makro pada grafik Anda dengan berlian berlabel, menggambar garis overlay nilai makro dan menunjukkan tabel data yang merangkum beberapa cetakan terakhir
- Peringatan TradingView → jembatan webhook yang pings titik akhir Flask kecil setiap kali kondisi Pine Script Anda menembak, memungkinkan Anda untuk merintangi referensi sinyal dengan konteks FXMacroData segar secara otomatis
Persyaratan
- Python 3.10+ dengan
requestsdipasang - Kunci API FXMacroData daftar di /langganan; Data indikator USD gratis tanpa kunci yang diperlukan
- Akun TradingView tingkat gratis mendukung Pine Script v5 dan indikator khusus
- Keterampilan dasar dalam menulis huruf Pine yang Pine Script v5 docs membahas konsep-konsep inti dalam waktu kurang dari satu jam
- Langkah 1 -
Langkah 1 Memahami titik akhir pengumuman FXMacroData
Setiap indikator di FXMacroData mengikuti bentuk REST yang sama. Permintaan kebijakan tingkat untuk EUR terlihat seperti ini menggunakan kunci API Anda sebagai parameter kueri:
curl "https://fxmacrodata.com/api/v1/announcements/eur/policy_rate?api_key=YOUR_API_KEY&start=2023-01-01"
Tanggapan JSON adalah objek datar dengan data array:
{
"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"
}
]
}
Setiap rekaman membawa date (Tahun-Tahunan-MM-DD tanggal lokal rilis), angka val, dan tingkat kedua UTC announcement_datetime. Bentuk yang konsisten di semua mata uang dan indikator adalah apa yang membuat generator kode mudah dibuat. Docs suku bunga kebijakan EUR dan jelajahi katalog indikator untuk mata uang target Anda.
- Langkah 2 -
Langkah 2 Mengambil data makro dengan Python
Buat file bernama generate_pine.py. Skrip ini mengambil data pengumuman untuk mata uang dan indikator yang dipilih, kemudian serialisasi hasil ke dalam array Pine Script yang Anda tempel ke dalam file indikator.
"""
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()
Simpan kunci API Anda dan jalankan skrip:
export FXMD_API_KEY="YOUR_API_KEY"
python generate_pine.py --currency eur --indicator policy_rate --start 2023-01-01
File output pine_data_eur_policy_rate.txt Anda dapat menjalankan skrip yang sama untuk CPI (--indicator inflation), PMI (--indicator pmi), atau indikator lain dari
Katalog FXMacroData.
- Langkah 3 -
Langkah 3 Buat indikator Pine Script
Buka TradingView, navigasi ke editor Pine Script (tab "Pine Editor" di bagian bawah grafik), dan tempelkan indikator berikut. _ann_ts Dan _ann_val array di bagian atas dengan output dari Langkah 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)
Kenapa? steplineApa yang kau lakukan?
Nilai indikator makro adalah fungsi langkah suku bunga kebijakan tidak terinterpolasi dengan lancar antara pertemuan; itu melompat. plot.style_stepline menjaga overlay jujur: garis mempertahankan tingkatnya sampai pengumuman baru dicetak, persis sesuai dengan data yang diterbitkan.
Klik Tambahkan ke grafik. Indikator akan menumpuk garis langkah yang sesuai dengan perkembangan nilai makro dan menjatuhkan penanda berlian berlabel pada setiap tanggal pengumuman. Gulir kembali melalui sejarah untuk melihat bagaimana setiap cetakan suku bunga kebijakan selaras dengan aksi harga pada pasangan mata uang yang Anda pilih.
- Langkah 4 -
Langkah 4 Lapisan dalam beberapa indikator
Satu indikator menceritakan bagian dari cerita. tepi nyata berasal dari lapisan kebijakan tingkat, CPI, dan PMI bersama-sama. Ulangi Langkah 2 untuk setiap indikator dan tambahkan bagian tambahan ke Pine Script, atau membuat tiga indikator terpisah dan menumpuk mereka di panel grafik yang sama.
Untuk mengambil tiga indikator dalam satu langkah, memperluas skrip 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)")
Setiap file output memberi Anda bagian drop-in untuk indikator Pine Script yang terpisah. Tambahkan masing-masing ke grafik Anda dan atributkan warna yang berbeda untuk setiap indikator misalnya, oranye untuk kebijakan suku bunga, biru untuk CPI, dan hijau untuk PMI sehingga Anda dapat melihat sekilas mana rezim makro yang berlaku. Anda dapat menjelajahi semua indikator yang tersedia untuk EUR melalui Dokumen PMI EUR dan katalog indikator yang lebih luas.
- Langkah 5 -
Langkah 5 Mengotomatiskan pembaruan dengan pemeriksaan kalender rilis
Data makro dalam array Pine Script menjadi usang saat pengumuman baru dicetak. Otomatiskan pembaruan dengan menelepon titik akhir kalender rilis FXMacroData sebelum setiap sesi perdagangan untuk memeriksa apakah ada yang dicetak sejak regenerasi terakhir Anda. Jika demikian, jalankan kembali generator dan perbarui Pine Script Anda.
"""
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()
Jadwalkan skrip ini untuk berjalan SeninJumat pukul 08:00 UTC, sebelum London dibuka, menggunakan pekerjaan cron, alur kerja GitHub Actions, atau penjadwal tugas lainnya.
pine_data_*.txt konten ke dalam Editor Pine TradingView dan klik Simpan. Tanda grafik Anda akan segera mencerminkan data pengumuman terbaru .
- Langkah 6 -
Langkah 6 Kirim peringatan TradingView kembali ke konteks FXMacroData
Aliran kerja sejauh ini mendorong data makro ke dalam Langkah 6 menutup loop ke arah yang lain: ketika Pine Script Anda menembakkan sinyal perdagangan (misalnya, pecah di atas resistensi setelah cetak CPI), sistem peringatan webhook TradingView meneruskan peristiwa itu ke titik akhir Flask kecil, yang segera menanyakan FXMacroData untuk konteks baru tren CPI terbaru, rilis mendatang, dan posisi COT saat ini dan log atau memberi tahu Anda dengan gambaran makro lengkap.
Ciptakan webhook_server.py:
"""
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)
Instal Flask dan jalankan server:
pip install flask
python webhook_server.py
Mengeksposisi port lokal ke internet dengan ngrokAku tidak tahu.
ngrok http 5050
Di TradingView, buka Peringatan → Buat Peringatan, pilih kondisi Pine Script Anda, aktifkan
URL Webhook, dan tempel URL HTTPS ngrok yang berakhir dengan /tradingview/alert. Atur pesan peringatan ke muatan JSON:
{
"currency": "eur",
"signal": "breakout_long",
"ticker": "{{ticker}}",
"price": {{close}}
}
Setiap kali kondisi Pine Script dipicu, TradingView memposting JSON ke endpoint Anda. Webhook handler mengambil nilai kebijakan EUR terbaru dan CPI dari FXMacroData dan mencatat konteks makro penuh bersama sinyal. Anda dapat memperluas ini untuk mengirim pemberitahuan Telegram atau Slack menggunakan data yang diperkaya.
Tip produksi
Untuk penyebaran permanen, tuan rumah webhook_server.py menggunakan variabel lingkungan untuk FXMD_API_KEY TradingView tidak menandatangani webhook payload secara native, jadi rahasia Anda sendiri dibagikan di jalur URL (misalnya /tradingview/alert/SECRET_TOKEN) is the simplest
guard.
- Langkah 7 -
Langkah 7 Perluas dengan posisi COT dan konteks spot FX
Data pengumuman makro adalah satu lapisan dari gambaran. Untuk sinyal yang lebih lengkap, tambahkan posisi Komitmen Pedagang CFTC dan konteks tren spot FX dari FXMacroData.
Posisi COT untuk EUR futures:
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
}
]
}
Tambahkan seri posisi net COT ke generator Pine Script Anda menggunakan pola yang sama dengan Langkah 2.
net_noncommercial nilai menunjukkan bahwa pedagang spekulatif adalah net long EUR futures latar belakang sentimen yang menambah keyakinan ketika dikombinasikan dengan sinyal kebijakan ECB yang agresif.
Panel COT sebelum menyematkannya ke dalam indikator Anda.
Perluas generator Python untuk memasukkan bagian 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})
"""
Dalam Pine Script, plot _cot_net dalam panel terpisah (set overlay=false untuk indikator itu) sehingga Anda dapat melihat tren posisi spekulatif di samping harga dan pengumuman makro.
- RINGKASAN -
Apa yang kau bangun
- ✅ Skrip Python yang mengambil pengumuman FXMacroData dan menghasilkan array literal Pine Script
- ✅ Indikator Pine Script v5 yang menandai tanggal acara makro pada grafik TradingView Anda dengan label, overlay garis langkah, dan tabel data
- ✅ Skrip refresh otomatis yang memeriksa cetakan baru sebelum setiap sesi dan meregenerasi array Pine bila diperlukan
- ✅ Sebuah titik akhir webhook Flask yang menerima peringatan TradingView dan memperkaya mereka dengan konteks makro langsung dari FXMacroData
- ✅ Ekstensi posisi COT yang menambahkan sentimen spekulatif pada gambar
Langkah selanjutnya: Perluas webhook handler untuk posting ke Telegram atau Slack, tambahkan kalender rilis cek sehingga indikator menonjol yang akan datang Mengidentifikasi perbedaan suku bunga antara dua mata uang (misalnya, EUR dan USD) untuk menghasilkan overlay perbedaan suku /api-data-docs untuk menemukan rangkaian makro yang paling sesuai dengan strategi Anda.