Continuous Futures COT Python
Continuous futures and COT in Python
Futures researchers need two things together: clean daily bars for a continuous contract and weekly positioning from the Commitments of Traders report. FinzData provides 139 futures markets with every contract since 2007 and COT positioning since 1986 in the free tier. This guide shows how to build a back-adjusted continuous series, why adjustment matters for returns, and how to align Tuesday COT data published on Friday with daily bars without look-ahead bias.
What a continuous futures series is and roll methods
A continuous futures series stitches together individual contract months into one price history so you can study trends without gaps. Each futures contract expires, so a continuous series rolls from the expiring front month to the next liquid contract.
There are three common roll approaches. Unadjusted series simply concatenate contracts at the roll date, which creates artificial price jumps. Ratio-adjusted series scale historical prices by the roll ratio so the price is continuous at the roll point. Back-adjusted series add a constant offset to past prices so the series is continuous and returns are preserved.
FinzData continuous futures use back-adjustment by default. The offset is applied to the entire history before the roll, keeping daily returns identical to the raw contracts. That makes backtests and statistical models valid across roll dates.
- Back-adjusted: preserves returns, preferred for returns, volatility and strategy testing
- Ratio-adjusted: preserves price levels, useful for charting nominal levels
- Unadjusted: raw contract prices, useful for execution analysis
Researchers often keep both the back-adjusted series for modeling and the roll metadata for reporting. Having every contract since 2007 allows you to test alternative roll windows and verify the default adjustment.
Why back-adjustment matters for returns
Returns are the foundation of futures research. If a roll creates a price jump, unadjusted series generate spurious daily returns on roll days. Those artifacts distort Sharpe ratios, drawdowns and correlation estimates.
Back-adjustment removes the jump by shifting the prior contract's history up or down by the roll gap. The price level changes, but the point change on each day matches the contract that was traded, so P&L in points is preserved. Percentage returns computed from far-back adjusted prices can drift, which is why many researchers compute returns contract by contract or use ratio adjustment for percentage-based work.
Ratio adjustment scales past prices instead, which preserves percentage returns but not point changes. For academic work and portfolio construction, back-adjusted continuous futures are the standard.
When you need both price levels and returns, keep the back-adjusted series for modeling and store the roll dates separately for reporting. FinzData exposes roll metadata so you can audit every adjustment and reproduce results offline.
Consistent returns across rolls also matter for cross-asset analysis. Comparing futures to equities or bonds requires clean daily returns without artificial spikes introduced by contract expiration.
FinzData futures coverage for research
FinzData covers 139 futures markets with every contract since 2007. Daily bars are available for the full history, with 1-minute to daily granularity on paid plans. The Python client mirrors yfinance, so you can use import finzdata as yf and get pandas DataFrames for CSV export.
Pricing is one-time ownership, not metered usage. One market's full history starts at $29. All 139 markets as daily bars are $75, and every bar size for all markets is $195 as an add-on to a stock bundle or $295 on its own. You own the data permanently and can reproduce results offline.
All contracts are included, not just the front month. That means you can build custom roll logic, test alternative roll windows, and verify the default back-adjusted series. Intraday bars are stamped at the start of each interval in US Eastern time and minutes without trades are omitted, never forward-filled.
This coverage is designed for bars and positioning research, not tick-level execution. For CME tick and order-book data for execution research, providers such as Databento specialise in that domain as of October 2026, https://databento.com/pricing. For continuous series and COT alignment, FinzData provides the daily bars and positioning you need.
COT positioning since 1986 and aligning with daily bars
The Commitments of Traders report shows how commercial hedgers, large speculators and small traders are positioned. FinzData provides COT positioning since 1986, and the free tier covers the last 12 months, with weekly reports for major futures markets.
COT is published by the CFTC with a lag. The report reflects Tuesday open interest and is released on Friday. Using Friday's data as if it were known on Tuesday creates look-ahead bias. The correct workflow is to shift COT availability to the Friday release date and then merge it onto daily bars.
Alignment steps are simple. Pull daily continuous futures, pull weekly COT for the market, shift the COT index forward to the Friday publication date, and merge_asof onto daily bars with a backward direction. That ensures each trading day only sees COT that was actually public.
Once aligned, you can compute rolling COT indices, e.g., a 52-week normalized net non-commercial position, and study its relationship to returns, volatility regimes and trend persistence without leakage.
Keeping the publication lag explicit also helps when combining COT with macro releases and earnings. All signals should be aligned to their true availability date to avoid inflated backtest performance.
CODE: Merge continuous futures with COT in Python
import finzdata as yf
import pandas as pd
c = yf.Client()
# Back-adjusted continuous daily bars for E-mini S&P 500
es = c.futures("ES", continuous=True)
# Weekly COT for S&P 500, Traders in Financial Futures report
cot = c.cot(report="tff", market="SP500")
# COT reflects Tuesday data, published on Friday
cot = cot.copy()
cot.index = pd.to_datetime(cot.index)
cot.index = cot.index + pd.Timedelta(days=3) # shift to Friday release
cot = cot.sort_index()
# Merge COT onto daily bars without look-ahead
merged = pd.merge_asof(es.sort_index(), cot.sort_index(), left_index=True, right_index=True, direction="backward")
# Simple 52-week COT index: net non-commercial position normalized
if "NonCommercial_Net" in merged.columns:
merged["cot_52w"] = merged["NonCommercial_Net"].rolling(52).mean()
merged["cot_z"] = (merged["NonCommercial_Net"] - merged["cot_52w"]) / merged["NonCommercial_Net"].rolling(52).std()
print(merged.tail())Start free
Start building continuous futures and COT workflows today with the free tier. Get last 12 months of every dataset, 1,000 API calls per day, no credit card required.
Get a free API key at https://api.finzdata.com/ and explore samples and pricing.
Frequently asked questions
What is a continuous futures series?
A continuous futures series links individual contract months into one price history using rolls. Back-adjusted series shift past prices by the roll gaps, preserving point changes; ratio-adjusted series preserve percentage returns.
Back-adjusted vs ratio-adjusted vs unadjusted?
Back-adjusted adds a constant offset and preserves point changes. Ratio-adjusted scales prices and preserves percentage returns. Unadjusted concatenates contracts and creates jumps. Use back-adjusted for point-based P&L and ratio-adjusted for percentage returns.
Does FinzData include COT in the free tier?
Yes. The free tier includes the last 12 months of COT; full history goes back to 1986. Paid plans unlock full history and bulk export.
How do I avoid look-ahead bias with COT?
COT reflects Tuesday data and is published on Friday. Shift the COT index to the Friday release date and merge_asof onto daily bars with direction='backward' so each day only sees public data.
What futures coverage does FinzData offer?
139 futures markets with every contract since 2007. One market from $29; all 139 markets daily $75; every bar size $195 as an add-on or $295 on its own. One-time purchase you keep.