Back to Community
Quantpedia Trading Strategy Series: Reversals during Earnings Announcements

In their whitepaper, "News-Driven Return Reversals," Eric C. So of MIT and Sean Wang of UNC show that abnormal short-term returns reversals take place during the period immediately surrounding earnings announcements. They surmise that this reversal results from market makers' response to a temporary demand imbalance, as they temporarily shift the stock's price to ride out the imbalance.

Our friends at Quantpedia summarize the reasons behind this phenomenon in the following abstract:

In general, reversal in price of an asset occurs due to investors' overreaction to asset-related news and the subsequent price correction. In this case, the most probable reason for the phenomenon, according to the authors, is the market makers' aversion to inventory risks that tend to increase dramatically in the pre-announcement period. Consequently, the market makers demand higher compensation for providing liquidity due to higher risk and therefore raise prices, which are expected to reverse after the earnings announcement.

The authors reached their conclusion based on data from 1996 to 2011; I endeavored to replicate their results using our pricing data and EventVestor's Earnings Calendar dataset, which spans from 2007 to the present day. In my analysis I was able to confirm the reversal that the authors observed. I also studied the reversal's robustness, and determined parameters and stock universes that improve the returns of the strategy that So and Wang proposed.

OOS Study Results

As the paper does, I find evidence of returns reversal during earnings announcements; while the paper tested using data from 1996 to 2011, I used data from 2007 to 2016. The average reversal among all stocks in my data is 0.449%, compared to a result of 1.448% in the paper. I found that we can reasonably increase the reversal to 0.6% by selecting firms based on a minimum average dollar volume percentile, or based on a minimum market cap.

Trading Strategy Details

In order to ensure liquidity, the strategy limits its universe to those stocks in the Q500US which are at or above the 95th percentile of average dollar volume among all equities on the platform. One day before each earnings announcement for each company, the algorithm determines the stock's 5-day returns quintile among all equities. Since reversal is expected, the algorithm goes short on the stock if it's in the highest quintile and long if it's in the lowest quintile. Positions are usually held for one day.

N.B.: As a result of parameter optimization, this strategy may be overfit.

Attached is the whitepaper walkthrough and OOS validation of the original study (Hit "Clone Notebook" to see a complete analysis).

FAQ

What is the Quantpedia Trading Strategy Series?

Quantpedia is an online resource for discovering trading strategies and we’ve teamed up with them to bring you interactive and high quality trading strategy examples based off financial research. Our goal is that you’re able to replicate the process we’ve used here for your own research and backtesting.

Where can I find more trading strategy ideas?

You can find the full Quantpedia Series here along with other research. Other than that, you can browse Quantpedia’s strategies or look through our forums for ideas posted by community members. Want to feature your own? Submit your proposal to SLEE @ quantopian.com

I can only run the backtest till 2014, why is that?

This algorithm uses EventVestor's Earnings Calendar dataset to time earnings announcements. It's a premium dataset that's available for $5/month which gives you full access to the data for backtesting, live trading, and contest submissions.

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. 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.

16 responses

Here is a backtest of the strategy. The strategy limits its universe to those stocks in the Q500US which are at or above the 95th percentile of average dollar volume among all equities on the platform. One day before each earnings announcement for each company, the algorithm determines the stock's 5-day returns quintile among all equities. Since reversal is expected, the algorithm goes short on the stock if it's in the highest quintile and long if it's in the lowest quintile. Positions are usually held for one day.

For non-premium subscribers, you're able to run the backtest till August of 2014.

Clone Algorithm
474
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: 57d171e81cf5bc102ae5cc7a
There was a runtime error.

Finally, here's a Pyfolio tearsheet run on the backtest.

Loading notebook preview...
Notebook previews are currently unavailable.

Really enjoyed going through your research process in verification. It was quite thorough and an inspiring look at the quest for real alpha.

I appreciate you sharing this! I'm already trying to think of factors that can be used to improve this strategy - the underwater plot makes it a bit scary to trade.

I liked your exploration of the alpha decay. I was going to clone your research book and start exploring in what dimensions the alpha decays. Do you know of any good papers on alpha decay? I'm quite curious what the decay curve looks like (and if it will have an overshoot and the signal will reverse...)

The underwater plot does show that this strategy needs a bit of refinement. Going off of that, here's a the full backtest run from 2011 ~ 2016 so you can get a glimpse of how it'd performed till present day. The results are consistent with the backtest trends, drawdown is still a bit high.

This uses the premium version of EventVestor's Earnings Calendar datafeed.

Clone Algorithm
166
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: 57daae3fb2df7112e7ece08f
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. 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.

Nathan Wolfe : awesome work, by the way, can you shore return distribution by long/short with us?
I am wondering which direction of over-reaction can generate more gain..

thank you
Kev

When I tried to live trade this one on Q I got the following error and can not start the algo:

IndexError: index -1 is out of bounds for axis 1 with size 0
There was a runtime error on line 45.

Anyone can help? Thanks

Hey Dawei,

Thanks for bringing the issue up. We're aware of the issue and we're working on a bug fix, we'll keep you posted as we find out more.

Matt

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. 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.

Hi Mathew, the issue was detected more than 2 weeks ago and I for one have raised concerns about it before too. Since there are no other trading calendars, do you have any timeline as to when the issue might be resolved? I would like to know whether I should be canceling the buybacks dataset which I pay a premium for. Moreover, should I start thinking about how to import my own earnings calendar through some outside server and CSV hack if the fix will take too long?

Thank you

Hi Peyman,

Thanks for bringing up the issue and we're working as fast as possible to fix the issue. I understand the frustration that comes. We're testing the solution internally and once that process is finished, the issue you're seeing with earnings calendar should be resolved.

I haven't seen the same issue come up for buyback authorizations but I'm happy to troubleshoot with you if you're experiencing problems.

Seong

Seong, Thank you for your quick response. Please don't get me wrong, I was not complaining about the issue that would be silly of me, I just wish the timeline was a little clearer so I could judge whether it is worth spending time on alternative routes in the interim (outside server and whatnot).

The buyback authorization dataset is perfectly fine on its own, but is almost not useful if the earnings calendar is not operational.

Thanks again for your speedy responses.

Thank you for understanding Peyman and totally understand on the buyback authorizations dataset.

I'll reach out to you personally along with making a larger PSA once the issue on earnings is fixed.

Seong

Peyman,

Thanks for your patience. A fix should be in place now so let me know if you see anything else.

To celebrate, here's another Quantpedia Series installment: https://www.quantopian.com/posts/quantpedia-trading-strategy-series-reversals-in-the-pead

We'll be taking a break from earnings after this but stay tuned for more!

Seong

Hi,

I cloned the algo. But as I start the backtesting, I got a lot of erros such as:
... ValueError: Bad response: Computation failed with message: AssertionError: File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/server/server.py", line 643, in compserver **compute_kwargs), File "/home/databazaar/.venv/lib/python3.4/site-packages/multipledispatch/dispatcher.py", line 164, in call return func(*args, **kwargs) File
...

Thomas

I got the same error as Thomas.

ValueError: Bad response: Computation failed with message: AssertionError: File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/server/server.py", line 643, in compserver **compute_kwargs), File "/home/databazaar/.venv/lib/python3.4/site-packages/multipledispatch/dispatcher.py", line 164, in call return func(args, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 412, in compute result = top_then_bottom_then_top_again_etc(expr3, d4, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 189, in top_then_bottom_then_top_again_etc return top_then_bottom_then_top_again_etc(expr3, scope4, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 189, in top_then_bottom_then_top_again_etc return top_then_bottom_then_top_again_etc(expr3, scope4, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 153, in top_then_bottom_then_top_again_etc return compute_down(expr, *leaf_data, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/multipledispatch/dispatcher.py", line 164, in call return func(*args, **kwargs) File "/home/databazaar/.venv/src/databazaar/databazaar/utils/throttler.py", line 95, in compute_throttler return_type='native', File "/home/databazaar/.venv/lib/python3.4/site-packages/multipledispatch/dispatcher.py", line 164, in call return func(args, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 412, in compute result = top_then_bottom_then_top_again_etc(expr3, d4, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 158, in top_then_bottom_then_top_again_etc expr2, scope2 = bottom_up_until_type_break(expr, scope, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 301, in bottom_up_until_type_break for i in inputs]) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 301, in for i in inputs]) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/core.py", line 325, in bottom_up_until_type_break **kwargs)} File "/home/databazaar/.venv/lib/python3.4/site-packages/multipledispatch/dispatcher.py", line 164, in call return func(*args, **kwargs) File "/home/databazaar/.venv/lib/python3.4/site-packages/blaze/compute/sql.py", line 1038, in compute_up assert names == expr._child.fields

Hi all,

This is my first post here so don’t be to hard on me. This looks like a very interesting idea, but, as some people have pointed out, drawdowns are quite large. A possible (and perhaps naive) solution is to keep track of the stock-specific drawdowns intra-day on days during which the position is held (t and t+1) and get out when the drawdown gets too large. Specifically:

  • For long positions: keep track of the peak since the initial investment on t-1 and close the position intra-day if drawdown exceeds 5% (5% is arbitrary of course).
  • For short positions: keep track of the low since the initial investment on t-1 and close the position intra-day if drawdown exceeds 5% (5% is arbitrary of course).

Does anybody has any pointers on how to code this? Being a beginner, I don't have clue where to start (although i've read the tutorials). Any help would be much appreciated!

Hi Everyone,

I cloned the original algorithm and changed it to utilize the recently released Optimize API. Let me know what you think.

The essence of the algorithm's strategy remains the same. The only changes have to do with how we place orders and take positions. In this implementation of the algorithm, order_optimal_portfolio (found in the Optimize API) is used to construct a portfolio given the stocks that we wish to trade and their target weights in the portfolio. Additionally, this allows us to adhere to constraints such as the maximum leverage we can tolerate (as seen in this algorithm) or whether or not we are strictly market neutral. Using order_optimal_portfolio requires that we specify a universe of equities, which must be an iterable object. Idiomatically, this is the index of a Pipeline object, but in this case, because code stores securities we are considering in two different columns (the long and the short columns) we construct the universe by combining these two columns into a list.

-Jeremy

Clone Algorithm
8
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: 58d18fbdefd9ea1b5a854143
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. 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. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.