Overall Statistics
Total Trades
3202
Average Win
0.12%
Average Loss
-0.11%
Compounding Annual Return
9.175%
Drawdown
9.000%
Expectancy
0.107
Net Profit
19.248%
Sharpe Ratio
0.905
Probabilistic Sharpe Ratio
41.729%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
1.16
Alpha
0.039
Beta
0.137
Annual Standard Deviation
0.072
Annual Variance
0.005
Information Ratio
-0.673
Tracking Error
0.191
Treynor Ratio
0.475
Total Fees
$15140.62
Estimated Strategy Capacity
$0
Lowest Capacity Asset
BPYPO X76STIPVGBC5
from AlgorithmImports import *
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
from itertools import groupby
#functools


class UpgradedFluorescentPinkZebra(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 11, 4)  # Set Start Date
        self.SetCash(2000000)  # Set Strategy Cash
        self.AddUniverse(self.Coarse, self.Fine)
        self.longTotal = 40
        self.shortTotal = 40
        self.longStocks = []
        self.shortStocks = []
        self.lastMonth = -1

    def OnData(self, data):
        pass


    def OnSecuritiesChanged(self, changes):
        self.Liquidate()
        for stock in self.longStocks:
            self.SetHoldings(stock, 0.0125)
        for stock in self.shortStocks:
            self.SetHoldings(stock, -0.0125)
    
    def Coarse(self, coarse):
        if self.lastMonth == self.Time.month:
            return Universe.Unchanged
        self.lastMonth = self.Time.month
        
        filtered = [x for x in coarse if x.HasFundamentalData and x.Price > 10 and x.Volume > 0]
        self.dollarVolumeBySymbol = {}
        return [x.Symbol for x in filtered]
    
    def Fine(self, fine):
        self.longStocks = []
        self.shortStocks = []
        self.metrics = {}
        rankinglist = []
        allFine = [x for x in fine]
        for security in fine:
            symbol = security.Symbol
            roic = security.OperationRatios.ROIC.ThreeMonths
            earning_yield = security.ValuationRatios.EarningYield
            pe = security.ValuationRatios.NormalizedPERatio
            ps = security.ValuationRatios.PSRatio
            pb = security.ValuationRatios.PBRatio
            self.metrics[security] = [roic, earning_yield, pe, ps, pb]
            rankinglist.append(security)
            
        '''Rank Securities'''
        self.rankings = {}
        ranking1 = sorted(rankinglist, key = lambda x: self.metrics[x][0], reverse=False)
        ranking2 = sorted(rankinglist, key = lambda x: self.metrics[x][1], reverse=False)
        ranking3 = sorted(rankinglist, key = lambda x: self.metrics[x][2], reverse=False)
        ranking4 = sorted(rankinglist, key = lambda x: self.metrics[x][3], reverse=False)
        ranking5 = sorted(rankinglist, key = lambda x: self.metrics[x][4], reverse=False)

        '''Convert their rankings to numerical values and sum a stocks rankings'''
        for stock in rankinglist:
            rank1 = ranking1.index(stock)
            rank2 = ranking2.index(stock)
            rank3 = ranking3.index(stock)
            rank4 = ranking4.index(stock)
            rank5 = ranking5.index(stock)
            total = (rank1 + rank2 + rank3 + rank4 + rank5)
            
            self.rankings[stock] = total
            
        finalSecurities = []
        sectorCodes = [MorningstarSectorCode.Technology, MorningstarSectorCode.FinancialServices, MorningstarSectorCode.RealEstate, MorningstarSectorCode.Healthcare]
        
        sector1 = [x for x in allFine if x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Technology]
        sector2 = [x for x in allFine if x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.FinancialServices]
        sector3 = [x for x in allFine if x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.RealEstate]
        sector4 = [x for x in allFine if x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Healthcare]
        sectors = [sector1,sector2,sector3,sector4]
        for sector in sectors:
            y = sorted(sector, key = lambda x: self.rankings[x], reverse = True)
            finalSecurities.extend(y[0:10]) #Top 10
            finalSecurities.extend(y[-10:]) #Bottom 1010
            self.longStocks.extend([x.Symbol for x in y[0:10]]) #Switch to Symbol.Value if wanting to Debug and not backtest
            self.shortStocks.extend([x.Symbol for x in y[-10:]])
        
        #         for code, g in groupby(allFine, lambda x: x.AssetClassification.MorningstarSectorCode):
        #   if code not in sectorCodes: continue
        #   y = sorted(g, key = lambda x: self.rankings[x], reverse = True)
        #   finalSecurities.extend(y[0:10]) #Top 10
        #   finalSecurities.extend(y[-10:]) #Bottom 1010
            
        finalSymbols = [x.Symbol for x in finalSecurities]
        finalTickers = [x.Value for x in finalSymbols]
        # self.Debug("LongStocks")
        # self.Debug(self.longStocks)
        # self.Debug("ShortStocks")
        # self.Debug(self.shortStocks)
        return finalSymbols