Overall Statistics
Total Trades
973
Average Win
0.12%
Average Loss
-0.07%
Compounding Annual Return
38.668%
Drawdown
6.300%
Expectancy
0.378
Net Profit
17.814%
Sharpe Ratio
2.431
Probabilistic Sharpe Ratio
85.987%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
1.70
Alpha
0.003
Beta
0.946
Annual Standard Deviation
0.108
Annual Variance
0.012
Information Ratio
-0.208
Tracking Error
0.057
Treynor Ratio
0.277
Total Fees
$973.41
from Selection.QC500UniverseSelectionModel import QC500UniverseSelectionModel

class CalibratedOptimizedCompensator(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 8, 16)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        # Set QC500 Universe Selection Model
        self.SetUniverseSelection(QC500UniverseSelectionModel())
        # Dictionary to hold SecurityData 
        self.data = {}
    
    def OnData(self, data):
        # Sort by ROIC
        sortedByROIC = sorted(list(self.data.keys()), key=lambda k : self.data[k].roic, reverse=True)
        # Sorted by MOM
        sortedByMOM = sorted(sortedByROIC[:100], key=lambda k : self.data[k].mom.Current.Value, reverse=True)
        # Select top 25 symbols
        selected = sortedByMOM[: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 not self.Portfolio[symbol].Invested:
                self.SetHoldings(symbol, 0.04)
                
    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.roic = security.Fundamentals.OperationRatios.ROIC.OneYear
        self.mom = algorithm.MOM(symbol, 14, Resolution.Daily)
        
        # Initialize MOM indicator with historical data
        history = algorithm.History(symbol, 14, Resolution.Daily)
        
        if not history.empty:
            history = history.close.unstack(0)
            if not history.empty:
                df = history[symbol]
                for time, close in df.iteritems():
                    self.mom.Update(time, close)