Back to Community
Statistical Arbitrage based on Divergence (Version 2)

This is a corrected version of the strategy I posted earlier (https://www.quantopian.com/posts/statistical-arbitrage-based-on-divergence).
Also, I have changed the entry and exit rules. The aim is to create a beta neutral position when divergence is observed.

For back-testing, I have used 6 IT stocks from S&P 500 companies, namely

  1. Apple Inc. (AAPL)
  2. Microsoft Corporation (MSFT)
  3. Amazon.com Inc. (AMZN)
  4. Alphabet Inc. Class A (GOOGL)
  5. Accenture (ACN)
  6. Adobe (ADBE)

Following are the steps for the strategy:

Calculations required
Every day, at market open, I calculate the historical volatility of the stocks as well as the benchmark (SPY) based on last one month's data, and calculate beta with respect to the benchmark for every stock.

Every day, 5 minutes before the market closes, I compute the divergence of every stock. Divergence is calculated is the difference between the stock's daily percentage return and the expected return of the stock based on its beta (Expected Return = (Benchmark Return*Stock Beta)).

Entry Rules
Once I have the divergence for every stock, I find the stock with maximum divergence values. Then I find the stock with minimum positive divergence. In case all the other stocks have a negative divergence, I select the stock with maximum negative divergence.
Then, I short the stock with maximum divergence if the divergence value is more than 1% and long the stock with minimum positive (or maximum negative) divergence value.

Exit and Stop Loss Rule
I square off my positions when the divergence of the stock with maximum divergence (at the time of entry) becomes less than or equal to 1/4th of divergence at the time of entry or when the the divergence of the stock with maximum divergence (at the time of entry) becomes more than or equal to 1.5 times the divergence at the time of entry.

Clone Algorithm
12
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: 5a242ab0f5dc6040ff66c7ae
There was a runtime error.
4 responses

Max Lvrg: 7.82 2008-01-03
Max Lvrg: 11.90 2008-01-16
Usually due to partial fills. For example, tracking GOOG_L ...

2008-01-02 06:31 ti:261 INFO 2008-01-02 to 2017-11-30  $100000  2017-12-03 10:23 US/Pacific  
2008-01-02 12:50 _t:433 INFO  380  Buy          1000 GOOG_L 681.66      _            0  0.00  6da5   100000  
2008-01-02 12:51 _t:433 INFO  381    Bot     379|0|1000 GOOG_L 682.06     379         -17  3.19  6da5   -98088  
2008-01-02 12:52 _t:433 INFO  382    Bot     503|379|1000 GOOG_L 683.00     882         318  6.61  6da5  -441659  
2008-01-02 12:53 _t:433 INFO  383    Bot     all 118|882|1000 GOOG_L 683.57    1000         820  7.39  6da5  -522320  
2008-01-03 12:50 _t:433 INFO  380  Sell                 -1000 GOOG_L 682.54    1000        -210  7.41  5788  -522320  
2008-01-03 12:51 _t:433 INFO  381    Sold        -628|0|-1000 GOOG_L 682.58     372         -64  2.54  5788  -153835  
2008-01-03 12:52 _t:433 INFO  382    Sold    all -372|-628|-1000 GOOG_L 683.20      _        [+98]  0.00  5788   100306  
2008-01-08 13:00 _ti:967 INFO  5 trading days     0 hr 0.0 min   2017-12-03 10:23 US/Pacific  
    Portfolio:  101325               2008-01-02 to 2017-11-30                  Alpha:  
 Initial Cash:  100000                      Buys:      5 (2 partial)            Beta:    0.82  
  Unused Cash:       0                     Sells:      5 (1 partial)          Sharpe:  
   Max Margin: -522321               Commissions:      9                    Drawdown:     9.2  
     Max Risk:  622321 (622%)         Shares Now:   1866                   Stability:   0.030  
  Cash Profit:   38224                Shares Val: -36899                     Sortino:  
 Total Profit:    1325                  Cash Now: 138224                    Shrt/Lng Now:  1.94  
     Q Return:   1.33% Profit/Init      Max Lvrg:   7.82  2008-01-03          Max Shorts:  -76139  
   PvR Return:   0.21% Profit/Risk     PvR %/day:   0.04                      Max  Longs:  686590  
2008-01-08 13:00 ti:1139 INFO .  
2008-01-08 13:00 _ti:967 INFO   Sort column 1                 Positions: 2 of 5 traded  
         Profit    Max   Return  Return   Buy    Price    Buy|Sell    Max     Shares   Shares  
 Symbol    PnL   Risked     %     %/day   Hold  Init|Now   Orders   Shrt|Lng    Now       %  
    ACN   1008    34939   2.89    1.44    -0.0   35|34      1|1     -1000|0       0         0  
   MSFT    231    27592   0.84    0.42    -0.0   34|33      1|1      0|803        0         0  
   AMZN    178    76317   0.23    0.12    -0.1   96|88      1|2      -866|0    -866   -0.7514  
 GOOG_L     98   682712   0.01    0.01    -0.1  682|631     1|1      0|1000       0         0  
   ADBE   -111    39351  -0.28   -0.28    -0.0   39|39      1|0      0|1000    1000    0.3873  
                   Trading Minute  Action          Fild|Prv|Ordr  Sym    Prc      Shrs        PnL   Lvrg  Oid     Cash  
2008-01-14 12:50 _t:433 INFO  380  Buy                      1000 GOOG_L 653.91      _            0  0.00  c32f   104272  
2008-01-14 12:51 _t:433 INFO  381    Bot              375|0|1000 GOOG_L 654.71     375         -16  2.96  c32f   -77748  
2008-01-14 12:52 _t:433 INFO  382    Bot            245|375|1000 GOOG_L 654.14     620        -240  4.51  c32f  -238023  
2008-01-14 12:53 _t:433 INFO  383    Bot        all 380|620|1000 GOOG_L 653.61    1000        -576  6.90  c32f  -486402  
2008-01-16 12:50 _t:433 INFO  380  Sell                    -1000 GOOG_L 617.48    1000      -36706  9.77  3da8  -486402  
2008-01-16 12:51 _t:433 INFO  381    Sold           -783|0|-1000 GOOG_L 616.88     217       -8096  1.94  3da8   -65008  
2008-01-16 12:52 _t:433 INFO  382    Sold    all -217|-783|-1000 GOOG_L 617.97      _        [-36940]  0.00  3da8    69090  
2008-02-05 12:50 _t:433 INFO  380  Sell                     -587 GOOG_L 507.79      _               0  0.00  cb48    66228  
2008-02-05 12:51 _t:433 INFO  381    Sold                   -587 GOOG_L 508.28    -587             -3  4.57  cb48   360237  
2008-02-06 12:50 _t:433 INFO  380  Buy                       587 GOOG_L 501.83    -587           3783  4.66  0231   331119  
2008-02-06 12:51 _t:433 INFO  381    Bot                     587 GOOG_L 501.50      _        [-32961]  0.32  0231    47926  
2008-02-07 12:50 _t:433 INFO  380  Sell                      -38 GOOG_L 503.30      _               0  0.00  9378    70448  
2008-02-07 12:51 _t:433 INFO  381    Sold                    -38 GOOG_L 504.49     -38             -0  1.23  9378   157314  
2008-02-08 12:50 _t:433 INFO  380  Buy                        38 GOOG_L 517.15     -38           -481  1.39  ace8   160649  
2008-02-08 12:51 _t:433 INFO  381    Bot                      38 GOOG_L 516.99      _        [-33437]  0.03  ace8    69283  
2008-02-26 12:50 _t:433 INFO  380  Sell                     -468 GOOG_L 462.21      _               0  0.00  afec    71931  
2008-02-26 12:51 _t:433 INFO  381    Sold                   -468 GOOG_L 462.78    -468             -1  3.52  afec   325007  
2008-02-28 12:50 _t:433 INFO  380  Buy                       468 GOOG_L 474.14    -468          -5318  3.90  d9dd   325007  
2008-02-28 12:51 _t:433 INFO  381    Bot                     468 GOOG_L 474.77      _        [-39050]  0.22  d9dd    80375  
2008-03-03 13:00 _ti:967 INFO  42 trading days     0 hr 0.4 min   2017-12-03 10:23 US/Pacific  
    Portfolio:   66027               2008-01-02 to 2017-11-30                  Alpha:  
 Initial Cash:  100000                      Buys:    37 (15 partial)            Beta:   -0.30  
  Unused Cash:       0                     Sells:    37 (20 partial)          Sharpe:  
   Max Margin: -522321               Commissions:    49                     Drawdown:    52.0  
     Max Risk:  622321 (622%)         Shares Now:     0                    Stability:   0.546  
  Cash Profit:  -33973                Shares Val:     0                      Sortino:  
 Total Profit:  -33973                  Cash Now: 66027                     Shrt/Lng Now:  
     Q Return: -33.97% Profit/Init      Max Lvrg: 11.90  2008-01-16           Max Shorts: -299188  
   PvR Return:  -5.46% Profit/Risk     PvR %/day: -0.13                       Max  Longs:  686590  
2008-03-03 13:00 ti:1139 INFO .  
2008-03-03 13:00 _ti:967 INFO   Sort column 1                 Positions: 0 of 6 traded  
         Profit    Max   Return  Return   Buy    Price    Buy|Sell     Max      Shares  Shares  
 Symbol     PnL  Risked     %     %/day   Hold  Init|Now   Orders    Shrt|Lng    Now       %  
   AMZN    9008   83311   10.8     0.9    -0.3   96|62     10|10     -1000|0      0       0  
    ACN    2860   39632   7.22    0.56    -0.0   35|35      9|9     -1000|1000    0       0  
   ADBE    1684   39351   4.28    0.86    -0.2   39|33      4|4       0|1000      0       0  
   MSFT     231   27592   0.84    0.42    -0.2   34|27      1|1       0|803       0       0  
   AAPL   -8475  159219  -5.32   -0.89    -0.2  159|122     3|3      -1000|0      0       0  
 GOOG_L  -39050  682712  -5.72   -0.71    -0.3  682|457     5|5     -587|1000     0       0  

Hi,

Thanks for pointing that out.
I ran the backtest again with a capital of $400,000.
That brought down the leverage to 2x.

PFA the backtest for the same and let me know your views on it.

Thanks

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

Sure. Couple thoughts.

You can be certain of the max leverage this way since it watches every minute although it will slow things down a bit:

def initialize(context):  
    context.mx_lvrg = 0  
    ...  
def handle_data(context, data):  
    if context.account.leverage > context.mx_lvrg:  
        context.mx_lvrg = context.account.leverage  
        record(MxLv = context.mx_lvrg)       # Record maximum leverage encountered  

With the goal in mind of not needing to worry about leverage, if you could distribute each stock's orders at different times so they won't overlap each other, could be one thing to try. The essential deal is when selling (including short), and incomplete, and buying complete, that's when the leverage is occurring here probably. Although leverage can also happen quickly with an increase in price in short shares.

Another route (since there are only six stocks here so far) that is difficult and requires a lot of code would be to hold each stock's order until the previous is complete. Dealing with them in a loop perhaps, and rechecking for get_open_orders(), only proceeding to the next when any partial fills are done, or only buying with available cash. Or maybe schedule a few times and change ratio*1000 to a lower number, distributing in that way. That would be the simplest I think, although I haven't delved into it to wrap my head around your code very well. Previously all I did is drop some code into it and take a look at the output.

Hi,

Thanks for the suggestion. I will surely try running the back-test using your methodology for controlling the leverage.