Skip to content

COTAnalysis

Victor Kaiuki edited this page Jun 20, 2026 · 2 revisions

COTAnalysis

The COTAnalysis class computes metrics on fetched COT data.

from cftc_cot import COTAnalysis

# df comes from client.execute()
analysis = COTAnalysis(df, classification="legacy")

# Compute
df = analysis.net_positions()
df = analysis.cot_index(window=156)

Note: On construction, rows are sorted ascending by report_date_as_yyyy_mm_dd when that column is present, so rolling and difference-based metrics are correct even though the client returns data newest-first. All methods are chainable in the sense that each enriches and returns the same internal DataFrame.

Methods

Method Description Columns added
.net_positions() Net (long − short) per category. {cat}_net
.z_scores(window=52) Rolling Z-scores of net positions. {cat}_net_zscore
.cot_index(window=156) Classic 0–100 COT Index over a rolling lookback. {cat}_net_cot_index
.extremes(threshold=0.9, window=156) Flags "bullish"/"bearish"/None from the COT Index. {cat}_net_extreme
.long_short_ratios() Long ÷ short per category. {cat}_ls_ratio
.percentile_rank(column) Percentile rank (0–1) of the most recent value. Returns a float.
.wow_change() Week-over-week change in net positions. {cat}_net_wow

Categories depend on the classification:

  • legacy: noncomm, comm
  • disaggregated: prod_merc, swap, m_money, other
  • tff: dealer, asset_mgr, lev_money, other

COT Index

The COT Index normalizes the current net position against its range over a rolling window:

100 * (net - rolling_min) / (rolling_max - rolling_min)

A reading near 100 is the most bullish positioning of the window; near 0, the most bearish. The default window=156 is ~3 years of weekly data, the conventional lookback. Rows without a populated range yet (e.g. the very first observation) are NaN.

df = analysis.cot_index(window=156)
print(df[['report_date_as_yyyy_mm_dd', 'noncomm_net_cot_index']].tail())

Extremes

df = analysis.extremes(threshold=0.9)
# noncomm_net_extreme == "bullish"  when COT index >= 90
# noncomm_net_extreme == "bearish"  when COT index <= 10

Clone this wiki locally