Overall Statistics
Total Trades
87
Average Win
1.49%
Average Loss
-1.14%
Compounding Annual Return
101.987%
Drawdown
45.300%
Expectancy
0.342
Net Profit
253.789%
Sharpe Ratio
1.933
Probabilistic Sharpe Ratio
68.262%
Loss Rate
42%
Win Rate
58%
Profit-Loss Ratio
1.31
Alpha
0.817
Beta
1.139
Annual Standard Deviation
0.564
Annual Variance
0.318
Information Ratio
1.719
Tracking Error
0.495
Treynor Ratio
0.956
Total Fees
$126.25
Estimated Strategy Capacity
$37000000.00
Lowest Capacity Asset
PCG R735QTJ8XC9X
#Takes 25 lowest cape ratio stocks from the QC 500

from Selection.QC500UniverseSelectionModel import QC500UniverseSelectionModel

class CalibratedOptimizedCompensator(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 8, 16)  # Set Start Date
        self.SetEndDate(2021, 6, 1)
        self.SetCash(100000)  # Set Strategy Cash
        # Set QC500 Universe Selection Model
        self.SetUniverseSelection(QC500UniverseSelectionModel())
        # Dictionary to hold SecurityData 
        self.data = {}
        self.count = 0
    def OnData(self, data):
        # Sort by CAPE
        sortedByCAPE = sorted(list(self.data.keys()), key=lambda k : self.data[k].cape, reverse=True)
        # Sorted by MOM
        sortedByROIC = sorted(sortedByCAPE[:200], key=lambda k : self.data[k].roic, reverse=False)
        # Select top 25 symbols
        selected = sortedByROIC[:25]
        # Liquidate outdated symbols
        for kvp in self.Portfolio:
            symbol = kvp.Key
            holding = kvp.Value
            if symbol not in selected and holding.Invested:
                self.Liquidate(symbol)
        # Set holdings to selected symbols
        for symbol in selected:
            if self.count < 14:
                self.count = self.count + 1
                return
            else:
                if not self.Portfolio[symbol].Invested:
                    self.SetHoldings(symbol, 0.04)
                    self.count = 0
                
    def OnSecuritiesChanged(self, changes):
        
        for security in changes.AddedSecurities:
            symbol = security.Symbol
            if symbol not in self.data:
                self.data[symbol] = SecurityData(self, symbol, security) 


class SecurityData:
    
    def __init__(self, algorithm, symbol, security):
        self.algorithm = algorithm
        self.symbol = symbol
        self.security = security
        # Retrieves ROIC fundamental
        self.cape = security.Fundamentals.ValuationRatios.PERatio
        self.roic = security.Fundamentals.OperationRatios.ROIC.OneYear