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!

327
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.

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%.

55
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
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.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)
top = ranges.keys()[0:num_stocks-1]

rangesD = priceslong.iloc[-1] - pricesshort.iloc[-1]
rangesD.sort(ascending=False)
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 ?

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

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_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)


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,:]

5
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

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_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)

# 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