Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
global name 'data' is not defined when migrating code

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)

3 responses

Simplified version of the above code :

def initialize(context):  
    context.etfs =symbols('XLV', 'XLK', 'XLI', 'XLP','XLE','XLU','XLB','XLY','XLF')  
    schedule_function(rebalance,date_rules.month_start(), time_rules.market_open(minutes=60))  
def rebalance(context,data):  
    target_vol = 0.25  
    lev = 1.0  
    if get_open_orders(): return  
    prices= data.history(context.etfs, 'price', 126, '1d')  
    hvol = prices.tail(60).pct_change().std()*(252**0.5)  
    mom = prices.ix[-1]/prices.ix[0]-1.0  
    for asset in context.etfs:  
        wt = lev*min(1.0,target_vol/hvol[asset])/len(context.etfs) if  mom[asset] > 0.0 else 0.0  
        order_target_percent(asset, wt)  
    record(leverage = context.account.leverage)  

Is the logic the same? How was it possible to collapse the code and make it so compact? I'm thoroughly impressed.

As a side note, is there any explanation as to why the minimalized code works, but the above port that I tried fails with an error? I'm still confused about that.

Hi Delma,

The problem is that you are only passing context to your get_vol and get_mom_weights functions, but you need to also pass data in order to be able to use the data.history function.

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.