Back to Community
Automated Futures Rolling

I'm excited to see futures on the platform. I recently wrote an algo and have started backtesting it, I noticed that once I entered into a contract it is not automatically rolled to the next contract after expiry (just like real life trading).

The ContinuousFuture data type has a specified way to roll each contract. I was wondering if there was some way to reuse the code to roll historical data for rolling current contracts. For example I would like to use volume to decide when to roll my contracts, the ContinuousFuture does that for historical data why not make it available for live positions.

I think this would be a useful feature.

1 response

I have written something myself, it didn't take too long.
See the attached code lines 41-53.

Maybe this will help out other people.

Clone Algorithm
5
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import itertools

import numpy as np
import pandas as pd
import scipy as sp
from statsmodels.tsa.stattools import coint

from quantopian.algorithm import order_optimal_portfolio
import quantopian.experimental.optimize as opt

N = 1

#   https://www.quantopian.com/posts/continuous-future-data-lifespans
available_futures = {
    'debug': {
        'soybean': 'SY',# good
        'chf': 'SF', # good
    },
}


def make_futures(context):
    # populates context.futures, by flattening available_futures
    context.futures = {}
    for sector in available_futures:
        for symbol in available_futures[sector].values():
            context.futures[symbol] = continuous_future(
                symbol,
                offset=0,
                roll='volume',     # default is volume 
                adjustment='mul',)
                               

def initialize(context):
    context.started = False
    make_futures(context)
    
    schedule_function(func=roll, date_rule=date_rules.every_day())
    schedule_function(func=rebalance_pairs, date_rule=date_rules.month_start())

def roll(context, data):
    """detects when a contract you hold is no longer current"""
    today = data.current_session.date()
    
    current_positions = context.portfolio.positions.keys()
    for cont in current_positions:
        days_to_auto_close = (cont.auto_close_date.date() - today).days
        print "days to auto_close: {}".format(days_to_auto_close)
        cont_future = context.futures[cont.root_symbol]
        current_cont = data.current(cont_future, 'contract')
        if current_cont != cont:
            print "this isn't the current contract bro"
            # take action here to roll

def rebalance_pairs(context, data):
    
    for ftr in context.futures.values():
        print "{} {} starts at: {} ends at: {}".format(ftr.root_symbol, ftr.sid, ftr.start_date, ftr.end_date)
    
    current_contracts = [data.current(future, 'contract') for future in context.futures.values()]
    if not context.started:             
        targets = {current_contracts[0]: 0.5}
        objective = opt.TargetPortfolioWeights(targets)
        order_optimal_portfolio(objective, constraints=[])
        context.started = True
There was a runtime error.