Overall Statistics
Total Trades
275
Average Win
0.15%
Average Loss
-0.18%
Compounding Annual Return
-3.614%
Drawdown
3.200%
Expectancy
-0.059
Net Profit
-1.603%
Sharpe Ratio
-1.094
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
0.84
Alpha
0.093
Beta
-6.515
Annual Standard Deviation
0.033
Annual Variance
0.001
Information Ratio
-1.69
Tracking Error
0.033
Treynor Ratio
0.006
Total Fees
$397.36
import numpy as np
from datetime import timedelta
from QuantConnect.Securities.Option import OptionPriceModels
import pandas as pd

# A pairs trading strategy for dual listed stocks
class DualListedArb(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2017, 6,1)  
        self.SetEndDate(2017,12,1)    
        self.SetCash(10000)  
        
        self.TriggerSignal = .025
        # Adding the dual class shares of Viacom 
        self.AddEquity("VIA", Resolution.Minute)
        self.AddEquity("VIAB", Resolution.Minute)
        
        self.AddEquity("SPY", Resolution.Minute)
        # Set a benchmark at the beginning of every trading day
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                self.TimeRules.At(0,0),
                Action(self.SetBenchmark))
        self.SetWarmUp(int(6.5*60*100))

    def OnData(self, data):
        # Called every minute
        if self.IsWarmingUp: return
        if data["VIAB"] is None: return
        if data["VIA"] is None: return
        if not data.ContainsKey("VIAB"): return
        if not data.ContainsKey("VIA"): return      
        mainPrice = data["VIAB"].Price 
        dualPrice = data["VIA"].Price

        self.currentSpread = dualPrice - mainPrice
        self.currentSpread = float(self.currentSpread)
        self.percentDiff = (self.currentSpread-self.benchmarkSpread)/self.benchmarkSpread
        # If the current spread is >2.5% of the benchmark spread in the 
        # SetBenchmark method, buy the stock without the premium
        if self.percentDiff > .025:
            if self.Portfolio["VIAB"].Quantity <= 0:
                self.SetHoldings("VIAB", 1.0, tag="Long")
        if self.percentDiff < .025:
            if self.Portfolio["VIAB"].Quantity > 0:
                self.SetHoldings("VIAB", 0, tag="Short")
                    
    def SetBenchmark(self):
        # Returns a spread for the premium of owning VIA stock over the 
        # past 100 days
        # The mean of those 100 spreads becomes the Benchmark Spread that we base our
        # predictions off of
        self.mainHistory = self.History(["VIAB"], 100)
        self.dualHistory = self.History(["VIA"], 100)
        
        mainBars = self.mainHistory.loc["VIAB"]
        mainHistoricalClose = mainBars["close"]
        dualBars = self.dualHistory.loc["VIA"]
        dualHistoricalClose = dualBars["close"]
        
        spread = dualHistoricalClose - mainHistoricalClose
        self.benchmarkSpread = spread.mean()
        self.benchmarkSpread = float(self.benchmarkSpread)