Link to home
Start Free TrialLog in
Avatar of J. Freeze
J. Freeze

asked on

Python: Building Continuous Futures Contract (How to iterate properly?)

I have a python script that will construct a list of futures contracts for a specified symbol, exchange, and year window.  The script will download pricing information from Quandl for each contract in the strip.  This script works properly.

import pandas as pd
from pandas import ExcelWriter
import quandl

symbol = 'ES'
exchange = 'CME/'

start_year = 2015
end_year = 2016


#Constructs a list of futures contract codes for a particular symbol
#and timeframe.
futures = []
months = 'HMUZ'
for y in range(start_year, end_year+1):
    for m in months:
        futures.append("%s%s%s%s" % (exchange, symbol, m, y))

#Download the data from Quandl.
for f in futures:
    quandl.ApiConfig.api_key = "xxxx"  
    data = quandl.get(str(f))
    data = data.drop(data.columns[[3, 4, 7]], axis=1)

I have another python script that will create a continuous futures contract from 2 consecutive contracts in the futures strip.  It uses the perpetual method; identifying the roll date as the first day where volume of the far contract exceeds volume of near contract, and then adjusts the prices of the previous 4 sessions to roll date by weighting the near and far contracts in increments/decrements of 20%.  This script works properly.

import pandas as pd
from pandas import ExcelWriter
import quandl

#Get quandl futures data
quandl.ApiConfig.api_key = "xxxx"    
contract_near = quandl.get("CME/ESH2015")
contract_far = quandl.get("CME/ESM2015")

#Drop the columns not needed
contract_near = contract_near.drop(contract_near.columns[[3, 4, 7]], axis=1)
contract_far = contract_far.drop(contract_far.columns[[3, 4, 7]], axis=1)

#Create combined data frame
combined = contract_near.merge(contract_far, left_index=True, right_index=True)

#Compare the volumes to get the roll date(s)
high_vol = combined['Volume_y'] > combined['Volume_x']
roll_date = high_vol[high_vol].index[0]

#Concatenate the correct dates from each contract
continuous = pd.concat([contract_near[contract_near.index < roll_date],
                        contract_far[contract_far.index >= roll_date]])

#Adjust the 4th session prior to roll date
continuous.iloc[(continuous.index.get_loc(roll_date))-4]['Open'] = \
                (.8 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-4]['Open']) + \
                (.2 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-4]['Open'])

continuous.iloc[(continuous.index.get_loc(roll_date))-4]['High'] = \
                (.8 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-4]['High']) + \
                (.2 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-4]['High'])
                                 
continuous.iloc[(continuous.index.get_loc(roll_date))-4]['Low'] = \
                (.8 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-4]['Low']) + \
                (.2 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-4]['Low'])
               
continuous.iloc[(continuous.index.get_loc(roll_date))-4]['Settle'] = \
                (.8 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-4]['Settle']) + \
                (.2 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-4]['Settle'])
               
#Adjust the 3rd session prior to roll date
continuous.iloc[(continuous.index.get_loc(roll_date))-3]['Open'] = \
                (.6 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-3]['Open']) + \
                (.4 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-3]['Open'])

continuous.iloc[(continuous.index.get_loc(roll_date))-3]['High'] = \
                (.6 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-3]['High']) + \
                (.4 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-3]['High'])
                                 
continuous.iloc[(continuous.index.get_loc(roll_date))-3]['Low'] = \
                (.6 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-3]['Low']) + \
                (.4 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-3]['Low'])
               
continuous.iloc[(continuous.index.get_loc(roll_date))-3]['Settle'] = \
                (.6 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-3]['Settle']) + \
                (.4 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-3]['Settle'])
               
#Adjust the 2nd session prior to roll date
continuous.iloc[(continuous.index.get_loc(roll_date))-2]['Open'] = \
                (.4 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-2]['Open']) + \
                (.6 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-2]['Open'])

continuous.iloc[(continuous.index.get_loc(roll_date))-2]['High'] = \
                (.4 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-2]['High']) + \
                (.6 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-2]['High'])
                                 
continuous.iloc[(continuous.index.get_loc(roll_date))-2]['Low'] = \
                (.4 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-2]['Low']) + \
                (.6 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-2]['Low'])
               
continuous.iloc[(continuous.index.get_loc(roll_date))-2]['Settle'] = \
                (.4 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-2]['Settle']) + \
                (.6 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-2]['Settle'])                
               
#Adjust the 1st session prior to roll date
continuous.iloc[(continuous.index.get_loc(roll_date))-1]['Open'] = \
                (.2 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-1]['Open']) + \
                (.8 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-1]['Open'])

continuous.iloc[(continuous.index.get_loc(roll_date))-1]['High'] = \
                (.2 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-1]['High']) + \
                (.8 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-1]['High'])
                                 
continuous.iloc[(continuous.index.get_loc(roll_date))-1]['Low'] = \
                (.2 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-1]['Low']) + \
                (.8 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-1]['Low'])
               
continuous.iloc[(continuous.index.get_loc(roll_date))-1]['Settle'] = \
                (.2 * contract_near.iloc[(contract_near.index.get_loc(roll_date))-1]['Settle']) + \
                (.8 * contract_far.iloc[(contract_far.index.get_loc(roll_date))-1]['Settle'])

# Output the continuous series of contract prices
print(continuous)

# Export to Excel File
instrName  = 'ES_Continuous'
out_path = "C:\\Users\\JamesFreeze\\Documents\\Technical Analysis\\Futures Data\\" + "%s" % instrName + ".xlsx"
writer = pd.ExcelWriter(out_path, engine='xlsxwriter')
continuous.to_excel(writer, "%s" % instrName)
writer.save()

What I would like to do is combine the functionality of the 2 scripts.  In other words, just specify the contract parameters (symbol, exchange, year window) and have the script build a continuous contract from start to finish.

Where I am having trouble conceptually is in properly coding the iterative process.  After the 1st iteration, how would I instruct python to use the continuous contract as the near contract?  For example, with ES futures, the 2015 contracts are: ESH2015, ESM2015, ESU2015, ESZ2015.  I can build the continuous contract from ESH to ESM, but I don't know how to instruct python to make the next iteration using the newly-created continuous contract as the near contract and ESU2015 as the far contract?

Any advice is greatly appreciated.  Thank you.
ASKER CERTIFIED SOLUTION
Avatar of J. Freeze
J. Freeze

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial