Overall Statistics
Total Trades
924
Average Win
0.91%
Average Loss
-0.91%
Compounding Annual Return
21.552%
Drawdown
39.400%
Expectancy
0.249
Net Profit
165.624%
Sharpe Ratio
0.813
Probabilistic Sharpe Ratio
26.067%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
1.01
Alpha
0.058
Beta
1.144
Annual Standard Deviation
0.267
Annual Variance
0.071
Information Ratio
0.425
Tracking Error
0.183
Treynor Ratio
0.19
Total Fees
$1445.41
Estimated Strategy Capacity
$20000000.00
Lowest Capacity Asset
ETSY VZR6X1TTY8H1
class Phase2Week2(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2016, 1, 1)
        self.SetEndDate(2021,1,1)
        self.SetCash(100000) 
        
        self.rebalanceTime = datetime.min
        self.activeStocks = set()
    
        self.AddUniverse(self.CoarseFilter, self.FineFilter)
        self.UniverseSettings.Resolution = Resolution.Hour
        
        self.portfolioTargets = []
        
        #for symbol in self.activeStocks:
            #self.AddEquity(symbol, Resolution.Daily)
            #self.macd = self.MACD(symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Daily)
       
        
    def CoarseFilter(self, coarse):
        if self.Time <= self.rebalanceTime:
            return self.Universe.Unchanged
        
        # to rebalance on a monthly basis
        self.rebalanceTime = self.Time + timedelta(30)
        
        # to sort by market cap, price more than $5 and return top 30)
        sortedByDollarVolume = sorted(coarse, key = lambda x: x.DollarVolume,
                                        reverse=True)
        return [x.Symbol for x in sortedByDollarVolume if x.Price > 5
                                and x.HasFundamentalData][:30]
                                
        self.Debug(sortedByDollarVolume)

    def FineFilter(self, fine):
        #further filter by PE ratio
        sortedByPE = sorted(fine, key = lambda x: x.MarketCap)
        return [x.Symbol for x in sortedByPE if x.MarketCap > 0][:10]
        
        self.Debug(sortedByPE)

        
    def OnSecuritiesChanged (self, changes):
        for x in changes.RemovedSecurities:
            self.Liquidate(x.Symbol)
            self.activeStocks.remove(x.Symbol)
        
        for x in changes.AddedSecurities:
            self.activeStocks.add(x.Symbol)
        
        self.portfolioTargets = [PortfolioTarget(symbol, 1/len(self.activeStocks))
                        for symbol in self.activeStocks]
   
   
    def OnData(self, data):
        if self.portfolioTargets == []:
            return
        
        for symbol in self.activeStocks:
            if symbol not in data:
                return
            
            #if self.macd.Current.Value > self.macd.Signal.Current.Value:
            self.SetHoldings(self.portfolioTargets)
            self.portfolioTargets = []