Back to Community
Quantopian Open: Example algorithm to control leverage

In the Quantopian Open, leverage is constrained to 3x for eligible entries. You can track and control your algorithm leverage using the context.account.leverage variable.

Below is an example momentum strategy, seeking equal weights in several volatile stocks based on their moving averages. The portfolio is leveraged to 2.45x and starts to exit positions if the leverage exceeds 2.5x.

Feel free to clone the algo, and use the leverage controllers in your contest algos. Good luck!

Clone Algorithm
327
Loading...
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
# This example is a demonstration of how to keep account leverage limited to 3x  
# 3X is the limit set for the Quantopian Open.
# The algorithm is a price-momentum type.

# Link to contest: https://www.quantopian.com/open


def initialize(context):
    # create the universe of securities
    context.stocks = symbols('FSLR', 'CREE', 'GRPN', 'NFLX', 'GMCR')  # a few volatile stocks
    
    # allocate equal weights to each stock
    # lever the portfolio to 2.45X
    context.weight = 2.45/len(context.stocks) 
    context.entered_short = False
    context.leverage_buffer = 2.5
    schedule_function(
        func=monthly_rebal,
        date_rule=date_rules.month_start(),
        time_rule=time_rules.market_close(minutes=1),
        half_days=True
      )
    
    
# Will be called on every bar for the securities you specify. 
def handle_data(context, data):
    
    # Track the algorithm's leverage, and put it on the custom graph
    leverage = context.account.leverage
    
    record(leverage=leverage)
    
    # order_target functions don't consider open orders when making calculations.
    # Add this guard to prevent over-ordering
    if get_open_orders():
        return
    
    for stock in data:
        # Check the account leverage, leaving a buffer for open orders
        # Liquidate the short position if the leverage is approaching the 3x limit
        if leverage > context.leverage_buffer:
            log.info("Approaching leverage limit. Current leverage is %s" % (leverage))

            # Need to liquidate short position
            if context.entered_short == True:
                log.info("Liquidating position %s" % (stock))
                order_target_percent(stock, 0)
            return
        
def monthly_rebal(context, data):
    for stock in data:    
        # Use history to store the last 100 days of daily pricing to a pandas dataframe
        trailing_prices = history(100, '1d', 'price')[stock]
        slowMA = trailing_prices.mean()

        # Define the fast moving average window to use only the last 20 days of historical pricing
        fastMA = trailing_prices[-21:-1].mean() 
    
        # Sell short if the fast moving average is below the slow moving average
        if fastMA < slowMA:
            order_target_percent(stock,context.weight)
        
        elif fastMA >= slowMA:
            #Go long if the fast moving average is equal to or above the slow moving average
            order_target_percent(stock,context.weight)
            context.entered_short = True
        
        


    
    
    
    
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.

12 responses

Hi Alisa,

Thanks for this. I know it's just demonstrating the use of context.account.leverage and not really meant to be an real algorithm, but a few things make it a little confusing at least to me.

  1. It doesn't seem to actually short anything even though it says it does
  2. It doesn't really back out of any shorts -- it just liquidates the first stock to come in via the "for stock in data" iterator.
  3. The "context.entered_short" variable doesn't appear mean anything - it just gets set to true on the first rebalance and remains true for ever after

Alan

Hi Alisa,

Thank you for writing this. I have been testing testing strategy at the minutely level and realised the 'context.account.leverage' method aggregate my trades and reported it as greater than the actual leverage.

Let me use an example to illustrate this. Say my balance is $100k and my long/short strategy buy and sell at the same time for a total of $100k (50k long, 50k short, dollar neutral). A single trade like this, the 'context.account.leverage' method will report it as 1.

However, if during the day the algo make 10 trades, and to be precise the algo closes each pair trades before starting a new one, the 'context.account.leverage' method will report it as 10. It seems to aggregate the intraday trades and exposure to daily level. I take this as meaning I have breached the maximum allowable leverage level of 3. I find it somewhat puzzling as it seems to punish higher frequency trades unnecessarily. Is this a bug in the system?

Sorry if some one has raised this point previously. I have been searching the community but not able to find a solution to this.

I am facing the same problem.The leverage is much more than 3 the maximum permissible limit when trading on strategies using minute based data

Hi- I am not sure what else to do now to try to control leverage. I have use the open order guard everywhere (though not sure if correctly) and also liquidating function once leverage exceeds buffer but I still keep shooting out of whack for some reason. Anyone have suggestions how I can trace the source? I also added logic (to my hodgepodge snippets of code) to not make any orders if leverage is over x%.

Clone Algorithm
55
Loading...
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
#TO DOOO!!!
#exclude volity index http://etf.stock-encyclopedia.com/category/volatility-index-(vix)-etfs.html

# figure out how to track sids that have hit losses and stop it from trading for X days https://www.quantopian.com/posts/pausing-my-trading-until-n-many-days-into-the-backtest
#https://www.quantopian.com/posts/issue-with-symbols-dot-dot-dot

# figure out how to track total portfolio drawdown and if below X % drop, stop trading for X days

# order the measures to limit to only buy top 6-8 stocks

#stop buying and selling the same stocks you just transacted

# - See more at: http://mebfaber.com/2015/06/16/three-way-model/#sthash.nUERh7tS.dpuf
import pandas as pd
import talib as ta
import numpy as np
from numpy import array
import datetime  


def initialize(context):
    context.longterm  = 30
    context.shortterm = 2
    context.N = (context.longterm)*30
    set_do_not_order_list(security_lists.leveraged_etf_list)   
    set_universe(universe.DollarVolumeUniverse(95.5, 99.9))
    context.exclude = [sid(38054), sid(40408), sid(48180), sid(39922), sid(41837), sid(38055), sid(41968), sid(41969), sid(40670), sid(40669), sid(40523)]    
    context.temp = []
    #myDataFrame.as_matrix(context.temp)    
    #set #shares of this universe we want to invest in individually in short/long
    context.pct_universe_to_buy = 5     
    total_minutes = 6*60 + 30

    for i in range(total_minutes):
    # Every 30 minutes run schedule
        if i % 30 == 1:
      # This will start at 9:31AM and will run every 30 minutes
            schedule_function(
            handle_data_daily,
                date_rules.every_day(),
                time_rules.market_open(minutes=i),
                True
            )   
    #schedule_function(handle_data_daily,
    #                  date_rule=date_rules.every_day(),
    #                  time_rule=time_rules.market_open(minutes=30))
    
    schedule_function(cleartemp,
                      date_rule=date_rules.week_end(),
                     time_rule=time_rules.market_close(minutes=2))    
# Will be called on every trade event for the securities you specify. 
    context.long_stop_pct = .975
    context.short_stop_pct = 1.025
#    context.max_notional = 100000.0  
#    context.min_notional = -100000.0
    set_max_position_size(sid, max_shares=10000, max_notional=25000.0)    
    context.leverage_buffer = 2.5

    context.date=None  
    context.timestep=0
    context.tradedate = dict()
    context.s = 0
    
    
def handle_data(context, data):
    # Track the algorithm's leverage, and put it on the custom graph
    leverage = context.account.leverage
    
    record(leverage=leverage)
    record(netlev = context.account.net_leverage)
    
    # order_target functions don't consider open orders when making calculations.
    # Add this guard to prevent over-ordering
    if get_open_orders():
        return    
    for sid in data:
        # Check the account leverage, leaving a buffer for open orders
        # Liquidate the short position if the leverage is approaching the 3x limit
        print context.portfolio.positions[sid].amount
        if leverage > context.leverage_buffer:
            log.info("Approaching leverage limit. Current leverage is %s" % (leverage))   
            log.info("Liquidating position %s" % (sid))
            if context.portfolio.positions[sid].amount > 0:
                order(sid, context.portfolio.positions[sid].amount*-0.5)
            if context.portfolio.positions[sid].amount < 0:
                order(sid, context.portfolio.positions[sid].amount*0.5)                
            
        return 

    if get_datetime().day <> context.date: #look for a new day  
        context.date=get_datetime().day
        context.timestep += 1  
        
def handle_data_daily(context, data):
    context.sids = data.keys()
    prices =  history(context.N, frequency="1d", field='price')
    prices = prices.dropna(axis=1)    
    prices = prices.resample('BM', how='last',closed ='left', label='left')
    pricesshort =  prices.apply(ta.SMA, timeperiod=context.shortterm)
    priceslong  =  prices.apply(ta.SMA, timeperiod=context.longterm)
    
    ranges = pricesshort.iloc[-1] - priceslong.iloc[-1]
    ranges.sort(ascending=False)
    num_stocks = round(int(min(len(ranges), context.pct_universe_to_buy)))
    top = ranges.keys()[0:num_stocks-1]
    
    rangesD = priceslong.iloc[-1] - pricesshort.iloc[-1]
    rangesD.sort(ascending=False)
    num_stocksD = round(int(min(len(rangesD), context.pct_universe_to_buy)))
    bottom = rangesD.keys()[0:num_stocksD-1]    
    
    #updown = pricesshort.iloc[-1] > priceslong.iloc[-1]
    #downup = pricesshort.iloc[-1] < priceslong.iloc[-1]
    #weight = 1.0/len(updown[updown==True])
    #weightdown = -1.0/len(downup[downup==True])
    today = pd.Timestamp(get_datetime().date())    
    hist = history(60, '1m', 'price').ix[today:]
    simple_returns = hist.pct_change()
    avg_simple_return = simple_returns.mean()
    mkt=avg_simple_return[symbol('SPY')]*10000
    mkt1 = data[symbol('SPY')].returns()*100
    record(Spy=mkt)
    record(Spy1=mkt1)
    
    #print(context.temp[1::2]) # gives dates of trade
    #print (context.temp)
    #print (len(context.temp))
    #print (context.temp[::2]) # gives positions in list
    
    
    if abs(mkt)>2:
        if get_open_orders():
            return
        for stock in context.portfolio.positions:
            order_target_percent(stock,0)
    else:
        if get_open_orders():
            return
        for sid in context.sids:
            if abs(mkt)<2:
                if sid in top:
                    if mkt >0:
                        if sid not in security_lists.leveraged_etf_list:
                            if sid not in context.exclude:
                                if sid not in context.temp:
                                    if sid not in context.portfolio.positions:
                                        if context.account.leverage < 2.75:
                                            weight = min(1.6/len(top),0.4)
                                            order_target_percent(sid,weight)
                                            context.temp.append(sid)
                                        #context.temp.insert(context.s+1,get_datetime().date())
                if sid in bottom:
                    if mkt<0:
                        if sid not in security_lists.leveraged_etf_list:
                            if sid not in context.exclude: 
                                if sid not in context.temp:
                                    if sid not in context.portfolio.positions:
                                        if context.account.leverage < 2.75:
                                            weight = min(1.6/len(bottom),0.4)
                                            order_target_percent(sid,-weight)
                                            context.temp.append(sid)
                                        #context.temp.insert(context.s+1,get_datetime().date())
                elif sid not in top and sid not in bottom:
                    if sid not in security_lists.leveraged_etf_list:
                        if sid not in context.exclude: 
                            order_target_value(sid,0)
            pass
        
    if get_open_orders():
        return
    for sid in context.portfolio.positions:
        if not get_open_orders(sid):        
            price = data[sid].price
            qty = context.portfolio.positions[sid].amount    
            if qty >0:
                long_stop_price = context.portfolio.positions[sid].cost_basis * context.long_stop_pct
            if qty <0:
                short_stop_price = context.portfolio.positions[sid].cost_basis * context.short_stop_pct
                #print short_stop_price
            if qty > 0 and price < long_stop_price:
                order(sid,-qty)
                log.info('stoplossLONG hit {s}'.format(s=sid.symbol))
                context.temp.append(sid)
                #context.temp.insert(context.s+1,get_datetime().date())
                
            elif qty < 0 and price > short_stop_price:
                order(sid,+qty)
                log.info('stoplossSHORT hit {s}'.format(s=sid.symbol))
                context.temp.append(sid)
                #context.temp.insert(context.s+1,get_datetime().date())

def cleartemp(context, data):               
    context.temp = []             
            
There was a runtime error.

...any suggestions please regarding where to look to solve this?

Hi Umar,

I've taken a look at the code you provided in your post, and it seems as though your call to set_max_position_size on line 56 incorrectly passes sid (a method name, not a variable) as an input parameter. To solve this, you need to pass a specific sid such as sid(38054). Of course, you can do this for multiple sids.

In general, I strongly advise against using the word sid as a variable name, as this makes it easier for you to get mixed up between the method name, and your variables.

All this being said, the set_max_position_size method should not have accepted a method name as an input parameter, and I have brought this to the attention of our engineers, so it should be fixed soon.

Let me know if this helps!

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.

@ Alisa Deychman

Hi Alisa ,
In your algorithm , data object is deprecated , how possibly I can change it ?

Thank You in Advance

It looks like you found an old thread! In the past two years we've added a lot to the platform. Namely, the pipeline API to create factors and filters, and to dynamically filter your trading universe. You can use the QTradeableStocksUS to choose from liquid, tradable stocks. And then use the optimize API to execute your orders. Within the optimize API you can set constraints such as max leverage, max gross exposure, and others.

To get started with these tools, take a look at these links:

Hello Alisa,

Many thanks for your hint to the Opti Api. I gave it a try and it gives good results wrt speed and robustness. But leverage is an issue. I used MaxGrossExposure to try to control it, but hat no luck to bring the code into a contest.

You mentioned "max leverage in your text. Could you help me with that and tell how to use it. The IDE cannot find something like that for "opti".

Thanks HAns

Hans, it's easiest to debug when you can share an algo. Could you start a new thread and share the backtest (or a skeleton of the code) that you're working on? We can then see the API calls you're making and help with the leverage control.

Alisa,

thanks for your answer. Below my code. I use the API in the method "rebalance". Any help is very welcome.

I attach the backtest with the leverage plotted. I do not believe that it can be above 1.1 in other backtests.

Hans

from quantopian.algorithm import attach_pipeline, pipeline_output, order_optimal_portfolio
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage, AverageDollarVolume, RollingLinearRegressionOfReturns
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters.morningstar import IsPrimaryShare
from quantopian.pipeline.classifiers.morningstar import Sector

import numpy as np
import pandas as pd

import quantopian.optimize as opt

Constraint Parameters

MAX_GROSS_EXPOSURE = 0.1
NUM_LONG_POSITIONS = 25
NUM_SHORT_POSITIONS = 25

MAX_SHORT_POSITION_SIZE = 2*1.0/(NUM_LONG_POSITIONS + NUM_SHORT_POSITIONS)
MAX_LONG_POSITION_SIZE = 2*1.0/(NUM_LONG_POSITIONS + NUM_SHORT_POSITIONS)

Risk Exposures

MAX_SECTOR_EXPOSURE = 0.10
MAX_BETA_EXPOSURE = 0.20

good lengt 30, number pos = 30

def make_pipeline():

dollar_volume = AverageDollarVolume(window_length=200)#  
universe = dollar_volume.percentile_between(10, 40) # 40:182  
slope_long = Dev(mask=universe, inputs=[USEquityPricing().close], window_length=23)  

combined_rank =   slope_long.rank(mask=universe)

longs = combined_rank.top(NUM_LONG_POSITIONS)  
shorts = combined_rank.bottom(NUM_SHORT_POSITIONS)

long_short_screen = (longs | shorts)

# Create pipeline  
pipe = Pipeline(columns = {  
    'longs':longs,  
    'shorts':shorts,  
    'combined_rank':combined_rank  
},  
screen = long_short_screen)  
return pipe

def initialize(context):
set_commission(commission.PerShare(cost=0.0, min_trade_cost=0))
set_slippage(slippage.VolumeShareSlippage(volume_limit=1, price_impact=0))
context.spy = sid(8554)

attach_pipeline(make_pipeline(), 'long_short_equity_template')

# Schedule my rebalance function  
schedule_function(func=rebalance,  
                  date_rule=date_rules.every_day(),  
                  time_rule=time_rules.market_open(hours=0,minutes=30),  
                  half_days=True)  
# record my portfolio variables at the end of day  
schedule_function(func=recording_statements,  
                  date_rule=date_rules.every_day(),  
                  time_rule=time_rules.market_close(),  
                  half_days=True)

def before_trading_start(context, data):
context.pipeline_data = pipeline_output('long_short_equity_template')

def recording_statements(context, data):
#record(num_positions=len(context.portfolio.positions))
record(leverage=context.account.leverage)

def rebalance(context, data):

pipeline_data = context.pipeline_data

objective = opt.MaximizeAlpha(pipeline_data.combined_rank)  
constraints = []  
# Constrain our maximum gross leverage  
constraints.append(opt.MaxGrossExposure(MAX_GROSS_EXPOSURE))  
constraints.append(opt.DollarNeutral())  
constraints.append(  
    opt.PositionConcentration.with_equal_bounds(  
        min=-MAX_SHORT_POSITION_SIZE,  
        max=MAX_LONG_POSITION_SIZE  
    ))

order_optimal_portfolio(  
    objective=objective,  
    constraints=constraints,  
)  

class Dev(CustomFactor):
def compute(self, today, asset_ids, out, values):
# Calculates the column-wise standard deviation, ignoring NaNs
x = []

    nDays = values.shape[0]  
    nShares = values.shape[1]  
    for iShare in range(0, nShares):  
        mean = 0  
        for iDay in range(0, nDays):  
            mean = mean + values[iDay][iShare]  
        mean = mean / nDays  

        for iDay in range(0, nDays):  
            values[iDay][iShare] = values[iDay][iShare] / mean  

    out[:] =    values[nDays-1,:]  
Clone Algorithm
5
Loading...
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, order_optimal_portfolio
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage, AverageDollarVolume, RollingLinearRegressionOfReturns
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters.morningstar import IsPrimaryShare
from quantopian.pipeline.classifiers.morningstar import Sector

import numpy as np
import pandas as pd

# from quantopian.pipeline.filters import Q1500US
import quantopian.optimize as opt

# Constraint Parameters
MAX_GROSS_EXPOSURE = 0.1
NUM_LONG_POSITIONS = 25
NUM_SHORT_POSITIONS = 25

# Here we define the maximum position size that can be held for any
# given stock. If you have a different idea of what these maximum 
# sizes should be, feel free to change them. Keep in mind that the
# optimizer needs some leeway in order to operate. Namely, if your
# maximum is too small, the optimizer may be overly-constrained.
MAX_SHORT_POSITION_SIZE = 2*1.0/(NUM_LONG_POSITIONS + NUM_SHORT_POSITIONS)
MAX_LONG_POSITION_SIZE = 2*1.0/(NUM_LONG_POSITIONS + NUM_SHORT_POSITIONS)

# Risk Exposures
MAX_SECTOR_EXPOSURE = 0.10
MAX_BETA_EXPOSURE = 0.20
        
# good lengt 30, number pos = 30 

def make_pipeline():

    dollar_volume = AverageDollarVolume(window_length=200)#
    universe = dollar_volume.percentile_between(10, 40) # 40:182
    slope_long = Dev(mask=universe, inputs=[USEquityPricing().close], window_length=23)
 
    combined_rank =   slope_long.rank(mask=universe)

    longs = combined_rank.top(NUM_LONG_POSITIONS)
    shorts = combined_rank.bottom(NUM_SHORT_POSITIONS)

    long_short_screen = (longs | shorts)
    
 

    # Create pipeline
    pipe = Pipeline(columns = {
        'longs':longs,
        'shorts':shorts,
        'combined_rank':combined_rank
    },
    screen = long_short_screen)
    return pipe




def initialize(context):
    # Here we set our slippage and commisions. Set slippage 
    # and commission to zero to evaulate the signal-generating
    # ability of the algorithm independent of these additional
    # costs.
    set_commission(commission.PerShare(cost=0.0, min_trade_cost=0))
    set_slippage(slippage.VolumeShareSlippage(volume_limit=1, price_impact=0))
    context.spy = sid(8554)

    attach_pipeline(make_pipeline(), 'long_short_equity_template')

    # Schedule my rebalance function
    schedule_function(func=rebalance,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_open(hours=0,minutes=30),
                      half_days=True)
    # record my portfolio variables at the end of day
    schedule_function(func=recording_statements,
                      date_rule=date_rules.every_day(),
                      time_rule=time_rules.market_close(),
                      half_days=True)


def before_trading_start(context, data):
    # Call pipeline_output to get the output
    # Note: this is a dataframe where the index is the SIDs for all
    # securities to pass my screen and the columns are the factors
    # added to the pipeline object above
    context.pipeline_data = pipeline_output('long_short_equity_template')


def recording_statements(context, data):
    # Plot the number of positions over time.
    #record(num_positions=len(context.portfolio.positions))
    record(leverage=context.account.leverage)


# Called at the start of every month in order to rebalance
# the longs and shorts lists
def rebalance(context, data):
    ### Optimize API
                                                 
                                                      
    pipeline_data = context.pipeline_data

    ### Extract from pipeline any specific risk factors you want 
     
    
    ### Here we define our objective for the Optimize API. We have
    # selected MaximizeAlpha because we believe our combined factor
    # ranking to be proportional to expected returns. This routine
    # will optimize the expected return of our algorithm, going
    # long on the highest expected return and short on the lowest.
    objective = opt.MaximizeAlpha(pipeline_data.combined_rank)
    
    ### Define the list of constraints
    constraints = []
    # Constrain our maximum gross leverage
    constraints.append(opt.MaxGrossExposure(MAX_GROSS_EXPOSURE))
    
    # Require our algorithm to remain dollar neutral
    constraints.append(opt.DollarNeutral())
    # Take the risk factors that you extracted above and
    # list your desired max/min exposures to them -
    # Here we selection +/- 0.01 to remain near 0.
 
    # With this constraint we enforce that no position can make up
    # greater than MAX_SHORT_POSITION_SIZE on the short side and
    # no greater than MAX_LONG_POSITION_SIZE on the long side. This
    # ensures that we do not overly concentrate our portfolio in
    # one security or a small subset of securities.
    constraints.append(
        opt.PositionConcentration.with_equal_bounds(
            min=-MAX_SHORT_POSITION_SIZE,
            max=MAX_LONG_POSITION_SIZE
        ))

    # Put together all the pieces we defined above by passing
    # them into the order_optimal_portfolio function. This handles
    # all of our ordering logic, assigning appropriate weights
    # to the securities in our universe to maximize our alpha with
    # respect to the given constraints.
    order_optimal_portfolio(
        objective=objective,
        constraints=constraints,
    )                                                      
                                                                                                            
        
        
class Dev(CustomFactor):
    def compute(self, today, asset_ids, out, values):
        # Calculates the column-wise standard deviation, ignoring NaNs
        x = []

        nDays = values.shape[0]
        nShares = values.shape[1]
        for iShare in range(0, nShares):
            mean = 0
            for iDay in range(0, nDays):
                mean = mean + values[iDay][iShare]
            mean = mean / nDays
            
            for iDay in range(0, nDays):
                values[iDay][iShare] = values[iDay][iShare] / mean
        
      
    
        out[:] =    values[nDays-1,:]
There was a runtime error.

Hello Alisa,

in between I got a feedback from the support stating that the error message is a little bit misleading. My issue is not a too high leverage but a too low.

To avoid these issues I use the notebook: "A New Contest is Coming: More Winners and a New Scoring System". Easy to handle and with detailed error messages.

Thanks anyway for your help, Hans