Overall Statistics |
Total Trades 4386 Average Win 0.01% Average Loss -0.01% Compounding Annual Return -40.168% Drawdown 4.500% Expectancy -0.187 Net Profit -4.269% Sharpe Ratio -8.319 Probabilistic Sharpe Ratio 0.000% Loss Rate 55% Win Rate 45% Profit-Loss Ratio 0.80 Alpha -0.33 Beta 0.066 Annual Standard Deviation 0.035 Annual Variance 0.001 Information Ratio -11.174 Tracking Error 0.077 Treynor Ratio -4.4 Total Fees $86036.18 Estimated Strategy Capacity $220000000.00 Lowest Capacity Asset THS T9V5YFMQ412D |
import numpy as np import pandas as pd import math import time class StatArb1(QCAlgorithm): def Initialize(self): self.SetStartDate(2012, 1,4) self.SetEndDate(2012,2,5) self.SetCash(20000000) self.SetWarmup(10) self.UniverseSettings.Resolution = Resolution.Minute self.UniverseSettings.MinimumTimeInUniverse = timedelta(hours=12) self.AddUniverse(self.LiquidWithFundamentalsFilter) self.spy = self.AddEquity("SPY",Resolution.Minute) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 10), self.Liquidate) self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 1), self.RefactorPortfolio) self.lookback = 20 self.activeStocks = [] self.maxWeight = .1 def LiquidWithFundamentalsFilter(self, coarse): sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) filtered = [ x.Symbol for x in sortedByDollarVolume if x.Price > 50 and x.DollarVolume > 10000000 and x.HasFundamentalData] return filtered[:100] def OnSecuritiesChanged(self, changes): for s in changes.RemovedSecurities: if s.Symbol in self.activeStocks: self.activeStocks.remove(s.Symbol) for s in changes.AddedSecurities: if str(s.Symbol) == "SPY": continue self.activeStocks.append(s.Symbol) def RefactorPortfolio(self): tickers = [s for s in self.activeStocks if s.ToString() != "SPY"] data = self.History(tickers,self.lookback,Resolution.Daily) dates = data.index.get_level_values("time") self.Debug("###"+str(dates[-1])+", "+str(len(tickers))+", "+str(len(self.ActiveSecurities))) tickerIndustries = {} for ticker in tickers: tickerIndustries[ticker] = self.ActiveSecurities[ticker].Fundamentals.AssetClassification.MorningstarIndustryCode alpha = {} for ticker in tickers: try: delta1close = data.loc[(ticker,dates[-2]),"close"]-data.loc[(ticker,dates[-3]),"close"] close = data.loc[(ticker,dates[-2]),"close"] delay1close = data.loc[(ticker,dates[-3]),"close"] volumeavailability = len([x for x in data.loc[(ticker,slice(None)),"volume"]]) sumvolume = sum([x for x in data.loc[(ticker,slice(None)),"volume"]]) adv20 = sumvolume/volumeavailability volume = data.loc[(ticker,dates[-2]),"volume"] vwap = sum([x[0]*x[1] for x in zip(data.loc[(ticker,slice(None)),"volume"], data.loc[(ticker,slice(None)), "close"])])/sumvolume todaysopen = data.loc[(ticker,dates[-1]),"open"] yesterdaysopen = data.loc[(ticker,dates[-2]),"open"] value = -np.log(todaysopen/close) except: self.Debug("Alpha Calculation Threw Error") value = np.NAN alpha[ticker] = value alpha = self.Neutralize(alpha, tickerIndustries) for ticker in alpha: if np.isnan(alpha[ticker]): alpha[ticker] = 0 if abs(alpha[ticker]) > self.maxWeight: alpha[ticker] = np.sign(alpha[ticker])*self.maxWeight self.SetHoldings(ticker,math.floor(alpha[ticker]*100000)/100000) def Neutralize(self, alpha, groupClassifications): groupValues = {} groupAvgs = {} groupTotalMagnitude = {} for group in set(groupClassifications.values()): groupValues[group] = [] for ticker in alpha.keys(): groupValues[groupClassifications[ticker]].append(alpha[ticker]) for group in set(groupClassifications.values()): groupAvgs[group] = np.nanmean(np.array(groupValues[group])) groupTotalMagnitude[group] = np.nansum(np.array([abs(x) for x in groupValues[group]])) for ticker in alpha.keys(): group = groupClassifications[ticker] alpha[ticker] = (alpha[ticker]-groupAvgs[group])/(groupTotalMagnitude[group]) return alpha def OnData(self, data): pass #self.Plot("Equity", 'Line', self.Portfolio.TotalPortfolioValue) #self.Plot("Margin", 'Line', self.Portfolio.TotalMarginUsed)