COTのポジショニングデータは,通貨先物市場の最大の投機的な参加者が毎週,解釈なしに,実際のお金で何をしているか教えてくれます. あなたが非商業ポジショনিংの方向性バイアスと取引エントリを調整すると,情報機関流量に対して泳いでいる取引から高い確率設定を分離する有意義なフィルターを追加します.
このガイドでは,COTデータをFXMacroData APIから抽出し,キー派生メトリックを計算し,ポジショニングフィルターを構築し,入力ワークフローに適用する.終了時までに,任意のFX戦略にスロットできる動作するPythonベースのフィルターを用意します.
あなた が 築く もの
- サポートされる8つの通貨のいずれかの週間のCOTデータを取得する Python関数
- 純定位標準化指標 (公開利息の%として)
- 設定可能な値を持つ多条件位置位置フィルター
- 方向信号を送る取引エントリゲート:
longほらshortほらneutral - EUR/USD を実例として使った実践的な説明
条件
- FXMacroData API キーを サイトで入手できます / サブスクリプト付与プランには,COTエンドポイントが含まれています.
- Python 3.9+ ほら ほろ
requestsインストールされたライブラリ (pip install requests) について - 基礎知識 (非商業的なロング,ショート,オープン・インテレスト) 外国為替取引者向けCOTレポートガイド 基本をカバーしています
- 選択的に
pandasデータ操作のステップ (pip install pandas) について
ステップ 1 APIからCOTデータを取得
FXMacroData COTエンドポイントは,通貨先物に対する週間の非商業および商業的ポジショニングを返します.サポートされる通貨はAUD,CAD,CHF,EUR,GBP,JPY,NZD,USDです.各レコードには,非商業的および商業的な参加者の長,短,純契約数,および総オープン利息が含まれます.
curl "https://fxmacrodata.com/api/v1/cot/eur?api_key=YOUR_API_KEY&start=2023-01-01"
JSON の応答は次の構造を持っています.
{
"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
}
]
}
Pythonでは,この呼び出しを時間順に並べたデータリストを返します.
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])
なぜ 12 か月 の 歴史 を 学ぶ の です か
ステップ3のフィルターしきい値は,後期の年度の百分位順で表される. 1年というのは,関連性を持つにはあまりにも古い体制変更を含まないほとんどの主要ペアにとって完全なポジショニングサイクルを把握するのに十分である.JPYやCHFのようなゆっくり動くポジショনিংサイクルを持つ通貨では,窓を2年3年まで拡大することができます.
ステップ2 導致位置測定値を計算する
通貨と時間によって原始契約数を比較するのは難しい. 80,000の契約の純長さは,CHF (より小さなオープン利息) とEUROの先物 (大きな流動市場) で非常に異なることを意味します. 2つの派生指標がこれを解決します.
2a 公開利息の割合としての純資産
非商業的な純資産を公募金利総数で割ると,−1から+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 パーセンチルランク位置付け
極端な立場なのかを知るには 歴史的な背景が必要です net_pct 値の値が75を超えると,満員ロング,25を下回ると満員ショートになります.
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")
百分位数 の 解釈
- 75 位から100 位まで 市場が長くなると 投資が長引く傾向が続くと 投資の逆転リスクが増加します
- 25 位75 位 中立地帯 強い位置付けの後風や逆風 他の信号は引かない
- 百分位数25位 取引対象でない取引は 短期取引が好ましい傾向が続く間 リスクが増加します
2c 位置付けの勢い
トレンド方向は現在のレベルと同じくらい重要です.成長しているネットロングは,平坦化または縮小し始めたネットロנגとは異なる信号です.勢力を把握するためにnet_pctの4週間の変化を計算します:
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}")
ステップ3 入力フィルターを構築する
この3つのメトリックを使って,任意の通貨の方向信号を返してくれるフィルター関数を構築できます.論理は,現在のレベル,百分位コンテキスト,モメント方向を1つのゲートに組み合わせます.
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)
EUR 非商業が混雑した長時間実行しているときにサンプル出力し,それに追加します:
{
"currency" : "EUR",
"signal" : "long",
"net_pct" : 0.231,
"percentile": 82.4,
"momentum" : 0.018,
"date" : "2025-03-25"
}
ステップ4 取引エントリにフィルターを適用する
フィルタ機能は,3つの信号のうちの1つを返します longほら shortほら neutral目的の使用は,あなたの主要な入力信号の前でゲートとして: COTフィルタが言うときだけ長いセットアップを取ります long (あるいは) neutral 短時間設定をする場合のみです. shortわかった
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()}")
実施要領:COTは週間の信号です.
COTデータは,前日の火曜日からのポジションのために毎週金曜日にリリースされます.これは,週間のまたは日々のバイアスをフィルタリングするのに適した低周波信号になります.日中のエントリではありません. 金曜日の午後3時30分ETリリース後に,週に一度フィルターを再実行し,結果をキャッシュし,次の週のすべてのエントリのための静的バイアスゲートとして使用します. 試験終了点のドキュメント リリースタイミングを検証する
ステップ 5 複数の通貨のダッシュボードに拡張
フィルターを8つのサポートされた通貨に同時に実行すると,毎週ポジショニングダッシュボードが表示されます.これは,どのFXペアが最も明確な投機家主導の後風を持っているか,そしてポジショনিংがあなたの方向性に反しているため,どれを避けるか特定するのに役立ちます.
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}")
サンプル毎週出力:
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
このスナップショットを読むと:非商業取引は,EUR,AUD,CHF,NZDの先物,JPYとUSDの先行取引が,CADとGBPの対価で中立である.EUR/JPYの先置取引を検討するトレーダーは,両足が投機家流によって確認されていることを発見する.USD/CADの先入取引を検討しているトレーダーはUSDの対向きのCOTとCADの中立の背景に直面する.
ステップ6 COTとマクロ確認層を組み合わせる
最も堅牢な設定は,COTのポジショニングと,同じ方向性論を裏付ける少なくとも1つのマクロファンドメナルの組み合わせです.レート差は自然な補完です.もし投機者がEURを長持ちし,ECBとFedのレート区分がEURの利害を拡大している場合,ポジショনিংとファンドメンタルのケースは一致します.
やってみろ 政策金利の最終点 各通貨の最新レートを抽出し,差を計算する
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"])
COT と マクロが 意見が一致しないとき
ポジショニングが一方的に非常に混雑しているとき,マクロファンドメンタルがそれに反対にシフトしている場合 (例えば,大きなショートJPY先物だが,日本銀行は引き締まり始めている) は,レジミンが移行している可能性があります.これらは,ショートカバーまたはロング清算を強制する方向で最も速く最大の動きを生み出すセットアップです.そのような場合,COTフィルタだけでは不十分です. 中央銀行の政策金利の歴史 位置を移動させるため 近づいて見ろ
概要
実行されたFXMacroData APIデータに構築された完全なCOTベースのエントリフィルターがあります. ワークフローは6つのステップで構成されています:
- 取引中の通貨または通貨の毎週COT記録を取得します.
- 通貨間正常化のために,オープン利息の割合として純資産を計算する.
- 極限または中性条件を特定するために,過去1年以内に現在の位置をランク付けします.
- 4週間の動向を計算して ポジションが有利なのか確認します
- フィルター信号にゲートする取引エントリ COTのアライナメントがあなたの方向に一致するときにのみ実行します.
- 選択的に,二要素確認のために,レート差のチェックと組み合わせます.
投資家の資金がどこに位置しているかについて毎週スナップショットを表示します. そのため,取引は,それに対してではなく,機関的な流れに合わせて行われます. 次のステップとして,COTフィルターを インフレ ほら 雇用 全体のモデルを構築するために,マクロスコアモデルを構成するエンドポイントを構成し,この3つの信号を一緒に評価します.