Back to Community
Buy at month end and sell at month begin

Hi all,

I implemented a strategy based on paper "Month-End Liquidity Needs and the Predictability of Stock Returns". It simply long SPY 6 days before the end of the month and hold the position until 2 days after month begin. Despite the simplicity of this strategy, it can actually achieve a 200% return from 2002 to now :)

Abstract of the paper:

Abstract:

This paper uncovers strong return reversals in stock returns around the last monthly settlement day, T-3, which guarantees liquidity for month-end cash distributions. We show that these return reversals are stronger in countries where the mutual fund ownership is large, and that in the US the return reversals have become stronger over time as the mutual fund ownership of stocks has increased. Finally, in the cross-section of stocks, the reversals around turn of the month are stronger for stocks more commonly held by mutual funds, for liquid stocks, and for more volatile stocks (controlling for liquidity).

Please feel free to play with the strategy :)

Clone Algorithm
187
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: 55faf0f91e62610e0e400448
There was a runtime error.
17 responses

Looks like we can further boost the performance of the strategy if we invest our money into risk free asset in the rest of the time. I use "TLT - 20+ Year Treasury Bond ETF" here.

Clone Algorithm
187
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: 55faf87bb58add0e13a46ea6
There was a runtime error.

Try to further fool around with the parameters.

Clone Algorithm
187
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: 55fba24f942d370e148c7451
There was a runtime error.

Incidentally sent the post without finishing it ...

Try to further fool around with the parameters, slightly adjust the date and now the strategy try to enter/exit the position in multiple days. The total return further went up to 3.45.

I guess we can add some risk control logic to further boost the performance. Maybe we could use something like history volatility/GARCH/bayesian approach.

This version trade large cap stocks instead of SPY

Clone Algorithm
83
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: 55fc1ffcc8a2750e15d945c2
There was a runtime error.

A enhanced version that try to identify the mean revert process on the stocks.

Clone Algorithm
83
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: 55fc4f8d2aba010e03f22ddc
There was a runtime error.

Added a naive risk control that assumes the stock prices will revert to its value T-8. The next step is to add some bayesian inference things. This strategy looks like to be a very good example for me to learn all these things.

Clone Algorithm
83
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: 55fcdbb18765a50e0826a8e6
There was a runtime error.

It's important to remember when backtesting to use minute mode to nail down your algorithms. This is an artifact of how the backtester operates. When considering algorithms like this, ones that are event driven or where timing is extremely crutial, you must be extremely diligent in making sure that orders are executed and filled when they need to be. I'm a big fan of these kind of strategies as you are only exposed to risk for the short amount of time around the event! Keep working on the implementation and see what you can get. Attached is a minute mode backtest from one of the above implementations...

Clone Algorithm
6
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: 55fcdc428174550dfc655f89
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.

@James

Right, i expect the return will drop when I switch to minute mode, so I am trying to get a higher over all return first. But the drop here is still much more larger than I expect ...

Here is a proof-of-concept version that work on minute data with SPY (without risk-free asset). The approach is inspired by paper "market making and mean reversion", but we are doing "directional" market making here.

Clone Algorithm
187
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: 55fe3475e557dc0e06b75e8f
There was a runtime error.

I think I figure out what went wrong in the minute mode. In daily mode the order is filled at the next day's close price. Hence in minute mode we need to schedule the enter/exit function 1 day later to replicate the result. And we need to schedule the function close the the market close.

And I figured out the the turn over of the stocks is a very good indicator for this strategy for the enter timing, perhaps also good for exit timing as well

Here is the working version at minute mode. After fixed the timing, we still need to fix the slippage issue - we should avoid hit the market with a large order in a short time, which may generate a significant price impact and cause the drop of returns.

Clone Algorithm
23
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: 56002c508aebeb0df58a5ae6
There was a runtime error.

This is what we can get if we set slippage to 0 (slippage.FixedSlippage(spread=0.00)). This suggests that we can optimize the ordering strategy to get better result.

Clone Algorithm
23
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: 5600b6b1792faa0e051edf1e
There was a runtime error.

It is worth noting that all of the implementations above are missing a key point from the paper - that this behavior is exhibited most clearly amongst stocks that are most commonly held by mutual funds and are showing the highest volatility prior to the month end draw down period.

However, I assume that automating these components within Quantopian would be very difficult?

Thanks for Richard for pointing out.

Do you have any idea where to get the list of popular stocks held by the mutual funds? Currently I only make a naive assumption that the larger market cap, the more stocks are held by mutual funds.

Perhaps we can also use some popular fundamental data metrics to reverse-engineering the list popular stocks?

Nice work iterating on this algorithm. I took your latest version and ran it through the tearsheet to analyze the meta-data about the algo. The tearsheet shows data about your position concentration, risk analysis, drawdown details and more. Here are some of the things that caught my eye:

  • Consider using record() to track the number of candidates your algo is trading. At one point it looks like all the holdings were in IEP, with 99.8% of the portfolio allocated. Maybe this intended? Either way, it's good to keep track!
  • The beta is slightly too high for the hedge fund. We are looking for strategies with a rolling beta-to-spy between 0.3 and -0.3. If you're still working on this strategy, keep this in the back of your mind.
  • Along the same lines, it has a high correlation to the small cap and high growth stocks in the Fama French factors. Generally, when you reduce the beta, you'll reduce your exposure to these factors.
  • Most of the time your algorithm had mild drawdowns - great! Note that in 2008 it had ~30% drawdown. Though most strategies suffered during this market.
  • It looks like your algo trades frequently and fluctuates between sitting in cash and holding positions. (And this is confirmed by your source code above). You can see the behavior in the Gross Leverage and Long/Short/Cash plots. It's good to be aware of this algo behavior. Perhaps you want to consider adding a hedge and shorting another basket of securities to lower the beta?

Take these details into account as you're working on the next iteration. If you want to learn more about how to analyze your algorithm's behavior and how to use the tearsheet, join this webinar on Thursday at 12PM EST: https://attendee.gotowebinar.com/register/3903306230308545025

Jess Stauth is our VP of Quant Strategy and she'll explain how to evalaute strategies.

Loading notebook preview...
Notebook previews are currently unavailable.
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 @Alisa for the comments and the hints.

For the IEP case, it is unexpected and may be a bug in the code or it is delisted before I can sell it at the month begin.

The beta is high because this is a long-only strategy. One way to workaround this (not fixing this) is to hold TLT during the month, which will reduce the beta significantly. But this still dosent change the fact that it is still a long-only strategy. I tried to build a long-short strategy but failed because my factor model dosent make sense currently :)

The correlation to small cap is unexpected because the month-turn effect is supposed to more significant to large cap stocks. This may suggest that I am picking the wrong stocks! The correlation to high growth stocks is expected because I think people tend to buy high growth stocks during the mean-revert process? I need to think about this.

For the 30% drawdown, actually I found an heuristics that based on average turn-over before T-8 and after T-8. That's only long the stock at then month end when its pre-T-8 turn-over is lower than its post-T-8 turn-over - this seems to eliminate the drawdown. I need to further think about the reason behind this also.

For the last point, such a behavior is intended. In fact, we can combine another intra-day strategy to this strategy to generate higher return and hopefully lower beta!

Essentially, it is the lack of liquidity that cause such a mean revert process around the month end. Perhaps paper "Liquidity and Market Crashes"[1] may provide useful insight for this strategy.

[1]http://web.mit.edu/wangj/www/pap/HW_070228.pdf