Back to Community
Help: Algo does not send orders

I have done this algo and it works well until 2009, but after that it stops making orders.
I have checked in the debugger and in this code the variables context.long_list and context.weigths are correctly populated.
So i cannot understand why it stops working.

    for long_stock in context.long_list:  
        if long_stock in data:  
            if long_stock in context.dont_buys:  
                continue  
            order_target_percent(long_stock, context.weigths.loc[long_stock])  
Clone Algorithm
4
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
import datetime
import statsmodels.api as sm
import numpy as np
import pandas as pd

'''
Algo Logic: 
1) define market uptrend and downtrend by the 252 days slope.
2) Group all stocks by sectors
3) Filter all the stocks of each sector by a combination of these factors: growth, value, roic, quality and 1/volatility
4) if the market is uptrend buy cyclical and sensitive stocks
5) if the market is downtrend buy sensitive and defensive stocks
'''

def initialize(context):
    context.num_stocks = 3
    
    context.defensive_sectors = [205,206,207] #Consumer_defensive, HealthCare, Utilities
    context.cyclical_sectors = [101,102,103,104] # Basic Materials, Consumer Cyclical, Financials, Real Estate
    context.sensitive_sectors = [308,309,310,311] # Communication, Energy, Industrials, Technology
    context.sectors = context.defensive_sectors + context.cyclical_sectors + context.sensitive_sectors
    context.fundamental_factors = ['growth', 'value','quality','roic', 'volatility']
    context.weigth = 0.95/(11*context.num_stocks)
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))
    create_pipeline(context)
    schedule_function(func=rebalance, 
                      date_rule=date_rules.month_end(days_offset=0), 
                      time_rule=time_rules.market_open(hours=0,minutes=30), 
                      half_days=True)

    schedule_function(func = cancel_open_orders,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_close(minutes=5),half_days=True )   
                  
def handle_data(context, data):
    # Record and plot the leverage, number of positions, and expsoure of our portfolio over time. 
    record(
           exposure=context.account.net_leverage, 
           longs = len([s for s in data if context.portfolio.positions[s].amount > 0]),
           shorts = len([s for s in data if context.portfolio.positions[s].amount < 0]),
           leverage=context.account.leverage)

    
def before_trading_start(context, data):
    
    context.output = pipeline_output('ranking_example')
    
    #~~~~~~ RESET DICTS AND LISTS ~~~~~~#
    
    context.long_list=[]
    weigths = {}

    #~~~~~~ FILTER OUT DELISTED STOCKS  ~~~~~~#
    context.output['end_date'] = [stock.end_date for stock in context.output.index]
    context.output = context.output[(context.output['end_date'] > (get_datetime()+datetime.timedelta(days=10)))]
    df = context.output
    

    
    #~~~~~~ SECOND FILTERING:  RANKING EACH SECTORS STOCKS ~~~~~~#
    grouped = df.groupby('sector')   
    for sector, group in grouped:
        
        if group['slope'].mean() > 0.0:  #trend up: buy it --> select good stocks 
            roic = group['roic'] > 0.0
            growth = group['growth'] > 0.0
            value = group['value'] > group['value'] .mean()
            quality = group['quality'] > group['quality'].mean()
            group = group[roic & growth & value & quality]

            group = group[context.fundamental_factors]                   
            normalized = group.apply(normalize)
            fund = normalized.sum(axis=1) 
            selected = fund.order(ascending=False).iloc[:context.num_stocks]
            long_stocks = selected.index.tolist()
            volatility = group['volatility'].loc[long_stocks]
            weigths[sector] = volatility
            
            if len(long_stocks) > 0:
                for stock in long_stocks:
                    context.long_list.append(stock)
            else:
                pass # No good stocks for this sector
                
        else:  
            pass # Sector has negative slope
    long_weigths = pd.DataFrame(weigths)
    long_weigths = long_weigths.sum(axis=1)
    context.weigths = long_weigths/long_weigths.sum()
    update_universe(context.long_list)
def rebalance(context,data):
    # Order our longs
    log.info("ordering longs")

    for long_stock in context.long_list:
        if long_stock in data:
            if long_stock in context.dont_buys:
                continue
            order_target_percent(long_stock, context.weigths.loc[long_stock])
      
    # Get rid of any stocks incorrectly held
    for security in context.portfolio.positions:
        if get_open_orders(security):
            continue
        if security in data:
            if security in context.dont_buys:
                continue
            if security not in context.long_list:
                order_target_percent(security, 0)

def create_pipeline(context):
    pipe_columns = {'roic': Value(), 'growth': Quality(), 'sector':Sector(), 'quality':Quality(), 'value':Value(),
                    'slope': Slope(window_length=252), 
                    'volatility': Volatility()}
    pipe = Pipeline(columns=pipe_columns)
    attach_pipeline(pipe, 'ranking_example')
    
    # We'll use this to screen out illiquid stocks...
    dollar_volume = AvgDailyDollarVolumeTraded()
    high_dollar_volume = dollar_volume > 10**7
    
    # ...and this to screen out penny stocks.
    sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    price = USEquityPricing.close.latest
    not_a_penny_stock = sma_200 > 5.0
    
    # Implement both of our screens.
    pipe.set_screen(high_dollar_volume & not_a_penny_stock)  
            
    # Used to avoid purchasing any leveraged ETFs 
    context.dont_buys = [sec for sec in security_lists.leveraged_etf_list]
    
def cancel_open_orders(context, data):
    for security in get_open_orders():
        for order in get_open_orders(security):
            cancel_order(order)
                      
class Value(CustomFactor):
    
    # Pre-declare inputs and window_length
    inputs = [morningstar.income_statement.ebit,
              morningstar.valuation.enterprise_value]
    window_length = 1
    
    def compute(self, today, assets, out, ebit, ev):
        out[:] = ebit[-1] / ev[-1]
        
        
#  Create a fundamental based custom "Quality" (profitability) factor
class Quality(CustomFactor):
    inputs = [morningstar.operation_ratios.roe]
    window_length = 1
    
    def compute(self, today, assets, out, roe):
        out[:] = roe[-1]
        
class Roic(CustomFactor):
    inputs = [morningstar.operation_ratios.roic]
    window_length = 1
    
    def compute(self, today, assets, out, roic):
        out[:] = roic[-1]
        
class Growth(CustomFactor):
    inputs = [morningstar.operation_ratios.revenue_growth]
    window_length = 1
    def compute(self, today, assets, out, growth):
        out[:] = growth[-1]      
        
class Sector(CustomFactor):
    inputs = [morningstar.asset_classification.morningstar_sector_code]
    window_length= 1
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]
        
class PEG(CustomFactor):
    inputs = [morningstar.valuation_ratios.peg_ratio]
    window_length = 1
    def compute(self, today, assets, out, peg):
        out[:] = peg[-1] 
        
class AvgDailyDollarVolumeTraded(CustomFactor):
    
    inputs = [USEquityPricing.close, USEquityPricing.volume]
    window_length = 20
    
    def compute(self, today, assets, out, close_price, volume):
        out[:] = np.mean(close_price * volume, axis=0)  
        
class Slope(CustomFactor):
    inputs = [USEquityPricing.close]
    def compute(self, today, assets, out, prices):
        Y = prices
        X = range(len(prices))
        A = sm.add_constant(X)
        results = sm.OLS(Y,A).fit()
        (b, a) =results.params
        slope = a / b * 252.0
        out[:] = slope
        
class PE_ratio(CustomFactor):
    inputs = [morningstar.valuation_ratios.pe_ratio]
    window_length= 1
    def compute(self, today, assets, out, pe):
        out[:] = pe[-1]

class Volatility(CustomFactor):    
    inputs = [USEquityPricing.close]
    window_length = 252
    
    def compute(self, today, assets, out, close):  
        close = pd.DataFrame(data=close, columns=assets) 
        # Since we are going to rank largest is best we need to invert the sdev.
        out[:] = 1 / np.log(close).diff().std()
        
normalize = lambda x : (x-x.mean())/x.std()                  

There was a runtime error.
8 responses

Hi Giuseppe,

It looks like the issue is that your rebalance() method is scheduled to run at month's end, but the timeframe in the backtest you shared ends on Jan. 24th!

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.

Thanks Jamie you are absolutely right, unfortunately the problem perstist in longer timeframes as well BUT only after 2009..
What i find strange is that the list with stocks to buy are not empty and weigths too, but the algo just stop working after 2009 and i cannot understand the reason why...

here an example

Clone Algorithm
4
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
import datetime
import statsmodels.api as sm
import numpy as np
import pandas as pd

'''
Algo Logic: 
1) define market uptrend and downtrend by the 252 days slope.
2) Group all stocks by sectors
3) Filter all the stocks of each sector by a combination of these factors: growth, value, roic, quality and 1/volatility
4) if the market is uptrend buy cyclical and sensitive stocks
5) if the market is downtrend buy sensitive and defensive stocks
'''

def initialize(context):
    context.num_stocks = 3
    
    context.defensive_sectors = [205,206,207] #Consumer_defensive, HealthCare, Utilities
    context.cyclical_sectors = [101,102,103,104] # Basic Materials, Consumer Cyclical, Financials, Real Estate
    context.sensitive_sectors = [308,309,310,311] # Communication, Energy, Industrials, Technology
    context.sectors = context.defensive_sectors + context.cyclical_sectors + context.sensitive_sectors
    context.fundamental_factors = ['growth', 'value','quality','roic', 'volatility']
    context.weigth = 0.95/(11*context.num_stocks)
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))
    create_pipeline(context)
    schedule_function(func=rebalance, 
                      date_rule=date_rules.month_end(days_offset=0), 
                      time_rule=time_rules.market_open(hours=0,minutes=30), 
                      half_days=True)

    schedule_function(func = cancel_open_orders,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_close(minutes=5),half_days=True )   
                  
def handle_data(context, data):
    # Record and plot the leverage, number of positions, and expsoure of our portfolio over time. 
    record(
           exposure=context.account.net_leverage, 
           longs = len([s for s in data if context.portfolio.positions[s].amount > 0]),
           shorts = len([s for s in data if context.portfolio.positions[s].amount < 0]),
           leverage=context.account.leverage)

    
def before_trading_start(context, data):
    
    context.output = pipeline_output('ranking_example')
    
    #~~~~~~ RESET DICTS AND LISTS ~~~~~~#
    
    context.long_list=[]
    weigths = {}

    #~~~~~~ FILTER OUT DELISTED STOCKS  ~~~~~~#
    context.output['end_date'] = [stock.end_date for stock in context.output.index]
    context.output = context.output[(context.output['end_date'] > (get_datetime()+datetime.timedelta(days=10)))]
    df = context.output
    

    
    #~~~~~~ SECOND FILTERING:  RANKING EACH SECTORS STOCKS ~~~~~~#
    grouped = df.groupby('sector')   
    for sector, group in grouped:
        
        if group['slope'].mean() > 0.0:  #trend up: buy it --> select good stocks 
            roic = group['roic'] > 0.0
            growth = group['growth'] > 0.0
            value = group['value'] > group['value'] .mean()
            quality = group['quality'] > group['quality'].mean()
            group = group[roic & growth & value & quality]

            group = group[context.fundamental_factors]                   
            normalized = group.apply(normalize)
            fund = normalized.sum(axis=1) 
            selected = fund.order(ascending=False).iloc[:context.num_stocks]
            long_stocks = selected.index.tolist()
            volatility = group['volatility'].loc[long_stocks]
            weigths[sector] = volatility
            
            if len(long_stocks) > 0:
                for stock in long_stocks:
                    context.long_list.append(stock)
            else:
                pass # No good stocks for this sector
                
        else:  
            pass # Sector has negative slope
    long_weigths = pd.DataFrame(weigths)
    long_weigths = long_weigths.sum(axis=1)
    context.weigths = long_weigths/long_weigths.sum()
    update_universe(context.long_list)
def rebalance(context,data):
    # Order our longs
    log.info("ordering longs")

    for long_stock in context.long_list:
        if long_stock in data:
            if long_stock in context.dont_buys:
                continue
            order_target_percent(long_stock, context.weigths.loc[long_stock])
      
    # Get rid of any stocks incorrectly held
    for security in context.portfolio.positions:
        if get_open_orders(security):
            continue
        if security in data:
            if security in context.dont_buys:
                continue
            if security not in context.long_list:
                order_target_percent(security, 0)

def create_pipeline(context):
    pipe_columns = {'roic': Value(), 'growth': Quality(), 'sector':Sector(), 'quality':Quality(), 'value':Value(),
                    'slope': Slope(window_length=252), 
                    'volatility': Volatility()}
    pipe = Pipeline(columns=pipe_columns)
    attach_pipeline(pipe, 'ranking_example')
    
    # We'll use this to screen out illiquid stocks...
    dollar_volume = AvgDailyDollarVolumeTraded()
    high_dollar_volume = dollar_volume > 10**7
    
    # ...and this to screen out penny stocks.
    sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    price = USEquityPricing.close.latest
    not_a_penny_stock = sma_200 > 5.0
    
    # Implement both of our screens.
    pipe.set_screen(high_dollar_volume & not_a_penny_stock)  
            
    # Used to avoid purchasing any leveraged ETFs 
    context.dont_buys = [sec for sec in security_lists.leveraged_etf_list]
    
def cancel_open_orders(context, data):
    for security in get_open_orders():
        for order in get_open_orders(security):
            cancel_order(order)
                      
class Value(CustomFactor):
    
    # Pre-declare inputs and window_length
    inputs = [morningstar.income_statement.ebit,
              morningstar.valuation.enterprise_value]
    window_length = 1
    
    def compute(self, today, assets, out, ebit, ev):
        out[:] = ebit[-1] / ev[-1]
        
        
#  Create a fundamental based custom "Quality" (profitability) factor
class Quality(CustomFactor):
    inputs = [morningstar.operation_ratios.roe]
    window_length = 1
    
    def compute(self, today, assets, out, roe):
        out[:] = roe[-1]
        
class Roic(CustomFactor):
    inputs = [morningstar.operation_ratios.roic]
    window_length = 1
    
    def compute(self, today, assets, out, roic):
        out[:] = roic[-1]
        
class Growth(CustomFactor):
    inputs = [morningstar.operation_ratios.revenue_growth]
    window_length = 1
    def compute(self, today, assets, out, growth):
        out[:] = growth[-1]      
        
class Sector(CustomFactor):
    inputs = [morningstar.asset_classification.morningstar_sector_code]
    window_length= 1
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]
        
class PEG(CustomFactor):
    inputs = [morningstar.valuation_ratios.peg_ratio]
    window_length = 1
    def compute(self, today, assets, out, peg):
        out[:] = peg[-1] 
        
class AvgDailyDollarVolumeTraded(CustomFactor):
    
    inputs = [USEquityPricing.close, USEquityPricing.volume]
    window_length = 20
    
    def compute(self, today, assets, out, close_price, volume):
        out[:] = np.mean(close_price * volume, axis=0)  
        
class Slope(CustomFactor):
    inputs = [USEquityPricing.close]
    def compute(self, today, assets, out, prices):
        Y = prices
        X = range(len(prices))
        A = sm.add_constant(X)
        results = sm.OLS(Y,A).fit()
        (b, a) =results.params
        slope = a / b * 252.0
        out[:] = slope
        
class PE_ratio(CustomFactor):
    inputs = [morningstar.valuation_ratios.pe_ratio]
    window_length= 1
    def compute(self, today, assets, out, pe):
        out[:] = pe[-1]

class Volatility(CustomFactor):    
    inputs = [USEquityPricing.close]
    window_length = 252
    
    def compute(self, today, assets, out, close):  
        close = pd.DataFrame(data=close, columns=assets) 
        # Since we are going to rank largest is best we need to invert the sdev.
        out[:] = 1 / np.log(close).diff().std()
        
normalize = lambda x : (x-x.mean())/x.std()                  

There was a runtime error.

I took another look, and it appears as though context.long_list is an empty list during the period of your algo with no trades!

If you add:

print len(context.long_list)  

right underneath the update_universe() function, you'll notice that in November 2008, it prints 0.

yes it's true, but for 2008, i hve added the length_long_list record and in this attachment you can see that it's 0 from 2008 untill the end, but it sould not be like this, infact if i do another backtest just changing the start date and the end date for the same algo, same code, i have different results (with correct values this tiem) as u can see..

Clone Algorithm
4
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
import datetime
import statsmodels.api as sm
import numpy as np
import pandas as pd

'''
Algo Logic: 
1) define market uptrend and downtrend by the 252 days slope.
2) Group all stocks by sectors
3) Filter all the stocks of each sector by a combination of these factors: growth, value, roic, quality and 1/volatility
4) if the market is uptrend buy cyclical and sensitive stocks
5) if the market is downtrend buy sensitive and defensive stocks
'''

def initialize(context):
    context.num_stocks = 3
    
    context.defensive_sectors = [205,206,207] #Consumer_defensive, HealthCare, Utilities
    context.cyclical_sectors = [101,102,103,104] # Basic Materials, Consumer Cyclical, Financials, Real Estate
    context.sensitive_sectors = [308,309,310,311] # Communication, Energy, Industrials, Technology
    context.sectors = context.defensive_sectors + context.cyclical_sectors + context.sensitive_sectors
    context.fundamental_factors = ['growth', 'value','quality','roic', 'volatility']
    context.weigth = 0.95/(11*context.num_stocks)
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))
    create_pipeline(context)
    schedule_function(func=rebalance, 
                      date_rule=date_rules.month_end(days_offset=0), 
                      time_rule=time_rules.market_open(hours=0,minutes=30), 
                      half_days=True)

    schedule_function(func = cancel_open_orders,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_close(minutes=5),half_days=True )   
                  
def handle_data(context, data):
    # Record and plot the leverage, number of positions, and expsoure of our portfolio over time. 
    record(
           exposure=context.account.net_leverage, 
           longs = len([s for s in data if context.portfolio.positions[s].amount > 0]),
           shorts = len([s for s in data if context.portfolio.positions[s].amount < 0]),
           leverage=context.account.leverage,
    length_long_list= len(context.long_list) )

    
def before_trading_start(context, data):
    
    context.output = pipeline_output('ranking_example')
    
    #~~~~~~ RESET DICTS AND LISTS ~~~~~~#
    
    context.long_list=[]
    weigths = {}

    #~~~~~~ FILTER OUT DELISTED STOCKS  ~~~~~~#
    context.output['end_date'] = [stock.end_date for stock in context.output.index]
    context.output = context.output[(context.output['end_date'] > (get_datetime()+datetime.timedelta(days=10)))]
    df = context.output
    

    
    #~~~~~~ SECOND FILTERING:  RANKING EACH SECTORS STOCKS ~~~~~~#
    grouped = df.groupby('sector')   
    for sector, group in grouped:
        
        if group['slope'].mean() > 0.0:  #trend up: buy it --> select good stocks 
            roic = group['roic'] > 0.0
            growth = group['growth'] > 0.0
            value = group['value'] > group['value'] .mean()
            quality = group['quality'] > group['quality'].mean()
            group = group[roic & growth & value & quality]

            group = group[context.fundamental_factors]                   
            normalized = group.apply(normalize)
            fund = normalized.sum(axis=1) 
            selected = fund.order(ascending=False).iloc[:context.num_stocks]
            long_stocks = selected.index.tolist()
            volatility = group['volatility'].loc[long_stocks]
            weigths[sector] = volatility
            
            if len(long_stocks) > 0:
                for stock in long_stocks:
                    context.long_list.append(stock)
            else:
                pass # No good stocks for this sector
                
        else:  
            pass # Sector has negative slope
    long_weigths = pd.DataFrame(weigths)
    long_weigths = long_weigths.sum(axis=1)
    context.weigths = long_weigths/long_weigths.sum()
    update_universe(context.long_list)
def rebalance(context,data):
    print 'length of long list: {}'.format(len(context.long_list))
    # Order our longs
    log.info("ordering longs")

    for long_stock in context.long_list:
        if long_stock in data:
            if long_stock in context.dont_buys:
                continue
            order_target_percent(long_stock, context.weigths.loc[long_stock])
      
    # Get rid of any stocks incorrectly held
    for security in context.portfolio.positions:
        if get_open_orders(security):
            continue
        if security in data:
            if security in context.dont_buys:
                continue
            if security not in context.long_list:
                order_target_percent(security, 0)

def create_pipeline(context):
    pipe_columns = {'roic': Value(), 'growth': Quality(), 'sector':Sector(), 'quality':Quality(), 'value':Value(),
                    'slope': Slope(window_length=252), 
                    'volatility': Volatility()}
    pipe = Pipeline(columns=pipe_columns)
    attach_pipeline(pipe, 'ranking_example')
    
    # We'll use this to screen out illiquid stocks...
    dollar_volume = AvgDailyDollarVolumeTraded()
    high_dollar_volume = dollar_volume > 10**7
    
    # ...and this to screen out penny stocks.
    sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    price = USEquityPricing.close.latest
    not_a_penny_stock = sma_200 > 5.0
    
    # Implement both of our screens.
    pipe.set_screen(high_dollar_volume & not_a_penny_stock)  
            
    # Used to avoid purchasing any leveraged ETFs 
    context.dont_buys = [sec for sec in security_lists.leveraged_etf_list]
    
def cancel_open_orders(context, data):
    for security in get_open_orders():
        for order in get_open_orders(security):
            cancel_order(order)
                      
class Value(CustomFactor):
    
    # Pre-declare inputs and window_length
    inputs = [morningstar.income_statement.ebit,
              morningstar.valuation.enterprise_value]
    window_length = 1
    
    def compute(self, today, assets, out, ebit, ev):
        out[:] = ebit[-1] / ev[-1]
        
        
#  Create a fundamental based custom "Quality" (profitability) factor
class Quality(CustomFactor):
    inputs = [morningstar.operation_ratios.roe]
    window_length = 1
    
    def compute(self, today, assets, out, roe):
        out[:] = roe[-1]
        
class Roic(CustomFactor):
    inputs = [morningstar.operation_ratios.roic]
    window_length = 1
    
    def compute(self, today, assets, out, roic):
        out[:] = roic[-1]
        
class Growth(CustomFactor):
    inputs = [morningstar.operation_ratios.revenue_growth]
    window_length = 1
    def compute(self, today, assets, out, growth):
        out[:] = growth[-1]      
        
class Sector(CustomFactor):
    inputs = [morningstar.asset_classification.morningstar_sector_code]
    window_length= 1
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]
        
class PEG(CustomFactor):
    inputs = [morningstar.valuation_ratios.peg_ratio]
    window_length = 1
    def compute(self, today, assets, out, peg):
        out[:] = peg[-1] 
        
class AvgDailyDollarVolumeTraded(CustomFactor):
    
    inputs = [USEquityPricing.close, USEquityPricing.volume]
    window_length = 20
    
    def compute(self, today, assets, out, close_price, volume):
        out[:] = np.mean(close_price * volume, axis=0)  
        
class Slope(CustomFactor):
    inputs = [USEquityPricing.close]
    def compute(self, today, assets, out, prices):
        Y = prices
        X = range(len(prices))
        A = sm.add_constant(X)
        results = sm.OLS(Y,A).fit()
        (b, a) =results.params
        slope = a / b * 252.0
        out[:] = slope
        
class PE_ratio(CustomFactor):
    inputs = [morningstar.valuation_ratios.pe_ratio]
    window_length= 1
    def compute(self, today, assets, out, pe):
        out[:] = pe[-1]

class Volatility(CustomFactor):    
    inputs = [USEquityPricing.close]
    window_length = 252
    
    def compute(self, today, assets, out, close):  
        close = pd.DataFrame(data=close, columns=assets) 
        # Since we are going to rank largest is best we need to invert the sdev.
        out[:] = 1 / np.log(close).diff().std()
        
normalize = lambda x : (x-x.mean())/x.std()                  

There was a runtime error.

and this is the other backtest, just a few months of 2010, now it do the trades with length_long_list non zero.

Clone Algorithm
4
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
import datetime
import statsmodels.api as sm
import numpy as np
import pandas as pd

'''
Algo Logic: 
1) define market uptrend and downtrend by the 252 days slope.
2) Group all stocks by sectors
3) Filter all the stocks of each sector by a combination of these factors: growth, value, roic, quality and 1/volatility
4) if the market is uptrend buy cyclical and sensitive stocks
5) if the market is downtrend buy sensitive and defensive stocks
'''

def initialize(context):
    context.num_stocks = 3
    
    context.defensive_sectors = [205,206,207] #Consumer_defensive, HealthCare, Utilities
    context.cyclical_sectors = [101,102,103,104] # Basic Materials, Consumer Cyclical, Financials, Real Estate
    context.sensitive_sectors = [308,309,310,311] # Communication, Energy, Industrials, Technology
    context.sectors = context.defensive_sectors + context.cyclical_sectors + context.sensitive_sectors
    context.fundamental_factors = ['growth', 'value','quality','roic', 'volatility']
    context.weigth = 0.95/(11*context.num_stocks)
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))
    create_pipeline(context)
    schedule_function(func=rebalance, 
                      date_rule=date_rules.month_end(days_offset=0), 
                      time_rule=time_rules.market_open(hours=0,minutes=30), 
                      half_days=True)

    schedule_function(func = cancel_open_orders,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_close(minutes=5),half_days=True )   
                  
def handle_data(context, data):
    # Record and plot the leverage, number of positions, and expsoure of our portfolio over time. 
    record(
           exposure=context.account.net_leverage, 
           longs = len([s for s in data if context.portfolio.positions[s].amount > 0]),
           shorts = len([s for s in data if context.portfolio.positions[s].amount < 0]),
           leverage=context.account.leverage,
    length_long_list= len(context.long_list) )

    
def before_trading_start(context, data):
    
    context.output = pipeline_output('ranking_example')
    
    #~~~~~~ RESET DICTS AND LISTS ~~~~~~#
    
    context.long_list=[]
    weigths = {}

    #~~~~~~ FILTER OUT DELISTED STOCKS  ~~~~~~#
    context.output['end_date'] = [stock.end_date for stock in context.output.index]
    context.output = context.output[(context.output['end_date'] > (get_datetime()+datetime.timedelta(days=10)))]
    df = context.output
    

    
    #~~~~~~ SECOND FILTERING:  RANKING EACH SECTORS STOCKS ~~~~~~#
    grouped = df.groupby('sector')   
    for sector, group in grouped:
        
        if group['slope'].mean() > 0.0:  #trend up: buy it --> select good stocks 
            roic = group['roic'] > 0.0
            growth = group['growth'] > 0.0
            value = group['value'] > group['value'] .mean()
            quality = group['quality'] > group['quality'].mean()
            group = group[roic & growth & value & quality]

            group = group[context.fundamental_factors]                   
            normalized = group.apply(normalize)
            fund = normalized.sum(axis=1) 
            selected = fund.order(ascending=False).iloc[:context.num_stocks]
            long_stocks = selected.index.tolist()
            volatility = group['volatility'].loc[long_stocks]
            weigths[sector] = volatility
            
            if len(long_stocks) > 0:
                for stock in long_stocks:
                    context.long_list.append(stock)
            else:
                pass # No good stocks for this sector
                
        else:  
            pass # Sector has negative slope
    long_weigths = pd.DataFrame(weigths)
    long_weigths = long_weigths.sum(axis=1)
    context.weigths = long_weigths/long_weigths.sum()
    update_universe(context.long_list)
def rebalance(context,data):
    print 'length of long list: {}'.format(len(context.long_list))
    # Order our longs
    log.info("ordering longs")

    for long_stock in context.long_list:
        if long_stock in data:
            if long_stock in context.dont_buys:
                continue
            order_target_percent(long_stock, context.weigths.loc[long_stock])
      
    # Get rid of any stocks incorrectly held
    for security in context.portfolio.positions:
        if get_open_orders(security):
            continue
        if security in data:
            if security in context.dont_buys:
                continue
            if security not in context.long_list:
                order_target_percent(security, 0)

def create_pipeline(context):
    pipe_columns = {'roic': Value(), 'growth': Quality(), 'sector':Sector(), 'quality':Quality(), 'value':Value(),
                    'slope': Slope(window_length=252), 
                    'volatility': Volatility()}
    pipe = Pipeline(columns=pipe_columns)
    attach_pipeline(pipe, 'ranking_example')
    
    # We'll use this to screen out illiquid stocks...
    dollar_volume = AvgDailyDollarVolumeTraded()
    high_dollar_volume = dollar_volume > 10**7
    
    # ...and this to screen out penny stocks.
    sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    price = USEquityPricing.close.latest
    not_a_penny_stock = sma_200 > 5.0
    
    # Implement both of our screens.
    pipe.set_screen(high_dollar_volume & not_a_penny_stock)  
            
    # Used to avoid purchasing any leveraged ETFs 
    context.dont_buys = [sec for sec in security_lists.leveraged_etf_list]
    
def cancel_open_orders(context, data):
    for security in get_open_orders():
        for order in get_open_orders(security):
            cancel_order(order)
                      
class Value(CustomFactor):
    
    # Pre-declare inputs and window_length
    inputs = [morningstar.income_statement.ebit,
              morningstar.valuation.enterprise_value]
    window_length = 1
    
    def compute(self, today, assets, out, ebit, ev):
        out[:] = ebit[-1] / ev[-1]
        
        
#  Create a fundamental based custom "Quality" (profitability) factor
class Quality(CustomFactor):
    inputs = [morningstar.operation_ratios.roe]
    window_length = 1
    
    def compute(self, today, assets, out, roe):
        out[:] = roe[-1]
        
class Roic(CustomFactor):
    inputs = [morningstar.operation_ratios.roic]
    window_length = 1
    
    def compute(self, today, assets, out, roic):
        out[:] = roic[-1]
        
class Growth(CustomFactor):
    inputs = [morningstar.operation_ratios.revenue_growth]
    window_length = 1
    def compute(self, today, assets, out, growth):
        out[:] = growth[-1]      
        
class Sector(CustomFactor):
    inputs = [morningstar.asset_classification.morningstar_sector_code]
    window_length= 1
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]
        
class PEG(CustomFactor):
    inputs = [morningstar.valuation_ratios.peg_ratio]
    window_length = 1
    def compute(self, today, assets, out, peg):
        out[:] = peg[-1] 
        
class AvgDailyDollarVolumeTraded(CustomFactor):
    
    inputs = [USEquityPricing.close, USEquityPricing.volume]
    window_length = 20
    
    def compute(self, today, assets, out, close_price, volume):
        out[:] = np.mean(close_price * volume, axis=0)  
        
class Slope(CustomFactor):
    inputs = [USEquityPricing.close]
    def compute(self, today, assets, out, prices):
        Y = prices
        X = range(len(prices))
        A = sm.add_constant(X)
        results = sm.OLS(Y,A).fit()
        (b, a) =results.params
        slope = a / b * 252.0
        out[:] = slope
        
class PE_ratio(CustomFactor):
    inputs = [morningstar.valuation_ratios.pe_ratio]
    window_length= 1
    def compute(self, today, assets, out, pe):
        out[:] = pe[-1]

class Volatility(CustomFactor):    
    inputs = [USEquityPricing.close]
    window_length = 252
    
    def compute(self, today, assets, out, close):  
        close = pd.DataFrame(data=close, columns=assets) 
        # Since we are going to rank largest is best we need to invert the sdev.
        out[:] = 1 / np.log(close).diff().std()
        
normalize = lambda x : (x-x.mean())/x.std()                  

There was a runtime error.

Hi Giuseppe,

Ah, I see what you're saying. This is caused by a bug where if you end up with an empty universe at some point in your backtest, any bar from that point on will skip handle_data and all of your scheduled functions. The length of your context.long_list actually goes back up to non-zero at the end of 2009 but since your handle_data was being skipped, the record() function wasn't working properly (I confirmed non-zero values with logging).

I've implemented a workaround in your code that adds a dummy stock (SPY) to your universe when it would otherwise be empty, and sets a flag context.run to false in this case. Then, handle_data and your scheduled functions are skipped by your code instead of by the bug, and when you end up with non-zero length context.long_list, it will resume trading.

Again, this is a bug on our end. We'll have to get it fixed.

Let me know if you have any questions!

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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
import datetime
import statsmodels.api as sm
import numpy as np
import pandas as pd

'''
Algo Logic: 
1) define market uptrend and downtrend by the 252 days slope.
2) Group all stocks by sectors
3) Filter all the stocks of each sector by a combination of these factors: growth, value, roic, quality and 1/volatility
4) if the market is uptrend buy cyclical and sensitive stocks
5) if the market is downtrend buy sensitive and defensive stocks
'''

def initialize(context):
    context.num_stocks = 3
    
    context.defensive_sectors = [205,206,207] #Consumer_defensive, HealthCare, Utilities
    context.cyclical_sectors = [101,102,103,104] # Basic Materials, Consumer Cyclical, Financials, Real Estate
    context.sensitive_sectors = [308,309,310,311] # Communication, Energy, Industrials, Technology
    context.sectors = context.defensive_sectors + context.cyclical_sectors + context.sensitive_sectors
    context.fundamental_factors = ['growth', 'value','quality','roic', 'volatility']
    context.weigth = 0.95/(11*context.num_stocks)
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    set_slippage(slippage.FixedSlippage(spread=0))
    create_pipeline(context)
    schedule_function(func=rebalance, 
                      date_rule=date_rules.month_end(days_offset=0), 
                      time_rule=time_rules.market_open(hours=0,minutes=30), 
                      half_days=True)

    schedule_function(func = cancel_open_orders,
                     date_rule = date_rules.every_day(),
                     time_rule = time_rules.market_close(minutes=5),half_days=True )   
                  
def handle_data(context, data):
    if not context.run and len(data) <= 1:
        return
    # Record and plot the leverage, number of positions, and expsoure of our portfolio over time. 
    record(
           exposure=context.account.net_leverage, 
           longs = len([s for s in data if context.portfolio.positions[s].amount > 0]),
           shorts = len([s for s in data if context.portfolio.positions[s].amount < 0]),
           leverage=context.account.leverage,
    length_long_list= len(context.long_list) )

    
def before_trading_start(context, data):
    
    context.output = pipeline_output('ranking_example')
    
    #~~~~~~ RESET DICTS AND LISTS ~~~~~~#
    
    context.long_list=[]
    weigths = {}

    #~~~~~~ FILTER OUT DELISTED STOCKS  ~~~~~~#
    context.output['end_date'] = [stock.end_date for stock in context.output.index]
    context.output = context.output[(context.output['end_date'] > (get_datetime()+datetime.timedelta(days=10)))]
    df = context.output
    

    
    #~~~~~~ SECOND FILTERING:  RANKING EACH SECTORS STOCKS ~~~~~~#
    grouped = df.groupby('sector')   
    for sector, group in grouped:
        
        if group['slope'].mean() > 0.0:  #trend up: buy it --> select good stocks 
            roic = group['roic'] > 0.0
            growth = group['growth'] > 0.0
            value = group['value'] > group['value'] .mean()
            quality = group['quality'] > group['quality'].mean()
            group = group[roic & growth & value & quality]

            group = group[context.fundamental_factors]                   
            normalized = group.apply(normalize)
            fund = normalized.sum(axis=1) 
            selected = fund.order(ascending=False).iloc[:context.num_stocks]
            long_stocks = selected.index.tolist()
            volatility = group['volatility'].loc[long_stocks]
            weigths[sector] = volatility
            
            if len(long_stocks) > 0:
                for stock in long_stocks:
                    context.long_list.append(stock)
            else:
                pass # No good stocks for this sector
                
        else:  
            pass # Sector has negative slope
    long_weigths = pd.DataFrame(weigths)
    long_weigths = long_weigths.sum(axis=1)
    context.weigths = long_weigths/long_weigths.sum()
    if len(context.long_list) > 0:
        update_universe(context.long_list)
        context.run = True
    else:
        update_universe([sid(8554)])
        context.run = False
    
def rebalance(context,data):
    if not context.run and len(data) <= 1:
        return
    print 'here'
    print 'length of long list: {}'.format(len(context.long_list))
    # Order our longs
    log.info("ordering longs")

    for long_stock in context.long_list:
        if long_stock in data:
            if long_stock in context.dont_buys:
                continue
            order_target_percent(long_stock, context.weigths.loc[long_stock])
      
    # Get rid of any stocks incorrectly held
    for security in context.portfolio.positions:
        if get_open_orders(security):
            continue
        if security in data:
            if security in context.dont_buys:
                continue
            if security not in context.long_list:
                order_target_percent(security, 0)

def create_pipeline(context):
    pipe_columns = {'roic': Value(), 'growth': Quality(), 'sector':Sector(), 'quality':Quality(), 'value':Value(),
                    'slope': Slope(window_length=252), 
                    'volatility': Volatility()}
    pipe = Pipeline(columns=pipe_columns)
    attach_pipeline(pipe, 'ranking_example')
    
    # We'll use this to screen out illiquid stocks...
    dollar_volume = AvgDailyDollarVolumeTraded()
    high_dollar_volume = dollar_volume > 10**7
    
    # ...and this to screen out penny stocks.
    sma_200 = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200)
    price = USEquityPricing.close.latest
    not_a_penny_stock = sma_200 > 5.0
    
    # Implement both of our screens.
    pipe.set_screen(high_dollar_volume & not_a_penny_stock)  
            
    # Used to avoid purchasing any leveraged ETFs 
    context.dont_buys = [sec for sec in security_lists.leveraged_etf_list]
    
def cancel_open_orders(context, data):
    if not context.run and len(data) <= 1:
        return
    for security in get_open_orders():
        for order in get_open_orders(security):
            cancel_order(order)
                      
class Value(CustomFactor):
    
    # Pre-declare inputs and window_length
    inputs = [morningstar.income_statement.ebit,
              morningstar.valuation.enterprise_value]
    window_length = 1
    
    def compute(self, today, assets, out, ebit, ev):
        out[:] = ebit[-1] / ev[-1]
        
        
#  Create a fundamental based custom "Quality" (profitability) factor
class Quality(CustomFactor):
    inputs = [morningstar.operation_ratios.roe]
    window_length = 1
    
    def compute(self, today, assets, out, roe):
        out[:] = roe[-1]
        
class Roic(CustomFactor):
    inputs = [morningstar.operation_ratios.roic]
    window_length = 1
    
    def compute(self, today, assets, out, roic):
        out[:] = roic[-1]
        
class Growth(CustomFactor):
    inputs = [morningstar.operation_ratios.revenue_growth]
    window_length = 1
    def compute(self, today, assets, out, growth):
        out[:] = growth[-1]      
        
class Sector(CustomFactor):
    inputs = [morningstar.asset_classification.morningstar_sector_code]
    window_length= 1
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]
        
class PEG(CustomFactor):
    inputs = [morningstar.valuation_ratios.peg_ratio]
    window_length = 1
    def compute(self, today, assets, out, peg):
        out[:] = peg[-1] 
        
class AvgDailyDollarVolumeTraded(CustomFactor):
    
    inputs = [USEquityPricing.close, USEquityPricing.volume]
    window_length = 20
    
    def compute(self, today, assets, out, close_price, volume):
        out[:] = np.mean(close_price * volume, axis=0)  
        
class Slope(CustomFactor):
    inputs = [USEquityPricing.close]
    def compute(self, today, assets, out, prices):
        Y = prices
        X = range(len(prices))
        A = sm.add_constant(X)
        results = sm.OLS(Y,A).fit()
        (b, a) =results.params
        slope = a / b * 252.0
        out[:] = slope
        
class PE_ratio(CustomFactor):
    inputs = [morningstar.valuation_ratios.pe_ratio]
    window_length= 1
    def compute(self, today, assets, out, pe):
        out[:] = pe[-1]

class Volatility(CustomFactor):    
    inputs = [USEquityPricing.close]
    window_length = 252
    
    def compute(self, today, assets, out, close):  
        close = pd.DataFrame(data=close, columns=assets) 
        # Since we are going to rank largest is best we need to invert the sdev.
        out[:] = 1 / np.log(close).diff().std()
        
normalize = lambda x : (x-x.mean())/x.std()                  

There was a runtime error.

Thank you very much Jamie!
Everything clear :)