Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Limiting Purchases To Portfolio Size

I was trying to build an algorithm that would trade any of a select number of stocks when their price moved above the 12 day moving average and sell them when they went below.

Given that there are about 25 stocks to trade, and it tries to buy $7000 worth of stock when it trades, the algorithm shouldn't be able to simultaneously own more than 7 stocks until the portfolio value has increased to over $56,000...

I tried to follow the example in the help document - https://www.quantopian.com/help#sample-multiple - however my algorithm seems to purchase much more stock than the limited $50,000 portfolio size I was trying to use.

Any help would be appreciated.

6 responses

Hello Chris,

I've attached a backtest that is a kind of re-work of yours. One thing to watch out for is open orders. Also, if you use order_target_percent, you can order by weight.

if not get_open_orders():  
        for stock in context.stocks:  
            order_target_percent(stock,context.weight[stock])  

Grant

Thank you Grant for your modifications.

This algo seems to limit the positions to the $50000 portfolio, which is great.

However I noticed that it seems to re-balance everyday and often buy or sells only a couple of stocks in each of the securities to make sure that portfolio is fully invested.

This might work for this algorithm because the transaction costs are on a per share basis, but with a live algo their are $1 minimums with IB per trade, so rebalancing everyday wouldn't be realistic for me and my $50,000.

Does anyone know of a way to set this algo to purchase fixed amounts of stock instead?

I understand that this may mean that their could be 20 stocks above the mavg, but only enough in the portfolio to buy 10 or so and that at times their will be cash on hand if there are not enough stocks above their mavg to be fully invested.

Chris,

One way I played around with awhile back is to treat the portfolio allocation weights as a vector. Then you can compare the angle between the current allocation vector and the new one. If the angle is too small, then just maintain the current allocation.

Here's an example of how to calculate the angle in Python:

http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python

Grant

Chris,

I think this does what you want (i.e. avoids negative cash)? Much more testing is needed against a variety of scenarios. I also suggest you play around with some other signals like a combination of MACD, RSI, and ADR. If I get some more time I'll update this with examples.

Best,
Tom

The backtests no longer work, they just say "Something went wrong".

It seems your notional variable is not managed correctly. Be careful both how you initialize it, how you update it (+= or -=?), and how you use it in conditions. Also, I don't think you should limit your portfolio to a fixed amount - you want it to grow, don't you?

Instead, you should look at available cash. Quantopian maintains context.portfolio.cash for you, but updates it not at the time you send your order, but as your order is filled, in whole or in part. For this reason, a typical Quantopian approach is to do no trading when there are any outstanding orders.

You should also take commissions into account when calculating the number of shares you can afford. (And slippage, but I'll leave it as an exercise for the reader.)

Thus, if you want to buy stocks in chunks limited to $7000 and the available cash, you could use something like this:

   cpt, cps = 0.0, 0.03 # commission in USD per trade, per share  
   if not get_open_orders():  
      for stock in context.stocks:  
         current_price = data[stock].price  
         if ...: # buying stock  
            number_of_shares = int((min(7000, context.portfolio.cash)-cpt)/(current_price+cps))  
            if number_of_shares > 0:  
               order(stock, number_of_shares)  
               log.info("Buying {}*{}@${}=${}, commission ${}".format(number_of_shares, stock.symbol,  
                  current_price, number_of_shares*current_price,  
                  cpt+number_of_shares*cps))  
               return # order nothing more this time, wait until this order is filled in full