Futures#
A futures contract is a commitment to buy or sell an asset on the contract’s expiry date for a fixed price.
Investors use futures contracts to invest in an asset without ever buying or selling the asset itself. After buying a futures contract for some asset, an investor holds the contract until some point in time closer to its expiry date. Then the investor “rolls” the contract, trading it for another contract for the same asset, with a later expiry date.
Learn how to work with futures contracts on the SigTech platform.
Environment#
Import Python libraries and initialize the SigTech framework environment:
import datetime as dtm
import numpy as np
import pandas as pd
import sigtech.framework as sig
env = sig.init()
Learn more: Setting up the environment
Futures contract groups#
On the SigTech platform, a futures contract group (FCG) represents contracts issued by an exchange for the same asset, with sequential expiry dates.
Futures contract groups are instances of the FuturesContractGroup
class. This class contains common information for futures that belong to the same futures strip (i.e. the trading of multiple futures contracts with different expiration dates, traded as a single transaction).
To retrieve a futures contract group on the SigTech platform, pass its object name to the sig.obj.get
utility function:
# Zinc futures on London Metal Exchange
lx_fcg = sig.obj.get("LX COMDTY FUTURES GROUP")
# US Treasury bond futures
ty_fcg = sig.obj.get("TY COMDTY FUTURES GROUP")
# Frozen orange juice
jo_fcg = sig.obj.get("JO COMDTY FUTURES GROUP")
For most framework objects on the SigTech platform, you can use the data_dict
instance method to retrieve a collection of descriptive static data about the object.
Print the static data fields available for a futures contract group:
jo_fcg.data_dict().keys()
Define a function to print selected static data for a framework object:
def get_info(sig_obj, dd_keys):
if isinstance(sig_obj, str):
sig_obj = sig.obj.get(sig_obj)
info = f"{sig_obj.name}\n"
dd = sig_obj.data_dict()
for key in dd_keys:
_key = f"{key}:".ljust(25)
info += f"{_key} {dd[key]}\n"
info += "\n"
return info
Print select fields for some futures contract groups:
fcg_fields = [
"asset_description", "contract_code", "contract_sector",
"exchange_code", "item_product_type",
]
print(get_info(jo_fcg, fcg_fields))
print(get_info(ty_fcg, fcg_fields))
print(get_info(lx_fcg, fcg_fields))
List futures contracts in an FCG#
Each FCG has a set of futures contracts with sequential expiry dates. The object names of futures contracts in an FCG are made up of:
The FCG contract code
A year code: two numerical characters representing the contract year
A month code: an alphabetical character representing the contract month
Retrieve the object names of all futures contract instruments for an FCG:
jo_fcg.query_instrument_names()[:10]
View month codes for futures contracts#
To see all the futures month codes, use one of the following FCG class attributes:
sig.FuturesContractGroup.CONTRACT_MONTH_CODES_DICT
sig.FuturesContractGroup.CONTRACT_MONTH_CODES_LIST
print(sig.FuturesContractGroup.CONTRACT_MONTH_CODES_DICT)
print(sig.FuturesContractGroup.CONTRACT_MONTH_CODES_LIST)
Get contract months for an FCG#
For some futures products, only a subset of months per year have a futures contract.
Get an FCG’s contract months for a given year:
print(jo_fcg.month_codes_for_year(2020))
print(jo_fcg.month_codes_for_year(20))
print(jo_fcg.month_codes_for_year("2000"))
print(jo_fcg.month_codes_for_year("20"))
Futures contract instruments#
Futures contract instruments are instances of subclasses of the Future
class, such as BondFuture
or CommodityFuture
.
A futures contract instrument’s object name comprises:
The FCG contract code
A month code: an alphabetical character representing the contract month
A year code: two numerical charaters representing the contract year
For example:
contract = sig.obj.get("JOF23 COMDTY")
print(contract.name, contract.contract_month, contract.contract_year)
contract = sig.obj.get("KCH09 COMDTY")
print(contract.name, contract.contract_month, contract.contract_year)
contract = sig.obj.get("LXQ09 COMDTY")
print(contract.name, contract.contract_month, contract.contract_year)
contract = sig.obj.get("CON18 COMDTY")
print(contract.name, contract.contract_month, contract.contract_year)
Define a function to retrieve a futures contract instrument for a given contract code, month, and year:
def get_contract(contract_code, month, year, contract_sector="COMDTY"):
result = None
year_code = str(year)[-2:]
month_code = sig.FuturesContractGroup.CONTRACT_MONTH_CODES_LIST[int(month)-1]
try:
fcg = sig.obj.get(f"{contract_code} {contract_sector} FUTURES GROUP")
except:
pass
else:
if month_code in fcg.month_codes_for_year(year_code):
result = sig.obj.get(f"{contract_code}{month_code}{year_code} {contract_sector}")
return result
Retrieve some futures contract instruments:
contract = get_contract("JO", 1, 23)
print(contract.name, contract.contract_month, contract.contract_year)
contract = get_contract("KC", "03", "02")
print(contract.name, contract.contract_month, contract.contract_year)
contract = get_contract("LX", "12", 2012)
print(contract.name, contract.contract_month, contract.contract_year)
contract = get_contract("CO", 8, 12)
print(contract.name, contract.contract_month, contract.contract_year)
Alternatively, retrieve futures contract instruments from a futures contract group object.
Get the first futures contract for an FCG:
jo_first = sig.obj.get(jo_fcg.first_contract)
jo_first
Get the active futures contract for an FCG:
jo_active = jo_fcg.active_contract()
jo_active
From a futures contract instrument, get the next contract in the sequence:
jo_next = jo_active.next_contract()
jo_next.name
Retrieve time series data for a futures product#
View the available historical data fields for a futures contract instrument:
jo_active.activity_fields, jo_active.history_fields
Retrieve and plot historical performance data for a futures contract:
jo_active.history().plot()
Rolling future strategies#
Use the RollingFutureStrategy
class to create futures investment strategies. You can choose to roll your futures strategy over multiple days by setting the rolling_rule
parameter. Our page on roll schedules has a list of available rolling rules.
def create_rfs(contract_code, contract_sector="COMDTY"):
return sig.RollingFutureStrategy(
start_date=START_DATE,
end_date=END_DATE,
currency="USD",
contract_code=contract_code,
contract_sector=contract_sector,
rolling_rule="F_0",
)
Define some variables for the rolling future strategies:
START_DATE = dtm.date(2023, 1, 10)
END_DATE = dtm.date(2024, 1, 10)
index = pd.date_range(START_DATE, END_DATE, freq="D")
columns = ["LX", "KC", "JO"]
Create and compare some rolling future strategies:
df = pd.DataFrame(columns=columns, data={
code: create_rfs(code).history()
for code in columns
}, index=index).dropna()
df
Learn more: Rolling future strategies
Back-adjusted futures data#
You can use back-adjusted futures data to avoid triggering spurious trading signals during the roll.
Use the following parameters with an RFPriceIndex
object to specify back adjustment options:
back_adjusted
: Boolean; default isFalse
. WhenTrue
, the strategy uses back-adjusted data.back_adjustment_type
: String; default is"diff"
.When set to
"diff"
, the back adjustment is calculated by difference.When set to
"ratio"
, the back adjustment is calculated by ratio.
Define a function to create a back-adjusted price series:
def get_ba_series(contract_code, ba=False, ba_type=None, contract_sector="COMDTY"):
return sig.RFPriceIndex(
start_date=START_DATE,
end_date=END_DATE,
currency="USD",
contract_code=contract_code,
contract_sector=contract_sector,
front_offset="-4,-1",
back_adjusted=ba,
back_adjustment_type=ba_type,
)
Compare some back-adjusted data:
columns = ["None", "Diff", "Ratio"]
data = {
"None": get_ba_series("CO", False).history(),
"Diff": get_ba_series("CO", True).history(),
"Ratio": get_ba_series("CO", True, "ratio").history(),
}
ba_df = pd.DataFrame(columns=columns, data=data, index=index).dropna()
ba_df