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
299
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 54e4ab4fc213650f0114139c
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
54
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 55ed448f8e74c50dda0e6cbf
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
3
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5a5db142bf4c1740f2bcee63
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