Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Serious questions: why are so many of the algos here returning +1000% over a few years?

Relatively new here, see a lot of algos posted that have absolutely insane returns. If we're actually generating alpha shouldnt it only be a percent or two? Maybe a dozen or so if you have a nice system? I just find it curious that some of these algos have quadruple digit returns.

11 responses

Hey Zachary,

Quantopian computes returns cumulatively from the beginning of the backtest. As the algorithm buys and sells during the course of the backtest, the returns will be computed from the initial value of the portfolio, not the updated value. It can be difficult to know when to start computing cumulative returns. The backtest engine is more suited to a self-financed portfolio - that is, one in which the cost of changing the composition of the portfolio can be covered using earnings and cash from the portfolio until that time.

Take a look at the sample algorithm below. The returns get very high as the algo buys more Apple.

def initialize(context):  
    pass  
def handle_data(context, data):  
    order(sid(24), 50)  

Best,
Ryan

Hello Zachary,

Very few algos here manage cash so they take impossibly large long/short positions. Even fewer algos have any concept of leverage, margin calls etc. Short algos rarely if ever account for the cost of borrowing the stock, and Quantopian doesn't deduct withholding tax (I'm not a US resident) on dividends as far as I am aware. I don't actually know how Quantopian treats short positions that go ex-dividend.

P.

When I was building an algo I think I was running into this cash management issue. I had set my original portfolio at 100K but I noticed I was placing orders when I didn't have the cash; I assume that the engine was automatically throwing me into margin. I also noticed that my open short positions added cash to my portfolio (as they should) but when I checked if my portfolio had available cash it said yes and I would end up using the cash received from my short. Which all ultimately led to me having to build my own portfolio management function that kept track of all my trades so that I wouldn't use short cash and would stay within the confines of my original portfolio value.

Take a look at these posts that David shared to manage the margin requirement:
https://www.quantopian.com/posts/margin-requirements
https://www.quantopian.com/posts/class-for-tracking-margins

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.

If people made a greater use of order_target_percent, most of these problems would go away. It's much easier to control what you are doing, especially with a large portfolio. I think because this is a newer function, a lot of people don't know about it. To me, this should be what people start with, and then move to other methods after they have more experience. I don't use anything else.

It seems there are issues within the logic that you can use to limit executions based on portfolio values. I've been experimenting with trying to limit trades based on existing positions and cash value left in accounts, and it doesn't appear to work correctly (or work as I would expect it to) for instance testing code which simply looked at RSI and if a position existed - I had multiple times where the portfolio quantities where much larger then one order size - so it appeared that multiple orders were executed - totally ignoring the rule where if a position in the stock is > 0 don't execute buy.

Also this is nit-picky but the program and system is using incorrect terminology. AMOUNT should refer to $$$ figures. QUANTITY should refer to # of shares. AMOUNT = QTY * PRICE

Hi Brandon,

I'm not sure I completely get the issue - might need to see some of the logic to debug. One thing to check just in case is if you have partial fills due to trading low volume stocks. By default (and by default I mean even if you code does not reference slippage at all) the backtester applies a volume share slippage model that prohibits trades of greater than 25% of the current bar's traded volume. To check this you can turn off slippage by setting the following inside of the initialize() method like this:

set_slippage(slippage.FixedSlippage(spread=0.00))  

If you are still seeing unexpected behavior with the slippage model off let me know and I can take another look.
Best wishes, Jess

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.

My issue isn't around the algo - it's immaterial, but rather the safeguards you can build around it to make sure that a trade doesn't exceed cash on hand etc etc. In my example I'm trying to limit a trade to cash on hand. I'm not concerned about spreading it out right now over multiple securities, but really just interested in why it doesn't seem to be. For instance I am trying to limit the trade to cash in portfolio. On one day it actually bought 4x my cash. It's unclear why - I would assume that my portfolio cash is updated as the code cycles through the array context.stocks. i.e.
for stock in context.stocks:
cash = context.portfolio.cash

each time a trade is made it doesn't appear cash is adjusted in the context.portfolio.cash variable

2008-02-19 19:00:00 GLD BUY 1091 $93.25 $101,730.29
2008-02-19 19:00:00 PSQ BUY 1593 $62.09 $98,901.40
2008-02-19 19:00:00 DOG BUY 1569 $63.23 $99,200.03
2008-02-19 19:00:00 RWMBUY 1275 $77.41 $98,691.38

I was essentially having the same issue -- where I would fill orders when I didn't have cash. This ultimately led to my algo returning insane amounts and unless I was printing logs of what I was buying, how much I was buying, and how much cash I had then there would have been no way for me to realize that I had made such large transactions. As a work around I had to build a data structure to store my trades and a conditional statement to check to see if I had enough cash in my portfolio. Which is fine, I guess, since it takes like 3 lines of code.

Ahh so allowing infinite leverage is a feature not a bug? =) I agree the "cash" doesn't seem to work correctly and there should be some portfolio functionality which is parameter driven where you could set things like leverage/margin/cash etc. Although I love the results it creates unusable tests and doesn't seem to work as you would expect. I'm sure there's work arounds - but the point would be it's got some issues which need to be addressed.

Hi Brandon,

We definitely have implementing a realistic margin model on our work queue. In the meantime you do need to do some defensive coding to prevent your algo from over ordering. This is especially true in a case like your shared algo where you are running in Daily backtest mode but looping over a number of stocks. The cash management logic you put in place was assuming that orders were being filled and taken out of the available cash pool as they were being placed -- however the backtester actually fills order on the NEXT bar of the simulation. So you were queuing orders up and just re-checking the static starting cash value from the beginning of the day.

One way to handle that is to add a convenience method that will keep track of how much cash you've allocated out to pending open orders so far. So for example you could do:

pending_order_value = open_order_value(context,data)  
##The available cash for placing new orders is the cash on hand MINUS the open orders already placed but not filled.  
cash = context.portfolio.cash - pending_order_value  

Where the pending_order_value is computed as follows:

def open_order_value(context,data):  
    #Return the $ pending in open orders  
    pending_order_value = 0  
    for stock in context.stocks:  
        orders = get_open_orders(stock)  
        if orders:  
            for oo in orders:  
                shares = oo.amount  
                price  = data[stock].price  
                value = shares * price  
                pending_order_value = pending_order_value + value  
    return pending_order_value  

Let me know if this is helpful and if you come across other comments or feedback!

Best regards,
Jess