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)