Back to Community
Large Intraday Swing Produces Overnight Return

I am having trouble with my cointegration test timing out in this algo (lines 171 and 203). It is seeming to have promising results. If anyone would like to take a stab at optimizing it to see if they can get a full backtest to run (greater than 5 years), that would be great!

The hypothesis behind the algo is: equities that experience a large intraday price swing will correct overnight. In order to further confirm that the price swing will revert, I run a cointegration test against all securities in the given security's sector and make sure it is a few standard deviation events outside the mean.

Please share your thoughts and feedback!

Clone Algorithm
13
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: 5961028dd8b4e951e5f6d858
There was a runtime error.
9 responses

I'm still wrapping my head around this.

So basically the premise is if a stock had large (10%+) intraday movement yesterday and hasn't yet reverted back in line with the rest of its sector by the next market close, place a bet that it will revert during the following night (night #2)?

It doesn't look find_cointegrated_pairs() finds stocks cointegrated specifically with the 10%+ intraday movement stocks. Instead, it looks like when you run find_cointegrated_pairs(sector_df) it simply creates a list of all the cointegrated pairs in those stocks' sectors. It doesn't seem like this would even necessarily contain pairs cointegrated with the stock in question. If this is indeed what you intend, it doesn't seem like you need to run this function redundantly for each stock -- it's enough to run it once for each sector.

Hey Viridian Hawk,
Yeah that's the gist of it. If stock AAA has a large intraday movement (10%+) and cointegrated stocks within stock AAA's sector DO NOT share a similar large intraday movement, place a bet that stock AAA will revert overnight.

You are correct that find_cointegrated_pairs() creates a list of all the cointegrated pairs in a stock's sector, I do this to average the return of all the cointegrated stocks in order to see if the large intraday movement is likely to revert or not.

Turns out 2 standard deviations from the average of a stock's cointegrated pairs is never greater than the intraday swing. So the cointegration test was pointless...

Attached is the backtest without the cointegration check.

Future tests might include adding a sentiment check using the PsychSignal library. The literature suggests that stocks with a large intraday swing without a corresponding news release revert more consistently than stocks with large intraday swings with corresponding news releases.

Clone Algorithm
5
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: 597cd9e0442b4953621277eb
There was a runtime error.

Ouch, that drawdown!

What about finding stocks that specifically cointergrated with the "big move" stock prior to the big move and use those as a gauge?

Here is a highly refactored version that uses psychsignal. As mentioned above, the literature suggests that stocks with a large intraday swing without a corresponding news release revert more consistently than stocks with large intraday swings with corresponding news releases.

Clone Algorithm
9
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: 5a218ea4872e3f4137761f3b
There was a runtime error.

Nice. Thanks for sharing.

I feel like psych signal is so new, it's inherently going to be overfit at least somewhat. So it'll be fun to keep track of this and see what happens out-of-sample.

Did you isolate the long and short elements of the algo to see which side performs better/more consistently? I ask because I think the psychology of pops and dips isn't symmetrical. I would guess that since Sept though "buy the dip" has been mantra on stocktwits and the like, pops perhaps haven't been reverting so much.

Thanks for the input!

Long only:
- Total Returns: -46.9%
- Benchmark Returns: 137.16%
- Alpha: -0.05
- Beta: 0.29
- Sharpe: -0.01
- Sortino: -0.01
- Volatility: 0.38
- Max Drawdown: -67.22%
Short only:
- Total Returns: 212.54%
- Benchmark Returns: 137.16%
- Alpha: 0.25
- Beta: -0.15
- Sharpe: 0.84
- Sortino: 1.18
- Volatility: 0.27
- Max Drawdown: -31.27%

Here is a backtest where I allocate 80% of portfolio to the shorts and 20% to the longs. Definitely speaks to your thought that pops and dips aren't symmetric.

I think I will add a sector comparison back into this strategy and see what happens.

Clone Algorithm
9
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: 5a21c4f38b14c8400cb3bebb
There was a runtime error.

Interesting! So it seems your premise is incorrect for the longs. You might try to set an entirely different criteria for the longs than you do for the shorts?

I tried running your algo with a higher starting capital, $100k. Totally ruins the performance. Do you have any ideas on how to scale it?