Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
What's wrong with my algo? Up 1600%+ over 14 years

I'm fairly new to swing trading and especially Quantopian. Since I'm a simple guy, I wrote and tested a simple algorithm that does the following:

-Every Tuesday morning before market open, scan for the 4 stocks that rose the most over the past five trading days. The stocks are selected from a custom universe that includes those:
- with avg. daily vol > 20000 over the past one year
- outstanding shares > 1000000
- market cap > 6000000
- average close price over the past five trading days > 1.10 and < 10.00
- not LP, OTC, WI, and is a common stock

-Tuesday at market open, I short $10000 worth of each of the four stocks.
-Thursday at market close, I cover all positions.

-I have a single stop in place such that if the Tuesday or Wednesday closing price > 2x cost basis, the position is closed the following morning.

The backtest results show a gain of +1606% from 1/1/2003 to 12/31/2016. Since I consistently short $10k/stock in this algorithm regardless of portfolio value, a smaller and smaller percentage of the total portfolio is invested as time moves forward. Instead of re-investing and compounding the gains (which would probably not work with this strategy as the stocks are not the most liquid), I would withdraw $40k from the portfolio each year. Unless I'm missing something, which I admit I most likely am, this strategy shows that I could start with $40k and have a steady stream of $40k in income per year over the 14 year test period.

It seems too good to be true. What am I missing? For the purposes of this backtest, I turned off slippage and set the commission to $4.95/trade (my E*Trade cost). I think I would get fill prices better than are calculated via Quantopian's slippage algorithm since I'm only making four round-trip trades per week, at market open and close when trading is generally most active. That said, even when I turn slippage on, the backtest results still show a gain of about 1280%. I also thought that since Quantopian does not trade exactly at market open or close that I should compare the filled prices within the backtest to actual open and close prices. The results show that I would actually do better than the backtest reveals by trading exactly at market open/close, not within a few minutes of open/close as Quantopian does. These results are shown in the backtest log along with the code.

I tweaked numerous variables and the weekly trading range, and those shown in this backtest yielded the best result of those I tested. I know these are not the most liquid stocks, but I think that by making few transactions at market open/close it should not be a huge problem. I also understand this algorithm is not scalable for that reason, but that is not my intent. That said, interestingly enough, if I turn slippage on and re-invest my gains instead of consistently trading $10k/stock, the algorithm shows a gain in the tens of thousands of percent by the end of the backtest period!

The backtest statistics look good to me, although they are skewed in the sense that only around $40k is invested at given time. That said the gain is fairly steady over time, with fairly minimum volatility and every 12-month period over the 14-year backtest shows a profit (through both bear and bullish market conditions).

I know that stocks may sometimes not be available to short, and that HTB fees will reduce the gains slightly. I do not estimate these as significantly reducing profit. Finally, note that I am only using Quantopian for its backtest feature and to determine which stocks to trade each week. I would still make all trades manually.

Anyway, what do you all think? Am I on to something here or is too good to be true? Do you have any suggestions to improve the algorithm?

Thank you!

18 responses

Attached is a backtest I conducted of your algorithm over the last 8 months of market data, from the end of December to the beginning of August. The results are lacking in the beta and drawdown statistics category. Personally, undergoing a 25% drawdown on $40,000 is not something I would want to experience myself. In addition, a -1.46 beta-to-SPY is very high, considering that the historical estimate was -0.09 in your backtest. It does have a decent Sharpe Ratio statistic, though the way that that statistic is estimated is not particularly significant without ~2 years of Out Of Sample.

Quant strategies have not performed exceptionally well this YTD, but beta and drawdown are things that can be controlled in nearly all market conditions. I would suggest controlling the net exposure of the algorithm by including shorts as well. I would deploy all liquidity of the time, instead of walking in and out of the markets periodically; institutional investors don't like for the money to sit in cash and pay fees on it.

The above suggestions are if you are looking for institutional investment consideration. For your own money, you may do as you please of course! :)

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.

That is an interesting algo, thanks for sharing.

I think you're underestimating the impact of shorting fees, and overestimating the availability of these stocks for shorting. They're definitely things that the backtester needs to have in the long run - it's too easy to skip over them. But since you're trading in mostly small cap stocks, you'd have a lot of borrowing issues.

I fiddled around with your algo a little, and forced it to trade only largecap stocks. The effect totally disappears.

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.

Thanks for the responses! My objective with this algorithm is to use it as a personal trading strategy, I agree this is not suited for institutional investing for the reasons cited above.

Historical short stock availability and HTB rates are indeed hard if not impossible to estimate. I would only consider using E*Trade or IB with this strategy due to their ample short stock availability. From my experience, E*Trade almost always has the small-cap stocks I am interested in trading available to short. I do see them run out sometimes during the day, but that should not regularly be an issue with this algorithm as the trades are placed at market open. E*Trade only allows stocks over $1 to be shorted; for this reason, I set the 5-day average close price filter in the algorithm to be > $1.10. I tried to minimize the HTB fees by only holding positions for 3 of 7 days during each week. I've seen HTB rates range from 0.25% to 300%, and they change every day, so it's impossible to estimate. I checked a few stocks that the algorithm returned recently and they either have no or low (<10%) HTB fees.

For argument sake, let's assume the HTB rate is always 25% for all stocks (which I think is more than generous). $40k * (3/7) * 0.25 = $4286/year. That's certainly a significant amount of money, but given the algorithm historically provides a return of about $46k per year, the total HTB fees represent less than 10% of the profit which still makes this a winning strategy for me.

Ok I just realized something that perhaps I should have realized earlier.... when I run the algorithm now, it doesn't output what stocks I am supposed to trade at open since the function that does so is in "before_trading_start". Is there a way around this? This won't work if I can't know what stocks to short Tuesday morning until Wednesday....

@Michael D -- Not sure I understand the problem. Pipeline output is generated every day before trading, including Tuesday mornings. I guess your problem is that you won't be able to manually place your orders at your broker at market open because the paper trade is 15-minutes delayed?

Otherwise, I feel like I need to point out that shorting penny stocks is a really dangerous game. Especially if your risk is spread across only four stocks. What happens if overnight just one of your stocks gets an FDA approval or has a freakishly good earnings report or something along those lines? Just one of those stocks shoots up 4x and you're wiped out.

The reason why that doesn't happen in the backtest is simply luck or overfitting. For example, if you remove c8 (price range filter) the algorithm performs overall better except when it hits one of these catastrophes. The price range used in c8 is totally arbitrary, and there's no logical reason why a security that falls within it wouldn't exhibit the same behavior as one that falls outside of it. That's an overfit. Also, what's the significance of Tuesdays? I haven't checked, but if the algo suffers when offset to other days of the week then I'd say that suggests overfitting as well.

Why do you short with a fixed dollar value? You don't compound your gains, but you do risk compounding your losses and exceeding leverage limits if you drop below the initial capital.

Sorry to be a party pooper, but I think it's important to be skeptical. If you're considering actually trading a strategy like this, I highly encourage you to work on spreading out your risk quite a bit first!

Some ideas:
- Does the inverse work? Can you make a long side of the strategy?
- Set stop-loss orders to avoid catastrophic intraday losses. Is there some way to make this profitable while only being short during the day? Overnight losses are so dangerous.
- What about increasing the number of shorts in order to spread out the risk a bit more? What about increasing based on the level of your portfolio value? So once you've made 100% returns you'll have double the amount of shorts?
- Make the algorithm rolling for each day of the week instead of just based around Tuesdays. This would spread the risk by increasing the number of short positions you hold and also by diversifying across days of the week.

And then there's Dan's point... I wouldn't discount if even for private investing. You're trying to short $10,000 worth of a "penny stock" that might have as little as 20,000 average daily volume, so in practice on any given day volume might be significantly lower... Even if you can borrow enough for the short and the fees don't wipe out your gains, covering the short is going to be really hard -- you feasibly could need to exceed the entire daily volume. So actual slippage is likely to be way worse than the modeled slippage. Also, the bid-ask spreads on low volume stocks can be huge. Try running the backtest with a fixed slippage spread that might be typical of these stocks.

Major issue is that most of the stocks that are picked to short - are not shortable.

2 of the 4 stocks picked today are not on the shortable list @ IB.

Quantopian is probably not the best platform for doing what you're trying to do, but have you tried log.info("Selected stocks "+ stock1.symbol +" "+stock2.symbol)etc. from within before_trading()? Then if you go to the paper-trade and view the log hopefully it'll show up at 8:45am. Not sure if that'll work, but hopefully!

But how do you get around the non shortable stocks? Seems like the backtest doesn't mean anything if you can't trade what it has picked.

Thanks for the critique - a lot to think about and respond to, but for the moment just a few comments/questions:

This morning's picks are FSNN, XOMA, XCO, and DMTX. The HTB rates at E*Trade are 3%, 7.5%, 99%, and 1% respectively. The rise in DMTX was due to an acquisition, its price is now static so I did not trade that one. FSNN and XOMA are both available to short at E*Trade as I write. There are no more shares of XCO available to short, but I had no problem shorting this morning at market open when shares were available. I picked-up 5000 shares at $1.98.

I wasn't able to see this list of stocks until 8:45am when before_market_open output the list to the log. This gives me 45 minutes to enter the trades with E*Trade for execution at market open. This isn't going to work for me long-term; I have a day job and need to get to work.... thus I need to know these stocks earlier in the day (around 6am) or the night before. How can I do this? This is why in my earlier post around 7am I said I could not see the list of stocks...

So does E*Trade have better shorting opportunities than IB?

Because IB doesn't have FSNN or XOMA available.

I can't speak to IB as I've never had an account with them. I am happy with the short stock availability at E*Trade. Sometimes shares become unavailable to short throughout the day, but almost always they are available in the morning around market open. Note that E*Trade only allows shares priced over $1 to be shorted (thus the >$1.10 filter in my algo), and a limit order must be used for all HTB stocks. I'm not sure how their HTB rates compare to other firms. E*Trade does charge 1 days' interest if you sell/cover in the same day; I heard some firms do not charge for intraday trading but I never pursued this.

You're probably best off recreating this script on your own server or installing python locally on your machine. E*trade has an API, so you can make it totally automated. You can get EOD prices from Quandl for free. I'd use that as a coarse filter to find >$1 stocks with the highest 6-day returns, then go through those and query E*trade's API until you find enough that match your fundamental criteria. There are all sorts of advantages to doing this. The E*Trade API might give your algorithm access to a bunch of useful information (such as perhaps short availability) that Quantopian doesn't give you.

I was playing around with the filters and stock universe in my code when I noticed a discrepancy that I can't explain. After building my filter (line 123), I used the make_us_equity_universe function to build the stock universe (line 125) because I thought that's what I had to do. I set the variables in make_us_equity_universe so that it would scan every possible stock and exclude only those defined by the mask. I set the mask=universe on line 133 when determining which stocks to trade. Later I realized that I shouldn't need to create the universe at all, instead, just set mask=my_filter directly on line 133 instead. I was expecting the same results but instead the algorithm is selecting slightly different stocks. For example, this past Tuesday with the "universe" mask was used one of the stocks is XOMA, but with the "my_filter" mask, it is RTNB. The other three stocks selected were the same for both algorithms. Why is there a difference? Both runs are attached for reference. There is a significant difference; XOMA was up ~50% of the five-day back window while RTNB was up ~100%.

Backtest with mask=my_filter

Backtest with mask=universe

original algo was down 17% this week. Weird it is making different picks.

Michael, I think the difference is coming from the groupby argument. If a stock doesn't have a known sector code, it will be omitted from the universe, since make_us_equity_universe won't know how to group it.

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.

Thanks, I thought that might be the case but saw those without a sector were grouped into a "-1" category which should technically be a group of it's own. Anyway, what would the code be to group by something else such that no stocks are omitted from the universe? Thanks again!

Hi @Michael,

The make_us_equity_universe method applies additional filtering based on the groupby and max_group_weight parameters. Securities are first ranked and sorted by AverageDollarVolume. Then, starting from the highest ranked security, they are added to the output universe as long as the max_group_weight has not been reached for their corresponding label (groupby categories). This is why computing the Returns factor using universe as a mask gives you a different set of securities.

If you want all securities that pass your custom filters to be considered when computing the Returns factor, you should use my_filter as a mask instead.

I hope 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.