"Futures not allowed for live trading" error upon attempt to paper trade or broker trade. Could someone from Quantopian explain this. Targeted algorithm is not trading Futures, but instead is using them as an indicator to trade valid sids. Why this is not allowed? What particular hurdles are there? How this could be "fixed"?

Clone Algorithm

120

Loading...

There was an error loading this backtest.

Backtest from
to
with
initial capital

Cumulative performance:

Algorithm
Benchmark

Custom data:

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 talib from math import trunc from pytz import timezone import numpy as np import pandas as pd import datetime import math import time import re import functools import itertools from zipline.utils import tradingcalendar #Max_Wager in $ we want to invest into this algorithm Max_Wager = 0 #5000. #Or set above Max_Wager to 0 and set Max_Wager_Percent, as percent of portfolio Max_Wager_Percent = 40. History = 128 # Setting thresholds threshold_vix_too_low = 10.8 # first percentile, very rare case, very likely VIX will pop so we want to be in UVXY threshold_xiv = -0.049 # 60th percentile, as we want to be primarily in XIV threshold_uvxy = -threshold_xiv # symmetry threshold_vxv_xiv = 0.79 # first percentile, very rare case threshold_vxv_uvxy = 2 - threshold_vxv_xiv # symmetry threshold_macd = -0.55 # first percentile, we want to pass 99% of the cases here threshold_vix_high = 19.9 # 85th percentile, we are already going to be in XIV 60% of the time, so need to be careful # no more than total 75% of the time in XIV threshold_vix_low = 11.5 # 5th percentile, very rare case, may be VIX will pop so we want to be in UVXY threshold_vc_low = -0.148 # 1.5th percentile, very rare, we are already going to be in XIV 60% of the time, so need to be careful # no more than total 75% of the time in XIV threshold_vc_high = 0.046 #80th percentile, we will hardly be in UVXY (actually 51 is 80th percentile) # so we need to pick up some cases where which is biased towards UVXY to get to at least 15% of the time in UVXY threshold_vc_low_2 = 0.0 #50th percentile, below this we go for UVXY in lieu of any other signals threshold_vc_high_2 = -0.06 # testing this, this is fitted # relaxing condition to invest in XIV from 60th to 62nd percentile (~5%), absolute value also relaxes ~5% from -0.049 to -0.046 threshold_xiv_2 = -0.046 # 62th percentile # this is to check for one last time if no signals have it, before we default to TQQQ threshold_uvxy_2 = -0.008 # 85th percentile, taking a risk to invest in UVXY when there's hardly any contango or backwardation # this is to check for one last time if no signals have it, before we default to TQQQ threshold_xiv_ratio = -0.06 # first percentile # if XIV has dropepd that much we probably don't want to be long XIVeven though other signals say yes, default to TQQQ threshold_uvxy_ratio = -threshold_xiv_ratio # symmetry # if XIV has gone up that much we probably don't want to be long UVXY even though other signals say yes, default to TQQQ # Blending two V1 and V2 ratios together using a weighted average ratio_weight = 0.7 def initialize(context): vixUrl = 'http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vixcurrent.csv' vxvUrl = 'http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vxvdailyprices.csv' fetch_csv(vixUrl, symbol='v', skiprows=1, date_column='Date', pre_func=addFieldsVIX, post_func=shift_data) fetch_csv(vxvUrl, symbol='vxv', skiprows=2, date_column='Date', pre_func=addFieldsVXV, post_func=shift_data) context.xiv = sid(40516) context.tqqq = sid(39214) context.uvxy = sid(41969) context.spyg = sid(22009) context.vix = -1 context.futures = continuous_future('VX') set_slippage(slippage.FixedSlippage(spread=0.0)) schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open(hours = 0, minutes = 1)) def my_rebalance(context, data): update_indices(context, data) last_vix = data.current('v', 'Close') last_vxv = data.current('vxv', 'Close') cl_chain = data.current_chain(context.futures) front = cl_chain[0] second = cl_chain[1] last_vx1 = data.current(front, 'price') last_vx2 = data.current(second, 'price') log.info("%s %5.3f %s %5.3f Vix %5.3f Vxv %5.3f" %(front, last_vx1, second, last_vx2, last_vix, last_vxv)) # Calculating the gap ratio between spot vix and the first month vix future last_ratio_v_v1 = last_vix/last_vx1 # Calculating the contango ratio of the front and second month VIX Futures last_ratio_v1_v2 = last_vx1/last_vx2 # average of above 2 using ratio_weight (more to front month) last_ratio = (ratio_weight*last_ratio_v_v1) + ((1-ratio_weight)*last_ratio_v1_v2) - 1 # VIX to VXV ratio vix_vxv_ratio = last_vix/last_vxv # Retrieve SPY prices for technical indicators prices = data.history(context.spyg, 'open', 40, '1d') # Retrieve SPY MACD data macda, signal, hist = talib.MACD(prices, fastperiod=12,slowperiod=26,signalperiod=9) macd = macda[-1] - signal[-1] # Calculate how much vix moved the previous day if (context.vix <> -1) : vix_ratio = last_vix/context.vix -1 else : vix_ratio = 0 context.vix = last_vix #change in XIV from previous day xiv_history = data.history(context.xiv, 'price', 2, '1d') xiv_ratio = xiv_history[1]/xiv_history[0] - 1 if last_vix < threshold_vix_too_low: # if VIX is too low, invest in UVXY witht he hope of a spike log.info("CASE UVXY 0") target_sid = context.uvxy elif last_ratio < threshold_xiv: # if contango is high, invest in XIV to gain from decay log.info("CASE XIV 1") target_sid = context.xiv elif vix_vxv_ratio < threshold_vxv_xiv: # if short term vol is low compared to mid term, invest in XIV to gain from decay log.info("CASE XIV 2") target_sid = context.xiv elif last_ratio > threshold_uvxy and macd > threshold_macd: # if backwardation is high, invest in UVXY to gain from decay log.info("CASE UVXY 3") target_sid = context.uvxy elif vix_vxv_ratio > threshold_vxv_uvxy: # if short term vol is high compared to mid term, invest in UVXY to gain from growth log.info("CASE UVXY 4") target_sid = context.uvxy elif last_vix > threshold_vix_high: # if VIX is too high, invest in XIV expecting that VIX will drop log.info("CASE XIV 5") target_sid = context.xiv elif last_vix < threshold_vix_low: # if VIX is too low, invest in XIV expecting that VIX will rise log.info("CASE UVXY 6") target_sid = context.uvxy elif vix_ratio < threshold_vc_low: # Vix down sharply, invest in XIV expecting that futures curve gets pulled down log.info("CASE XIV 7") target_sid = context.xiv elif vix_ratio > threshold_vc_high: # Vix up sharply, invest in UVXY expecting that futures curve gets pulled up log.info("CASE UVXY 8") target_sid = context.uvxy elif vix_ratio > threshold_vc_high_2: #have to think log.info("CASE XIV 9") target_sid = context.xiv elif vix_ratio < threshold_vc_low_2: # vix dropped. There are no other signals. in the absence of any signal, try UVXY log.info("CASE UVXY 10") target_sid = context.uvxy elif last_ratio < threshold_xiv_2: # before we give up on XIV and move to TQQQ let's relax the contango conditions a bit log.info("CASE XIV 11") target_sid = context.xiv elif last_ratio > threshold_uvxy_2: # before we give up on UVXY and move to TQQQ let's relax the backwardation conditions a bit log.info("CASE UVXY 12") target_sid = context.uvxy else: log.info("CASE TQQQ 13") target_sid = context.tqqq if (target_sid == context.xiv and xiv_ratio < threshold_xiv_ratio) : # indicators say XIV but it just dropped overnight, so got for TQQQ log.info("CASE TQQQ 14") target_sid = context.tqqq elif (target_sid == context.uvxy and xiv_ratio > threshold_uvxy_ratio) : # indicators say UVXY but it just dropped overnight, so got for TQQQ log.info("CASE TQQQ 15") target_sid = context.tqqq if target_sid not in context.portfolio.positions: Wager = Max_Wager if Wager == 0.: Wager = Max_Wager_Percent/100.*context.portfolio.portfolio_value Weight = Wager/context.portfolio.portfolio_value log.info("Wager %5.2f Weight %5.2f" %(Wager, Weight)) order_target_percent(context.tqqq,0) order_target_percent(context.uvxy,0) order_target_percent(context.xiv,0) order_target_percent(target_sid, Weight) def update_indices(context, data): context.fetch_failed = False context.vix_vals = unpack_from_data(context, data, 'v') context.vxv_vals = unpack_from_data(context, data, 'vxv') def fix_close(df,closeField): df = df.rename(columns={closeField:'Close'}) # remove spurious asterisks df['Date'] = df['Date'].apply(lambda dt: re.sub('\*','',dt)) # convert date column to timestamps df['Date'] = df['Date'].apply(lambda dt: pd.Timestamp(datetime.datetime.strptime(dt,'%m/%d/%Y'))) df = df.sort_values(by='Date', ascending=True) return df def subsequent_trading_date(date): tdays = tradingcalendar.trading_days last_date = pd.to_datetime(date) last_dt = tradingcalendar.canonicalize_datetime(last_date) next_dt = tdays[tdays.searchsorted(last_dt) + 1] return next_dt def add_last_bar(df): last_date = df.index[-1] subsequent_date = subsequent_trading_date(last_date) blank_row = pd.Series({}, index=df.columns, name=subsequent_date) # add today, and shift all previous data up to today. This # should result in the same data frames as in backtest df = df.append(blank_row).shift(1).dropna(how='all') return df def shift_data(df): log.info("Pre-Shift") df = add_last_bar(df) df.fillna(method='ffill') df['PrevCloses'] = my_rolling_apply_series(df['Close'], to_csv_str, History) dates = pd.Series(df.index) dates.index = df.index df['PrevDates'] = my_rolling_apply_series(dates, to_csv_str, History) return df def unpack_from_data(context, data, sym): try: v = data.current(sym, 'PrevCloses') i = data.current(sym, 'PrevDates') return from_csv_strs(i,v,True).apply(float) except: log.warn("Unable to unpack historical {s} data.".format(s=sym)) context.fetch_failed = True def addFieldsVIX(df): #log.info("VIX: Pre-Massage") df = fix_close(df,'VIX Close') #log.info("VIX: Post-Massage") return df def addFieldsVXV(df): #log.info("VXV: Pre-Massage") df.rename(columns={'Unnamed: 0': 'Date'}, inplace=True) df = fix_close(df,'CLOSE') #log.info("VXV: Post-Massage") return df # convert a series of values to a comma-separated string of said values def to_csv_str(s): return functools.reduce(lambda x,y: x+','+y, pd.Series(s).apply(str)) # a specific instance of rolling apply, for Series of any type (not just numeric, # ala pandas.rolling_apply), where the index of the series is set to the indices # of the last elements of each subset def my_rolling_apply_series(s_in, f, n): s_out = pd.Series([f(s_in[i:i+n]) for i in range(0,len(s_in)-(n-1))]) s_out.index = s_in.index[n-1:] return s_out # reconstitutes a Series from two csv-encoded strings, one of the index, one of the values def from_csv_strs(x, y, idx_is_date): s = pd.Series(y.split(','),index=x.split(',')) if (idx_is_date): s.index = s.index.map(lambda x: pd.Timestamp(x)) return s