先物分析向けCFTCポジションデータの取得
コード Machine Learning for Trading
サマリー
選択した先物商品について、週次のCFTCトレーダー別建玉報告データを取得し、各商品の履歴をParquetファイルとして保存する方法を説明します。COTレポートは火曜日時点のポジションを記録し、金曜日に公表されます。トレーダーの分類は金融先物と商品先物で異なります。取得データには報告日、建玉、買い建玉、売り建玉、ネットポジションが含まれ、先物調査のワークフローでポジションやセンチメントの特徴量として利用できます。
ダウンローダーでは商品と年の範囲を選ぶか、設定済みの商品リストと既定の日付範囲を使用できます。要求した商品コードを検証し、データが返されなかった商品を記録し、取得失敗を報告します。これは運用ガイドであり、COTシグナルの性能分析ではありません。バックテスト、予測の証拠、ポジション変化の解釈ルールは示していません。COTの観測値は週次のスナップショットであるため、特定のトレード戦略に対する適時性や有用性を立証するものではありません。
主なアイデア
- CFTCレポートは週次の先物ポジションのスナップショットであり、トレーダーの分類は市場とレポートの種類によって異なります。
- 出力にはレポート日ごとの建玉と、トレーダー区分別の買い、売り、ネットポジションが記録されます。
- 商品と年を選択でき、取得失敗と空の結果は別々に報告されます。
- 文書ではデータの取得と保存を説明しますが、COT特徴量がリターンを予測するかは検証していません。
タグ
全文
# cot_download.py
```py
#!/usr/bin/env python3
"""Download CFTC Commitment of Traders (COT) data.
CFTC publishes weekly COT reports (Tuesday snapshot, released Friday) showing
futures positioning broken down by trader type (dealers, asset managers,
leveraged money for financial futures; commercials, managed money for
commodities). The data is free and useful for sentiment/positioning features.
This downloader uses ``ml4t.data.cot.COTFetcher`` — which wraps the
``cot_reports`` library — to fetch per-product panels and writes one parquet
per product to ``$ML4T_DATA_PATH/futures/positioning/cot/{product}.parquet``. The
``load_cot()`` loader in ``data/futures/loader.py`` consumes these files.
Output layout under ``$ML4T_DATA_PATH/futures/positioning/cot/``::
{PRODUCT}.parquet one parquet per product code (e.g., ES.parquet)
Schema (columns vary by report type but include):
product exchange product code (ES, CL, GC, …)
report_type CFTC report that produced the row
report_date Tuesday snapshot date
open_interest total open interest
<trader>_long long positions per trader category
<trader>_short short positions per trader category
<trader>_net computed long − short per category
Usage::
# Default: all products in PRODUCT_MAPPINGS, 2020–current year
python data/futures/positioning/cot_download.py
# Restrict to a subset
python data/futures/positioning/cot_download.py --products ES,NQ,CL,GC
# Wider year range
python data/futures/positioning/cot_download.py --start-year 2010 --end-year 2024
# Override output root
python data/futures/positioning/cot_download.py --data-path /tmp/ml4t-data
"""
from __future__ import annotations
import argparse
from pathlib import Path
from ml4t.data.cot import PRODUCT_MAPPINGS, COTConfig, COTFetcher
from utils.downloading import resolve_data_dir
def main() -> int:
parser = argparse.ArgumentParser(
description="Download CFTC Commitment of Traders data",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"--products",
type=str,
default=None,
help=(
"Comma-separated product codes (default: all in PRODUCT_MAPPINGS). "
f"Available: {', '.join(sorted(PRODUCT_MAPPINGS.keys()))}"
),
)
parser.add_argument(
"--start-year",
type=int,
default=2020,
help="First calendar year to fetch (default: 2020)",
)
parser.add_argument(
"--end-year",
type=int,
default=None,
help="Last calendar year to fetch (default: current year)",
)
parser.add_argument(
"--data-path",
type=Path,
default=None,
help="Override output root (default: $ML4T_DATA_PATH)",
)
args = parser.parse_args()
if args.products:
products = [p.strip().upper() for p in args.products.split(",") if p.strip()]
unknown = [p for p in products if p not in PRODUCT_MAPPINGS]
if unknown:
print(f"ERROR: unknown product code(s): {', '.join(unknown)}")
print(f"Available: {', '.join(sorted(PRODUCT_MAPPINGS.keys()))}")
return 1
else:
products = sorted(PRODUCT_MAPPINGS.keys())
data_path = resolve_data_dir(args.data_path)
output_dir = data_path / "futures" / "positioning" / "cot"
output_dir.mkdir(parents=True, exist_ok=True)
config = COTConfig(
products=products,
start_year=args.start_year,
end_year=args.end_year,
storage_path=output_dir,
)
fetcher = COTFetcher(config)
print()
print(f"Output: {output_dir}")
print(f"Years: {config.start_year}–{config.end_year}")
print(f"Products: {len(products)} ({', '.join(products)})")
print()
written = 0
empty = 0
failed: list[str] = []
for i, product in enumerate(products, 1):
print(f" [{i}/{len(products)}] {product}…", end="", flush=True)
try:
df = fetcher.fetch_product(product)
except Exception as e:
failed.append(product)
print(f" FAILED ({e})")
continue
if df.is_empty():
empty += 1
print(" no rows returned")
continue
out_path = output_dir / f"{product}.parquet"
df.write_parquet(out_path)
written += 1
print(f" {len(df):,} rows → {out_path.name}")
print()
print(f"Wrote: {written} parquet(s)")
if empty:
print(f"Empty: {empty} product(s) returned no rows")
if failed:
print(f"Failed: {len(failed)} — {', '.join(failed)}")
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())
```出典を明記したうえで、ライセンスに従って全文を掲載しています。 ライセンス: MIT
この要約は原文をもとにStratmillのリサーチエージェントが作成したもので、出典の複製ではありません。