Back to Community
Newbie here - help with runtime error

I am trying to implement this algo, but I get a runtime error on line 252
Would someone know what is wrong?

I copy the algo here in case you cant see the source code

"""
Select 10 stocks from Q500US universe based on following ranking system:  
1) VALUATION     60%  
    - Price to Book ratio (lowest).......33%  
    - TTM PE (lowest)....................33%  
    - 5 year Sales % CAGR (highest)......33%  <--- coded with growth_score, but not exactly correct, i.e. should be only growth of sales  
2) MOMENTUM     40%  
    - 3 Months Pct Change................50%  
    - 3 Months Pct Change 3 Months ago...50%


Rules:  
- Entry if SMA50 > SMA200 with following settings:  
- Exit if SMA50 <= SMA200 with following settings:


"""



from quantopian.algorithm import attach_pipeline,pipeline_output  
from quantopian.pipeline import Pipeline  
from quantopian.pipeline.data.builtin import USEquityPricing  
from quantopian.pipeline.factors import AverageDollarVolume,SimpleMovingAverage  
from quantopian.pipeline.filters.morningstar import Q500US  
from quantopian.pipeline.data import morningstar  
# from quantopian.pipeline.data import Fundamentals as income_statement  
# from quantopian.pipeline.data import Fundamentals as balance_sheet  
from quantopian.pipeline.data import Fundamentals as valuation_ratios  
from quantopian.pipeline.data import Fundamentals as valuation  
# from quantopian.pipeline.classifiers.fundamentals import Sector  
from quantopian.pipeline import CustomFactor  
import numpy

#========================================================================================

'''
Set constants  
'''

# Set quarter look-back period  
trading_days_in_year = 252  
Q1=-1  
Q2=0-(trading_days_in_year/4)  
Q3=0-(trading_days_in_year/4)*2  
Q4=0-(trading_days_in_year/4)*3

# Set number of stocks going long during positive market trends  
target_stocks = 10

#Set Max leverage  
stocks_long_max_leverage = +1.0

spy = sid(8554)

#========================================================================================

def initialize(context):  
    """  
    Called once at the start of the algorithm.  
    """  
    # Rebalance every day, 1 hour after market open.  
    schedule_function(my_rebalance, date_rules.every_day(),time_rules.market_open(minutes=5))  
    # Record tracking variables at the end of each day.  
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())  
    # # Import SPY for 130/30 portfolio  
    # context.spy = sid(8554)  
    # # Import IEI for adverse market conditions  
    # context.iei = sid(33151)  
    my_pipe = make_pipeline()  
    attach_pipeline(my_pipe,'my_pipeline')  
    # Keep track of market conditions  
    context.spy_uptrend = False  
    context.spy_downtrend = False  
#========================================================================================  
'''
RELATIVE STRENGTH SIGNALS  
'''

# 3 months momentum  
class Momentum3M(CustomFactor):  
    # Pre-declare inputs and window_length  
    inputs = [USEquityPricing.close]  
    window_length = 62  
    # Compute factor1 value  
    def compute(self, today, assets, out, close):  
        out[:] = close[-2]/close[-62]  
# 3 months momentum 3 months ago  
class Momentum3M3M(CustomFactor):  
    # Pre-declare inputs and window_length  
    inputs = [USEquityPricing.close]  
    window_length = 120  
    # Compute factor2 value  
    def compute(self, today, assets, out, close):  
        out[:] = close[-60]/close[-120]   


#========================================================================================

'''VALUATION RATIOS'''

# Calculate trailing 12 months EPS sum  
class EPS_TTM(CustomFactor):  
    inputs = [morningstar.earnings_report.basic_eps]  
    window_length = trading_days_in_year  
    def compute(self, today, asset_ids, out, eps):  
        out[:] = eps[Q1] + eps[Q2] + eps[Q3] + eps[Q4]


# Latest Price to Book ratio  
class Price_to_book(CustomFactor):  
    inputs = [morningstar.valuation_ratios.pb_ratio]  
    window_length = 2  
    def compute(self, today, asset_ids, out, pb):  
        out[:] = pb[-1]

# Past 5 years revenue growth rate  
class Growth5yr(CustomFactor):  
    inputs = [morningstar.asset_classification.growth_score]  
    window_length = trading_days_in_year  
    def compute(self, today, asset_ids, out, value):  
        out[:] = value[-1]

#========================================================================================

def make_pipeline():  
    # Base universe set to the Q500US  
    base_universe = Q500US()  
    '''  
    Import momentum signals  
    '''  
    momentum3M = Momentum3M()  
    # pipe.add(momentum3M, 'momentum3M')  
    momentum3M3M = Momentum3M3M()  
    # pipe.add(momentum3M3M, 'momentum3M3M')

    '''  
    Rank momentum signals  
    '''  
    momentum3M_rank = momentum3M.rank(mask=base_universe, ascending=False)  
    # pipe.add(momentum3M_rank, 'mom3M_rank')  
    momentum3M3M_rank = momentum3M3M.rank(mask=base_universe, ascending=False)  
    # pipe.add(momentum3M3M_rank, 'mom3M3M_rank')  

    # Combine momentum ranking  
    mom_comb = (momentum3M_rank*0.5 + momentum3M3M_rank*0.5)  
    # my_pipe.add(mom_comb, 'Momentum combination')  
    # Rank the mom_comb  
    mom_rank = mom_comb.rank(mask=base_universe, ascending=False)  
    # pipe.add(mom_rank, 'Momentum Rank')  

    '''  
    Valuation ratios  
    '''  
    # Last quarter Price to Book ratio  
    pb_ratio = Price_to_book()  
    # Get last closing price  
    yesterday_close = USEquityPricing.close.latest  
    # Trailing 12 months PE ratio  
    eps_ttm = EPS_TTM()  
    pe_ttm =  eps_ttm / yesterday_close

    # 5 year growth  
    growth = Growth5yr()  
    # growth = morningstar.asset_classification.growth_score.latest  
    '''  
    Rank valuation ratios  
    '''  
    # dividend yield  
    pb_rank = pb_ratio.rank(mask=base_universe, ascending=True)  
    pe_rank = pe_ttm.rank(mask=base_universe, ascending=True)  
    growth_rank = growth.rank(mask=base_universe, ascending=False)  

    # Combine Valuation ranking  
    val_comb = (pb_rank*0.33 + pe_rank*0.33 + growth_rank*0.33)  
    # Rank the val_comb  
    val_rank = val_comb.rank(mask=base_universe, ascending=False)  
    '''  
    Combined Total Rank (Momentum + Valuation)  
    '''  
    comb = (val_rank * 0.6 + mom_rank * 0.4)  
    # Rank the combined ranking  
    comb_rank = comb.rank(mask=base_universe, ascending=False)  

    '''  
    Return values  
    '''  
    pipe = Pipeline(  
        screen = base_universe,  
        columns = {  
            'Mom Value': mom_comb,  
            'Val Value':val_comb,  
            'Total Ranking':comb_rank  
        }  
    )  
    return pipe

#========================================================================================

def before_trading_start(context, data):  
    """  
    Called every day before market open.  
    """  
    context.output = pipeline_output('my_pipeline')  
    # These are the long securities that we are interested in trading each day in favourable mkt conditions  
    # i.e. SMA50 > SMA200  
    context.long_list = context.output.sort(['comb_rank'], ascending=False).iloc[:target_stocks]  


#========================================================================================

def my_assign_weights(context, data):  
    """  
    Assign weights to securities that we want to order.  
    """  
    pass

#========================================================================================

def my_rebalance(context,data):  
    """  
    Execute orders according to our schedule_function() timing.  
    """  
    # Check that list of stocks to buy is not empty  
    try:  
        long_stocks_weight = stocks_long_max_leverage / float(len(context.long_list))  
    except ZeroDivisionError:  
        long_stocks_weight = 0.0  
        log.info('no stocks to buy today')  
    # Calcualte SMA50 and SMA200 for entry/exit and hedge rules  
    sma_50 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50, mask=spy)  
    sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200, mask=spy)  
    # When SMA50 > SMA200 go 130% long on list of stocks and 30% short on SPY  
    if sma_50 > sma_200:  
        for long_stock in context.long_list.index:  
            if data.can_trade(long_stock):  
                order_target_percent(long_stock, long_stocks_weight)  
        context.spy_uptrend = True  
        context.spy_downtrend = False  
    # When SMA50 <= SMA200 go 100% long on bond ETF  
    elif sma_50 <= sma_200:  
        order_target_percent(long_stock, 0.0)  
        context.spy_uptrend = False  
        context.spy_downtrend = True  

        # for stock in context.portfolio.positions.iterkeys():  
        #     # if stock not in context.long_list.index and stock not in context.short_list.index:  
        #     if stock not in context.long_list.index:  
        #         order_target(stock, 0)

#========================================================================================

def my_record_vars(context, data):  
    """  
    Plot variables at the end of each day.  
    """  
    # Record and plot the leverage of our portfolio over time.  
    record(leverage = context.account.leverage)  
    print "Long List"  
    log.info("\n" + str(context.long_list.sort(['comb_rank'], ascending=True)))  


#========================================================================================

def handle_data(context,data):  
    """  
    Called every minute.  
    """  
    pass

#========================================================================================

# def daily_clean(context, data):  
#     for stock in context.portfolio.positions:  
#         if stock not in context.security_set and data.can_trade(stock):  
#             order_target_percent(stock, 0)

Clone Algorithm
3
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ecc7f10aa92d3f71269106
There was a runtime error.
11 responses

Hello Matteo,

I copied your code and got run time error on line 207 which is strange cause you say you got it on line 252. My error was caused 'comb_rank'. You have defined Pipeline colums as 'Total Ranking':comb_rank, but you've used 'comb_rank' in following lines:

context.long_list = context.output.sort(['comb_rank'], ascending=False).iloc[:target_stocks]

log.info("\n" + str(context.long_list.sort(['comb_rank'], ascending=True)))

While you should've used 'Total rank' instead of 'comb_rank'. So I changed 'comb_rank' to 'Total rank' on those two lines and now your algorithm runs.

Clone Algorithm
2
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ed163a24fb554114719d4c
There was a runtime error.

Thanks Mikko J

Would you happen to know also why the leverage keeps increasing? I would assume its because some positions are not being closed correctly, but how can I amend that? as you see in line 52, I would like leverage to be 1.0 max

I have tried to change the exit rules from line 241 but i still a very high leverage

Clone Algorithm
3
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ed92734ccf5b419e9be7a0
There was a runtime error.

Hello Matteo,

Somehow target_stocks = 10 messes up leverage. I'm not really familiar with target_stock implementation so I can't help you how to set it correctly, but I deleted it from line 49 and from line 209, context.long_list = context.output.sort(['Total Ranking'], ascending=False).iloc[:target_stocks] and now leverage stays around 1.

Clone Algorithm
3
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ededf04ccf5b419e9bf0b3
There was a runtime error.

Thanks a lot Mikko, have you made any other changes?
I have made the changes you suggest +

current_position = context.portfolio.positions[long_stock].amount  

in the order section, but as you can see leverage is still pretty high around 5

Clone Algorithm
3
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59edf6c649965a4166548616
There was a runtime error.

Also, having tested your algo on a longer time period, it seems like the leverage increases and especially the positions held at any given time are much more than 10

Do you know how to make sure that only 10 stock are held at any given time and to make sure that stocks that do not fit the requirements are sold at re-balancing?

Clone Algorithm
3
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59edfa7e9999703ffdfaa944
There was a runtime error.

Matteo - take a look at the new Optimize API. You can construct your long_list using a helper function like Scott describes. Then, pass that objective into the optimizer and it will take care of opening and closing positions for you.

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.

Ah yeah. I made some other changes while I was locating leverage issue. My plan was to delete anything I tried, but seems like I've missed a spot. :-)
I used current_position = context.portfolio.positions[long_stock].amount and current_position == 0: when I thought it was issue of algorithm buying and buying more and more of stock which it already owns. But it didn't solve issue after that I figured out target_stocks stuff which I wrote about.
I'm honestly sorry if my additional code caused some confusion. Here's your original code without target_stocks and without any of my code, as you see leverage stays around 1.

Clone Algorithm
3
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ee15cc98674d4139700c4a
There was a runtime error.

Thanks Mikko, I have tried to run the above algo and on longer time frames, the leverage increases as time passes also if you take a look at the transactions you will see that there are days with over 500 transactions - i am only looking at holding 10 stocks each day - do you know what could be causing the problem?

Dan - many thanks for the inputs, i have looked at the docs but i am having troubles in understanding how to implement it in the algo. I think more generally, there might be something wrong with the number of stocks selected and the daily rebalancing

Clone Algorithm
0
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ee17f1e8c97c4176729071
There was a runtime error.

Hi Matteo,

First, there are a couple of issues with the algo's structure that I would like to point out:

1) In lines 210, 211 you are trying to use SimpleMovingAverage to calculate sma for SPY, but this will not have the result you intend. The SimpleMovingAverage factor can only be used within a pipeline's definition. Instead, you should query pricing data for SPY using data.history and calculate the mean over the periods you want. You can find a good example of how to do this in the sample algorithm from the Getting Started tutorial.

2) The long_stock variable is only defined within the for loop inside the if condition that triggers when sma50 > sma_200 (line 214), but you try to use it outside this block in line 221. This will cause an error if the second condition is triggered.

With that out of the way, I'll address your original question. Currently, your algorithm does not limit the amount of securities that it trades. The pipeline will output ~500 securities, and your algorithm will try to open long positions on all of them, regardless of their comb_rank value. To fix this, you can change your pipeline's screen to comb_rank.top(10), which will limit the number of securities that your pipeline outputs to 10, based on their comb_rank value.

Also, the algorithm's leverage slowly increases because it never exits securities that are no longer a part of its target universe. When the first condition is triggered (sma_50 > sma200), you need to check your portfolio's positions against your list of targets (context.long_list) and sell off any positions that are no longer a part of your target universe.

I hope the sample algorithm attached helps.

Clone Algorithm
5
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ee2e0140fc97411cd89f8f
There was a runtime error.
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.

Thank you all! J seems to be working fine now!

Ernesto - I have tried to run this from 2003 and it seems like it doe snot buy anything until 2009 - would you happen to know why?

Clone Algorithm
1
Loading...
Backtest from to with initial capital
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
# Backtest ID: 59ef7d100b0056450c800351
There was a runtime error.