Quantopian portfolio limit

Hey everybody, I'm new here and to automatic trading. I'm just a little curious if its possible to run out of money while backtesting? This sample algorithm just buys stocks, no logic. Does Quantopian convert stocks to cash when cash goes below 0?

18
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
  # For this example, we're going to write a simple momentum script.  When the
# stock goes up quickly, we're going to buy; when it goes down quickly, we're
# going to sell.  Hopefully we'll ride the waves.

# To run an algorithm in Quantopian, you need two functions: initialize and
# handle_data.

def initialize(context):
# This initialize function sets any data or variables that you'll use in
# your algorithm.  For instance, you'll want to define the security (or
# securities) you want to backtest.  You'll also want to define any
# parameters or values you're going to use.

# In our example, we're looking at Apple.  If you re-type this line
# yourself, you'll see the auto-complete that is available for the
# security ID.
context.aapl = sid(24)

# In these two lines, we set the maximum and minimum we want our algorithm
# to go long or short our security.  You don't have to set limits like this
# when you write an algorithm, but it's good practice.
context.max_notional = 1000000.1
context.min_notional = -1000000.0

def handle_data(context, data):
# This handle_data function is where the real work is done.  Our data is
# minute-level tick data, and each minute is called a frame.  This function
# runs on each frame of the data.

# We've built a handful of useful data transforms for you to use.  In this
# line, we're computing the volume-weighted-average-price of the security
# defined above, in the context.aapl variable.  For this example, we're
# specifying a three-day average.
order(context.aapl, 100)

This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.
5 responses

Hello Timothy,

You need to impose constraints in your code to avoid excessive borrowing. Be aware that if you short a stock, the proceeds from the short sale show up in your cash balance as a positive amount. However, since you borrowed money to buy and immediately then sell the stock, the cash from the short sale is not fully available, since there are SEC/broker margin restrictions.

Grant

I agree with Grant 100%.

If you want a simpler method you can set per stock limits. That is the method suggested by the example source code.

  # In these two lines, we set the maximum and minimum we want our algorithm
# to go long or short our security.  You don't have to set limits like this
# when you write an algorithm, but it's good practice.
context.max_notional = 1000000.1
context.min_notional = -1000000.0


The idea is that you would check the amount the stock is long (or short) against those limits and stop buying (shorting) once they are reached.

The problem with this "simple" approach is that you may still end up borrowing a large amount of cash if you are trading multiple stocks.

  # check cash position of stock
shares = context.portfolio.positions[context.aapl].amount
dollars = shares * context.portfolio.positions[context.aapl].cost_basis
if dollars < context.max_notional and dollars > context.min_notional:
order(context.aapl, 100)


It is possible to extend this idea to multiple stocks. In this case I will make three changes:

1) instead of a fixed dollar limit, use cash limit specified in backtest

2) cycle over all stocks being traded

3) combine long and short limits into a single absolute (positive) number

  # get starting cash
start_cash = context.portfolio.starting_cash

# cycle over all stocks
abs_dollars = 0.0
for stock in data.keys():
# get absolute (positive) dollars invested in stock
shares = context.portfolio.positions[stock].amount
abs_dollars += abs(shares * context.portfolio.positions[stock].cost_basis)

# check position and price for AAPL
aapl_shares = context.portfolio.positions[context.aapl].amount
aapl_price = data[context.aapl].price

# compare absolute (positive) dollars invested against cash limit and stock price
if abs_dollars < start_cash - aapl_price*100:
# make new investment
order(context.aapl, 100)
else:
# [optional] sell off part of position
if aapl_shares > 100:
order(context.aapl, -100)


Thank you everyone for your answers. You have provided tons of information. Now only if we were aloud to go 200% below in the real market. 5000% returns doesn't sound too bad.

Hi All - Please see my most recent thread on limiting the leverage within a portfolio - https://www.quantopian.com/posts/template-limiting-leverage-by-brandon-ogle-and-dan-sandberg

This should solve the problems the OP is having.