| 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)