The code and backtest are attached below. I'm sure this is an easy answer with an easy solution, but my lack of knowledge with the migration is making this difficult.
# Implementation of - Volatility Weighted Momentum
# as described in the paper Adaptive Asset Allocation: A Primer
# which can be found here - http://bpgassociates.com/docs/Adaptive-Asset-Allocation-A-Primer.pdf
# the Volatility Weighted Momentum algorithm is described in Exhibit 4 of the paper
import math
def initialize(context):
set_symbol_lookup_date('2005-01-01')
#Asset #1 - test 7 asset scenario from paper - the small global multi asset universe
# from Keller/Butler - Elastic Asset Allocation (EAA)
#removed HYG from sample set to allow for longer backtest
'''
context.etfs = symbols('SPY', #proxy for S&P
'EFA', #proxy for EAFE
'EEM', #proxy for EEM
'QQQ', #proxy for US Tech
'EWJ', #proxy for Japan Topix
'IEF') #proxy for US Govt 10 yr
'''
#Asset #2 - test a more generalized distribution of assets
#US stocks, European stocks, Emerging market stocks, US bonds, gold, real estate
#context.etfs = symbols('SPY','EFA','EEM','IEF','GLD','IYR')
#Asset #3 - test against S&P sectors to estimate upside extraction
context.etfs = [symbols('XLY', # XLY Consumer Discrectionary SPDR Fund
'IYR', #Real Estate ETF in place of XLFS
'IYG', #Financial Services etf in place of
'XLF', # XLF Financial SPDR Fund
'XLK', # XLK Technology SPDR Fund
'XLE', # XLE Energy SPDR Fund
'XLV', # XLV Health Care SPRD Fund
'XLI', # XLI Industrial SPDR Fund
'XLP', # XLP Consumer Staples SPDR Fund
'XLB', # XLB Materials SPDR Fund
'XLU') # XLU Utilities SPRD Fund
]
context.mom_lookback = 240
context.risk_free_asset = symbol('SHY')
context.target_vol = 0.01 #target 1% volatility
context.vol_lookback = 60
schedule_function(rebalance,date_rules.month_end(days_offset=0), time_rules.market_close(minutes=60))
#calculate volatility for etf universe
def get_vol(context):
h = data.history(context.etfs, 'price', context.vol_lookback*2, '1d')
hs = h.ix[-1*context.vol_lookback:]
context.hvol = hs.pct_change().std()
#calculate weights based on relative momentum ranking and absolute momentum test
def get_mom_weights(context):
#init weights
context.weights = {}
for s in context.etfs:
context.weights[s] = 0
h = data.history(context.etfs, 'price', context.vol_lookback*2, '1d')
h = h.resample('M',how='last')
#drop first row because it is nan
pct_change =h.iloc[[0,-2]].pct_change()[1:]
#drop any other nan values
pct_change = pct_change.dropna(axis=1)
#convert dataframe to series for sorting. Then sort in descending order
context.pct_change_series = pct_change.squeeze().order(ascending=False)
l = int(math.floor(len(context.etfs)/2.0))
context.weight = 1.0/l
for i in range(l) :
if context.pct_change_series.ix[i] > 0.0 :
s = context.pct_change_series.index[i]
context.weights[s] = context.weight
def rebalance(context,data):
get_vol(context)
get_mom_weights(context)
total_weight = 0.0
for s in context.etfs:
mom_vol_weight = context.weights[s]*(context.target_vol/context.hvol[s])
if mom_vol_weight > context.weight:
mom_vol_weight = context.weight
order_target_percent(s,mom_vol_weight)
total_weight += mom_vol_weight
if total_weight < 1.0:
order_target_percent(context.risk_free_asset,1.0-total_weight)
else:
order_target_percent(context.risk_free_asset,0.0)
# Will be called on every trade event for the securities you specify.
def handle_data(context, data):
record(leverage = context.account.leverage)