Live release feed
Sub-second macro releases for FX backtests
Point-in-time history
Official CPI, jobs, GDP, and central-bank events with point-in-time history.
$25/month 14-day free trial
Start Free Trial
Cara Menggunakan Data COT untuk Membuat Filter entri perdagangan FX image
Share headline card X LinkedIn Email
Download

Implementation

How-To Guides

Cara Menggunakan Data COT untuk Membuat Filter entri perdagangan FX

Panduan langkah demi langkah untuk menarik Komitmen CFTC dari data posisi Pedagang dari FXMacroData API, menghitung metrik posisi bersih, dan membangun filter arah yang menyelaraskan entri perdagangan dengan aliran institusional.

Juga tersedia dalam English
Share article X LinkedIn Email

Data posisi COT memberi tahu Anda apa yang dilakukan peserta spekulatif terbesar di pasar berjangka mata uang dengan uang riil setiap minggu, tanpa interpretasi.

Panduan ini berjalan melalui proses lengkap: menarik data COT dari FXMacroData API, menghitung metrik yang berasal kunci, membangun filter posisi, dan menerapkannya ke aliran kerja entri Anda.

Apa yang Akan Anda Bangun

  • Fungsi Python yang mengambil data COT mingguan untuk salah satu dari delapan mata uang yang didukung
  • Metrik normalisasi posisi bersih (net sebagai % dari bunga terbuka)
  • Filter penentuan posisi multi-kondisi dengan ambang batas yang dapat dikonfigurasi
  • Sebuah gerbang entri perdagangan yang mengembalikan sinyal arah: longAku akan pergi. short, atau neutral
  • Sebuah panduan praktis menggunakan EUR/USD sebagai contoh kerja

Persyaratan

  • Kunci API FXMacroData tersedia di /langganan. titik akhir COT termasuk dalam semua rencana berbayar.
  • Python 3.9+ dengan requests perpustakaan yang terinstal (pip install requests)).
  • Keterampilan dasar dalam terminologi laporan COT (non-komersial long, short, open interest). Panduan Laporan COT untuk Pedagang FX mencakup dasar-dasarnya.
  • Opsional, pandas untuk langkah-langkah manipulasi data (pip install pandas)).

Langkah 1 Mengambil Data COT dari API

FXMacroData COT Endpoint mengembalikan posisi non-komersial dan komersial mingguan untuk futures mata uang. Mata uang yang didukung adalah AUD, CAD, CHF, EUR, GBP, JPY, NZD, dan USD. Setiap catatan berisi jumlah kontrak panjang, pendek, dan bersih untuk peserta non-kommersial dan komersil, ditambah total bunga terbuka.

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

Jawaban JSON memiliki struktur ini:

{
  "currency": "eur",
  "data": [
    {
      "date": "2025-03-25",
      "noncommercial_long": 198432,
      "noncommercial_short": 61840,
      "noncommercial_net": 136592,
      "commercial_long": 68230,
      "commercial_short": 201860,
      "open_interest": 591400
    },
    {
      "date": "2025-03-18",
      "noncommercial_long": 185710,
      "noncommercial_short": 66320,
      "noncommercial_net": 119390,
      "commercial_long": 72140,
      "commercial_short": 189430,
      "open_interest": 578200
    }
  ]
}

Di Python, bungkus panggilan ini dalam pembantu yang mengembalikan daftar data yang disortir secara kronologis:

import requests
from datetime import date, timedelta

BASE_URL = "https://fxmacrodata.com/api/v1"
API_KEY  = "YOUR_API_KEY"


def fetch_cot(currency: str, lookback_days: int = 365) -> list[dict]:
    """Return COT weekly records for *currency* over the last *lookback_days* days."""
    start = (date.today() - timedelta(days=lookback_days)).isoformat()
    resp = requests.get(
        f"{BASE_URL}/cot/{currency.lower()}",
        params={"api_key": API_KEY, "start": start},
        timeout=15,
    )
    resp.raise_for_status()
    payload = resp.json()
    return sorted(payload["data"], key=lambda r: r["date"])


records = fetch_cot("eur")
print(f"Loaded {len(records)} COT records for EUR")
print("Latest:", records[-1])

Mengapa 12 Bulan Sejarah?

The filter thresholds in Step 3 are expressed as percentile ranks over the trailing year. One year is long enough to capture a full positioning cycle for most major pairs without including regime changes that are too old to be relevant. You can widen the window to 2–3 years for currencies with slower-moving positioning cycles like JPY or CHF.

Langkah 2 Menghitung Metrik Posisi Turunan

Jumlah kontrak mentah sulit dibandingkan di berbagai mata uang dan sepanjang waktu. panjang bersih 80.000 kontrak berarti sesuatu yang sangat berbeda dalam EUR futures (pasar besar, likuid) versus CHF (keuntungan terbuka yang lebih kecil).

2a. Posisi bersih sebagai persentase dari bunga terbuka

Membagi posisi bersih nonkomersial dengan total bunga terbuka menghasilkan rasio normalisasi antara -1 dan +1.

def net_pct_oi(records: list[dict]) -> list[dict]:
    """Add 'net_pct' field = noncommercial_net / open_interest to each record."""
    enriched = []
    for r in records:
        oi = r.get("open_interest") or 1  # guard against zero
        enriched.append({**r, "net_pct": r["noncommercial_net"] / oi})
    return enriched


records = net_pct_oi(records)
latest  = records[-1]
print(f"EUR net % OI: {latest['net_pct']:.3f}  ({latest['date']})")

2b. Posisi Percentile Rank

Untuk mengetahui apakah posisi saat ini ekstrem, Anda perlu konteks historis. net_pct within the trailing window converts an absolute number into a percentile (0 = most bearish on record, 100 = most bullish). A percentile above 75 indicates a crowded long; below 25 indicates a crowded short.

def percentile_rank(series: list[float], value: float) -> float:
    """Return the percentile rank of *value* within *series* (0–100)."""
    below = sum(1 for x in series if x < value)
    return below / len(series) * 100


net_series     = [r["net_pct"] for r in records]
current_net    = records[-1]["net_pct"]
pct_rank       = percentile_rank(net_series, current_net)

print(f"EUR positioning percentile: {pct_rank:.1f}th")

Menjelaskan Percentile Rank

  • 75th100th percentile: Tidak komersial yang penuh sesak panjang. Memihak entri panjang sementara tren memegang; menambahkan risiko pembalikan jika fundamental berubah.
  • 25th75th percentile: Zona netral. tidak kuat posisi angin belakang atau angin ke depan sinyal lainnya harus memimpin.
  • 0th25th percentile: Tidak komersial yang penuh dengan pendek. mendukung entri pendek sementara tren bertahan; menambahkan risiko memeras pada setiap kejutan bullish.

2c. Momentum Posisi

Arah tren penting seperti tingkat saat ini. Net long yang tumbuh adalah sinyal yang berbeda dari net long yang telah stabil atau mulai menyusut. Hitung perubahan 4 minggu di net_pct untuk menangkap momentum:

def positioning_momentum(records: list[dict], periods: int = 4) -> float:
    """Return the change in net_pct over the last *periods* weeks."""
    if len(records) < periods + 1:
        return 0.0
    return records[-1]["net_pct"] - records[-(periods + 1)]["net_pct"]


momentum = positioning_momentum(records)
print(f"EUR 4-week positioning change: {momentum:+.3f}")

Langkah 3 Buat Filter Masuk

Dengan tiga metrik di tangan, Anda dapat membangun fungsi filter yang mengembalikan sinyal arah untuk mata uang apa pun. Logika menggabungkan tingkat saat ini, konteks persentil, dan arah momentum ke dalam satu gerbang.

def cot_entry_filter(
    currency: str,
    lookback_days: int = 365,
    long_pct_threshold: float = 55.0,
    short_pct_threshold: float = 45.0,
    momentum_min: float = 0.005,
) -> dict:
    """
    Return a COT positioning signal for *currency*.

    Parameters
    ----------
    currency            : ISO currency code (AUD, CAD, CHF, EUR, GBP, JPY, NZD, USD)
    lookback_days       : history window for percentile calculation
    long_pct_threshold  : minimum percentile to confirm a long bias
    short_pct_threshold : maximum percentile to confirm a short bias
    momentum_min        : minimum absolute 4-week change to confirm momentum

    Returns
    -------
    dict with keys: currency, signal, net_pct, percentile, momentum, date
    """
    records  = fetch_cot(currency, lookback_days)
    records  = net_pct_oi(records)
    latest   = records[-1]

    net_series = [r["net_pct"] for r in records]
    pct_rank   = percentile_rank(net_series, latest["net_pct"])
    momentum   = positioning_momentum(records)

    if pct_rank >= long_pct_threshold and momentum >= momentum_min:
        signal = "long"
    elif pct_rank <= short_pct_threshold and momentum <= -momentum_min:
        signal = "short"
    else:
        signal = "neutral"

    return {
        "currency"   : currency.upper(),
        "signal"     : signal,
        "net_pct"    : round(latest["net_pct"], 4),
        "percentile" : round(pct_rank, 1),
        "momentum"   : round(momentum, 4),
        "date"       : latest["date"],
    }


result = cot_entry_filter("eur")
print(result)

Output sampel ketika EUR non-komersial berjalan panjang penuh dan menambahkan ke itu:

{
  "currency"  : "EUR",
  "signal"    : "long",
  "net_pct"   : 0.231,
  "percentile": 82.4,
  "momentum"  : 0.018,
  "date"      : "2025-03-25"
}

Langkah 4 Terapkan Filter untuk entri perdagangan

Fungsi filter mengembalikan salah satu dari tiga sinyal longAku akan pergi. short, atau neutral. Penggunaan yang dimaksudkan adalah sebagai gerbang di depan sinyal masuk utama Anda: hanya mengambil pengaturan panjang ketika filter COT mengatakan long (atau neutral Jika Anda lebih agresif), dan hanya mengambil pengaturan singkat ketika filter COT mengatakan shortAku tidak tahu.

def should_enter_trade(
    currency: str,
    proposed_direction: str,
    allow_neutral: bool = False,
) -> bool:
    """
    Return True if COT positioning supports *proposed_direction* for *currency*.

    Parameters
    ----------
    currency           : ISO currency code
    proposed_direction : 'long' or 'short'
    allow_neutral      : if True, a 'neutral' COT signal does not block entry
    """
    cot = cot_entry_filter(currency)
    if cot["signal"] == proposed_direction:
        return True
    if allow_neutral and cot["signal"] == "neutral":
        return True
    return False


# Example: checking whether to enter a EUR/USD long
currency = "eur"   # base currency of the pair
direction = "long"

if should_enter_trade(currency, direction):
    print(f"COT confirms {direction} bias for {currency.upper()} — proceed to entry check")
else:
    print(f"COT filter blocked {direction} entry for {currency.upper()}")

Catatan Pelaksanaan: COT adalah sinyal mingguan

Data COT dirilis setiap hari Jumat untuk posisi mulai hari Selasa sebelumnya. Itu membuatnya menjadi sinyal frekuensi rendah cocok untuk menyaring bias mingguan atau harian, bukan entri intraday. Jalankan kembali filter sekali seminggu setelah rilis ET jam 3:30 malam Jumat, cache hasilnya, dan gunakan sebagai gerbang bias statis untuk semua entri pada minggu berikutnya. Dokumen titik akhir COT untuk memverifikasi waktu rilis.

Langkah 5 Perluas ke Dashboard Multi-Valuasi

Mengoperasikan filter di semua delapan mata uang yang didukung sekaligus memberi Anda dasbor posisi mingguan. Ini berguna untuk mengidentifikasi pasangan FX mana yang memiliki angin belakang yang paling jelas didorong oleh spekulator dan mana yang harus dihindari karena posisi bekerja melawan arah Anda.

CURRENCIES = ["aud", "cad", "chf", "eur", "gbp", "jpy", "nzd", "usd"]

def cot_dashboard() -> list[dict]:
    """Return COT positioning signals for all supported currencies."""
    results = []
    for ccy in CURRENCIES:
        try:
            result = cot_entry_filter(ccy)
            results.append(result)
        except Exception as exc:
            print(f"Warning: could not load {ccy.upper()} COT data — {exc}")
    return results


dashboard = cot_dashboard()
for row in dashboard:
    bar = "▲" if row["signal"] == "long" else ("▼" if row["signal"] == "short" else "–")
    print(f"{row['currency']:4s}  {bar} {row['signal']:8s}  pct={row['percentile']:5.1f}  mom={row['momentum']:+.3f}")

Hasil sampel mingguan:

AUD   ▲ long      pct= 71.2  mom=+0.012
CAD   – neutral   pct= 53.8  mom=-0.004
CHF   ▲ long      pct= 68.4  mom=+0.008
EUR   ▲ long      pct= 82.4  mom=+0.018
GBP   – neutral   pct= 48.1  mom=-0.002
JPY   ▼ short     pct= 19.6  mom=-0.022
NZD   ▲ long      pct= 63.0  mom=+0.007
USD   ▼ short     pct= 22.1  mom=-0.015

Membaca gambar ini: non-komersial adalah posisi EUR, AUD, CHF, dan NZD berjangka panjang; JPY dan USD pendek; dan netral pada CAD dan GBP. Seorang pedagang yang mempertimbangkan EUR/JPY panjang akan menemukan kedua kaki dikonfirmasi oleh arus spekulator. Seorang trader yang mempertimbangkan USD/CAD panjang akan menghadapi COT headwind pada USD dan latar belakang netral di CAD pengaturan yang lebih lemah dari perspektif posisi.

Langkah 6 Gabungkan COT dengan lapisan konfirmasi makro

Jika spekulan EUR panjang dan diferensial suku bunga ECB-Fed meluas menguntungkan EUR, posisi dan kasus fundamental sejajar.

Gunakan titik akhir suku bunga kebijakan untuk menarik nilai tukar terbaru untuk setiap mata uang dan menghitung diferensial:

def fetch_latest_rate(currency: str) -> float | None:
    """Return the most recent policy rate for *currency* as a float."""
    resp = requests.get(
        f"{BASE_URL}/announcements/{currency.lower()}/policy_rate",
        params={"api_key": API_KEY, "limit": 1},
        timeout=15,
    )
    if resp.status_code != 200:
        return None
    data = resp.json().get("data", [])
    return data[0]["val"] if data else None


def rate_differential(base_ccy: str, quote_ccy: str) -> float | None:
    """Return base_rate − quote_rate, or None if either rate is unavailable."""
    base_rate  = fetch_latest_rate(base_ccy)
    quote_rate = fetch_latest_rate(quote_ccy)
    if base_rate is None or quote_rate is None:
        return None
    return base_rate - quote_rate


def combined_filter(base_ccy: str, quote_ccy: str, direction: str) -> dict:
    """
    Return a combined COT + rate-differential signal for a currency pair.

    direction : 'long' (buy base) or 'short' (sell base)
    """
    cot_base   = cot_entry_filter(base_ccy)
    cot_quote  = cot_entry_filter(quote_ccy)
    diff       = rate_differential(base_ccy, quote_ccy)

    # For a long (buy base): we want long bias on base AND short/neutral on quote
    if direction == "long":
        cot_ok   = cot_base["signal"] == "long" and cot_quote["signal"] != "long"
        macro_ok = diff is not None and diff > 0
    else:
        cot_ok   = cot_base["signal"] == "short" and cot_quote["signal"] != "short"
        macro_ok = diff is not None and diff < 0

    return {
        "pair"       : f"{base_ccy.upper()}/{quote_ccy.upper()}",
        "direction"  : direction,
        "cot_ok"     : cot_ok,
        "macro_ok"   : macro_ok,
        "confirmed"  : cot_ok and macro_ok,
        "cot_base"   : cot_base,
        "cot_quote"  : cot_quote,
        "rate_diff"  : round(diff, 4) if diff is not None else None,
    }


signal = combined_filter("eur", "jpy", "long")
print("Confirmed:", signal["confirmed"])
print("COT base :", signal["cot_base"]["signal"], "| COT quote:", signal["cot_quote"]["signal"])
print("Rate diff :", signal["rate_diff"])

Ketika COT dan Makro Tidak Setuju

Ketika posisi sangat padat di satu sisi tetapi fundamental makro bergeser menentangnya (misalnya, berjangka JPY pendek besar tetapi Bank of Japan mulai mengetatkan), rezim mungkin sedang transisi. Ini adalah pengaturan yang menghasilkan pergerakan tercepat dan terbesar seringkali ke arah yang memaksa penutup pendek atau likuidasi panjang. Dalam kasus seperti itu, filter COT saja tidak cukup; pantau Sejarah suku bunga kebijakan bank sentral dekat untuk setiap pergeseran yang bisa memicu posisi unwind.

Ringkasan

Anda sekarang memiliki filter entri berbasis COT lengkap yang dibangun pada data FXMacroData API langsung.

  1. Dapatkan catatan COT mingguan untuk mata uang atau mata uang yang Anda perdagangan.
  2. Menghitung posisi bersih sebagai persentase bunga terbuka untuk normalisasi di seluruh mata uang.
  3. Peringkat posisi saat ini dalam tahun terakhir untuk mengidentifikasi kondisi ekstrem atau netral.
  4. Hitung momentum 4 minggu untuk memastikan apakah posisi sedang berlari menguntungkanmu.
  5. Gerbang entri perdagangan Anda terhadap sinyal filter hanya melanjutkan ketika keselarasan COT sesuai arah Anda.
  6. Opsional menggabungkan dengan pemeriksaan tingkat-perbedaan untuk konfirmasi dua faktor.

Dashboard multi-mata uang penuh memberi Anda gambaran mingguan di mana uang spekulan diposisikan, sehingga Anda memasuki perdagangan dengan aliran institusional daripada melawan itu. inflasi atau pekerjaan titik akhir untuk membangun model skor makro yang mempertimbangkan ketiga sinyal bersama-sama posisi, perbedaan suku bunga, dan momentum pertumbuhan/inflasi untuk gambaran yang lebih lengkap.

Blogroll

AI Answer-Ready

Key Facts

Page
How To COT Data FX Trade Filter
Section
Articles
Canonical URL
https://fxmacrodata.com/id/articles/how-to-cot-data-fx-trade-filter
Source
FXMacroData editorial and official publisher references
Last Updated
2026-06-15 11:06 UTC

Provenance And Trust

Cite the canonical URL and source field above. Where available, this page maps to official publisher releases and timestamped updates.

Quick Q&A

What is this page about? This page explains How To COT Data FX Trade Filter with directly usable context for trading, research, and API workflows.

What source should be cited? Use the canonical URL and the listed source field; cite official publisher references when available.

How fresh is this content? The last updated value above reflects the page metadata or latest available data timestamp.

Can this be used in AI assistants? Yes. This section is intentionally structured for retrieval and citation in chat assistants.

Prompt Packs

Use these in ChatGPT, Claude, Gemini, Mistral, Perplexity, or Grok for consistent source-aware outputs.