Skip to content

CFTC Commitments of Traders

Two read-only tools over market-data-hub's CFTC Commitments of Traders (COT) positioning data: cftc_positioning_financial for financial futures (rates, FX, equity indices, credit) and cftc_positioning_commodities for commodity futures (energy, metals, agriculture). Each wraps exactly one hub reader and adds no behaviour beyond translating LLM-shaped arguments into the reader's own and turning the returned DataFrame into JSON-shaped records.

from lazybridge import Agent, LLMEngine
from lazytools.connectors.cftc_cot import CFTCPositioningTools

agent = Agent(name="positioning", engine=LLMEngine("deepseek-v4-flash"),
              tools=[CFTCPositioningTools(db_path="hub.duckdb")])

No extra to install — this connector needs market-data-hub on the path (it is not on PyPI; see the tools overview), and specifically the hub's cftc_cot source module and read_cftc_tff/read_cftc_legacy readers. If the hub installed on the machine predates that module, the tools raise an ImportError on first call rather than at import time — nothing here checks for it up front.

What it is, and what it is not

Read-only, with no write surface to gate. market-data-hub's own ingestion job owns pulling the CFTC's published reports and keeping this data current; these tools only ever read what is already there. Unlike the connectors that carry an allow_write/allow_refresh knob to opt into a mutating tool, there is nothing of the kind here — there is no write tool in this provider for a flag to gate, so none is offered.

Two reports, not one, because they cover different futures and split traders differently:

Tool Covers Trader breakdown Hub reader
cftc_positioning_financial Financial futures only — rates, FX, equity indices, credit Dealer / Asset Manager / Leveraged Money (the CFTC's Traders in Financial Futures, TFF, categories) read_cftc_tff
cftc_positioning_commodities Commodity futures only — energy, metals, agriculture Commercial / Non-Commercial (the CFTC's Legacy report categories) read_cftc_legacy

The two reports are not two views of the same data: a financial contract never appears in the Legacy split and a commodity contract never appears in the TFF one, and the trader categories themselves differ — TFF's dealer/asset-manager/leveraged-money breakdown has no equivalent in the coarser Legacy commercial/non-commercial split. Picking the wrong tool for a contract does not error, it just returns nothing, which is why each tool's description names the other as the alternative.

The tools

Both share the same signature and reply shape:

tools = CFTCPositioningTools(db_path="hub.duckdb")
tools.cftc_positioning_financial("2026-01-01", "2026-08-01", "EURO FX")
tools.cftc_positioning_commodities("2026-01-01", "2026-08-01")  # all commodity contracts
Parameter Meaning
start Inclusive first report date, YYYY-MM-DD. Required — an empty string raises ValueError before any import or hub call.
end Inclusive last report date, YYYY-MM-DD. Required, same rule as start.
contract_market_name Exact CFTC contract market name to filter on, or "" (the default) for every contract in that report. "" is translated to None before reaching the hub reader — the hub's own optional-argument convention, which an LLM tool schema cannot express directly.

The reply is a dict:

{
    "start": "2026-01-01",
    "end": "2026-08-01",
    "contract_market_name": "EURO FX",   # or None if no filter was given
    "returned": 34,
    "rows": [...],   # list[dict], one row per report date x contract
}

rows is the hub DataFrame converted with .to_dict(orient="records") — one plain dict per row, JSON-shaped for a model to read directly. Column names follow whichever report was queried (dealer/asset-manager/leveraged-money long/short/spread positions and percent-of-open-interest for TFF; commercial/ non-commercial long/short for Legacy), unchanged from what the hub reader returns.

Why these methods restate their arguments

The pattern is the same one EconCalendarTools documents: the hub readers' Python-facing optional parameters use None for "no filter", which does not translate reliably into an LLM tool schema — a model omitting an argument and a model passing null are not reliably distinguishable downstream. So these tools take required date strings and "" for an absent contract filter, and translate "" to None before calling the hub. They also bind db_path at construction time, since a model cannot supply or manage the underlying database connection itself.

Depends on the hub's cftc_cot source landing first

This connector wraps two functions — market_data_hub.reader.read_cftc_tff/read_cftc_legacy — that live in market-data-hub's own cftc_cot source module. That module is separate, parallel work in the hub repository; until it has shipped, the local imports inside each tool method (from market_data_hub.reader import read_cftc_tff, from market_data_hub.reader import read_cftc_legacy) will fail on whatever hub version is actually installed, even though this connector's own code and tests do not depend on it being present.