بيانات وضع COT تخبرك بما يفعله أكبر المشاركين المضاربة في أسواق العقود الآجلة للعملات بالمال الحقيقي كل أسبوع، دون تفسير. عندما تقوم بمواءمة إدخالات التداول الخاصة بك مع التحيز الاتجاهي للمواقع غير التجارية، فإنك تضيف مرشحًا ذو مغزى يفصل بين الإعدادات ذات الاحتمال العالي من الصفقات التي تسبح ضد التدفق المؤسسي المستنير.
يقدم هذا الدليل عملية كاملة: سحب بيانات COT من FXMacroData API ، وحساب المقاييس المشتقة من المفاتيح ، وبناء فلتر تحديد الموقع ، وتطبيقه على سير العمل الخاص بك. بحلول النهاية ، سيكون لديك فلتر يعمل على أساس Python يمكنك وضعها في أي استراتيجية FX.
ما الذي ستبنيه
- وظيفة بايثون التي تحصل على بيانات COT الأسبوعية لأي من العملات الثمانية المدعومة
- مقياس تطبيع الموقع الصافي (صافي كنسبة من الفائدة المفتوحة)
- مرشح تحديد المواقع متعدد الحالات مع عتبات قابلة للتكوين
- بوابة دخول التجارة التي تعيد إشارة اتجاهية:
long- لاshortأوneutral - خطوة عملية باستخدام EUR/USD كمثال عمل
الشروط المسبقة
- مفتاح FXMacroData API متاح في / اشتركيتم تضمين نقطة نهاية COT في جميع الخطط المدفوعة.
- بايثون 3.9+ مع
requestsمكتبة مثبتة (pip install requests) - معرفة أساسية بمصطلحات تقارير COT (المبادلات الطويلة غير التجارية، القصيرة، الفائدة المفتوحة). دليل تقرير COT للمتداولين في مجال العملات الأجنبية تغطي الأساسيات
- اختياريًا
pandasلخطوات التعامل مع البيانات (pip install pandas)
الخطوة 1 احضار بيانات 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
}
]
}
في بايثون، لف هذه المكالمة في مساعد يعيد قائمة البيانات مرتبة حسب التسلسل الزمني:
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 على أنها صفوف مئوية على مدار السنة الأخيرة. سنة واحدة طويلة بما فيه الكفاية لالتقاط دورة وضع كاملة لمعظم الأزواج الرئيسية دون تضمين تغييرات النظام التي هي قديمة جداً ليكون لها صلة. يمكنك توسيع النافذة إلى 23 سنوات للعملات ذات دورات وضع أبطأ مثل JPY أو CHF.
الخطوة 2 حساب مقاييس تحديد المواقع المشتقة
من الصعب مقارنة أعداد العقود الخام عبر العملات وعبر الزمن. يعني صافي طول 80،000 عقد شيء مختلف تمامًا في العقودي الآجلة للـ EUR (سوق سائلة كبيرة) مقابل الفرنك السويسري (الفائدة المفتوحة الأصغر). تحل مقاييس مشتقة اثنين هذا.
2 أ - الصرف الصافي كنسبة مئوية من الفائدة المفتوحة
تقسيم صافي الموقف غير التجاري من قبل إجمالي الفائدة المفتوحة ينتج نسبة طبيعية بين -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']})")
2ب - تحديد ترتيب النسبة المئوية
لمعرفة ما إذا كان الموقع الحالي متطرفاً، تحتاج إلى سياق تاريخي. net_pct في نافذة الاحتياطي، يحول عدد مطلق إلى نسبة مئوية (0 = أكثر الهبوطية في السجل، 100 = أكثر صعودية). نسبة المائة فوق 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 ٪: منطقة محايدة لا يجب أن تؤدي إشارات أخرى إلى رياح قوية
- % 025 غير التجارية هي مزدحمة قصيرة. يفضل دخول قصيرة في حين أن الاتجاه يحافظ؛ يضيف خطر الضغط على أي مفاجأة صعودية.
2ج. تحديد موقع الزخم
اتجاه الاتجاه مهم بقدر المستوى الحالي. إن الشبكة الطويلة التي تنمو هي إشارة مختلفة عن الشبكات الطويلة الذي تراجع أو بدأ في الانكماش. حساب التغيير في 4 أسابيع في net_pct لالتقاط الزخم:
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 قم ببناء فلتر الدخول
مع المقاييس الثلاثة في اليد، يمكنك بناء وظيفة تصفية تعيد إشارة اتجاهية لأي عملة. المنطق يجمع بين المستوى الحالي، السياق النسبي، واتجاه الزخم في بوابة واحدة.
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 تطبيق المرشح على إدخالات التداول
وظيفة الفلتر تعيد واحدة من ثلاث إشارات long- لا shortأو neutralالاستخدام المقصود هو كبوابة أمام إشارة الدخول الرئيسية: فقط اتخاذ إعدادات طويلة عندما يقول مرشح COT long أو neutral إذا كنت أكثر عدوانية) ، وتأخذ فقط الإعدادات القصيرة عندما يقول فلتر COT 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 يوم الجمعة ، واحفظ النتيجة في المؤخذة المؤقتة ، واستخدمها كبوابة تحيز ثابتة لجميع الإدخالات في الأسابيع التالية. استخدم وثائق نقطة نهاية COT للتحقق من توقيت الإفراج
الخطوة 5 توسيع إلى لوحة التحكم متعددة العملات
تشغيل المرشح عبر جميع العملات الثمانية المدعومة في وقت واحد يمنحك لوحة تحديد المواقع الأسبوعية. هذا مفيد لتحديد أزواج الفوركس التي لديها أوضح الرياح الدافعة التي يقودها المضارب وأي منها لتجنبها لأن التوضع يعمل ضد اتجاهك.
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
قراءة هذه اللقطة الفورية: يتم وضع العقود الآجلة غير التجارية طويلة على اليورو والدولار الأسترالي والفرنك السويسري والدولار النيوزيلندي؛ قصيرة على اليابان والدولار الأمريكي؛ و محايدة على السعودية والجنيه الإسترليني. سيجد المتداول الذي يدرس المدى الطويل لليابان والجنة الإسترالية كلتا الساقين مؤكدةً من خلال تدفق المضاربين. سيواجه المتداولة التي تدرس المدة الطويلة للدولار الأميركي والجنية والسلطرية رياحًا عكسية على الدولار الأمريكى وخلفية محايداً على السودان والجنين إعداد أضعف من منظور التوضيح.
الخطوة 6 الجمع بين COT مع طبقة تأكيد الماكرو
وتجمع أكثر الأجهزة قوة بين وضع أسعار العملات الأجنبية مع أساس ماكرو واحد على الأقل يدعم نفس الرسالة الاتجاهية. وتكون فروق أسعار الفائدة هي المكمل الطبيعي: إذا كان المضاربون يمتلكون أسعار طويلة لـ 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 و Macro
عندما يكون الموقع مزدحمًا للغاية على جانب واحد ولكن الأساسية الكلية تتحول ضده (على سبيل المثال ، العقود الآجلة الكبيرة القصيرة لـ JPY ولكن بنك اليابان يبدأ في التشديد) ، قد يكون النظام في مرحلة انتقالية. هذه هي الإعدادات التي تنتج أسرع وأكبر التحركات غالبًا في الاتجاه الذي يجبر على التغطية القصير أو التصفية الطويلة. في مثل هذه الحالات ، فإن فلتر COT وحده غير كاف؛ راقب التداول. تاريخ أسعار الفائدة السياسية للبنك المركزي على مقربة من أي تحول يمكن أن يؤدي إلى تحريك الموقع.
ملخص
لديك الآن فلتر إدخال كامل قائم على COT مبني على بيانات FXMacroData API الحية. يتكون سير العمل من ست خطوات:
- احضر سجلات COT الأسبوعية للعملة أو العملات التي تتداولها.
- حساب الصرف الصافي كنسبة مئوية من الفوائد المفتوحة لتطبيعها عبر العملات.
- رتب الموقع الحالي خلال السنة الأخيرة لتحديد الظروف القاسية أو المحايدة.
- احسبي الزخم لمدة 4 أسابيع لتأكدين إن كان التوجه في صالحك
- فتحة إدخالات التجارة الخاصة بك ضد إشارة المرشح المضي قدما فقط عندما يطابق محاذاة COT اتجاهك.
- اختياريًا الجمع مع فحص الفارق في المعدل للحصول على تأكيد من عاملين.
لوحة التحكم الكاملة متعددة العملات تعطيك لقطة أسبوعية من حيث يتم وضع أموال المضارب، حتى تتمكن من الدخول في الصفقات مع التدفق المؤسسي بدلا من ضدها. التضخم أو العمل النقاط النهائية لبناء نموذج درجة الكلية يزن كل الإشارات الثلاثة معاً الموقع، وفوارق الأسعار، ودفعة النمو/التضخم للحصول على صورة أكثر اكتمالاً للنظام.