Overall Statistics
Total Trades
1160
Average Win
2.08%
Average Loss
-2.10%
Compounding Annual Return
40.127%
Drawdown
49.600%
Expectancy
0.333
Net Profit
2824.249%
Sharpe Ratio
0.965
Probabilistic Sharpe Ratio
45.123%
Loss Rate
33%
Win Rate
67%
Profit-Loss Ratio
0.99
Alpha
0.345
Beta
-0.053
Annual Standard Deviation
0.352
Annual Variance
0.124
Information Ratio
0.599
Tracking Error
0.379
Treynor Ratio
-6.435
Total Fees
$38855.75
class SmallCapInvestmentAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2010, 1, 1)
        self.SetEndDate(2020, 1, 1)
        self.SetCash(50000)

        self.UniverseSettings.Resolution = Resolution.Daily
        self.count = 10

        self.symbols = []
        self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
        
        self.AddEquity("SPY", Resolution.Daily)
        self.Schedule.On(self.DateRules.MonthStart("SPY"),
                         self.TimeRules.AfterMarketOpen("SPY"),
                         self.Rebalance)

    def CoarseSelectionFunction(self, coarse):
        return [x.Symbol for x in coarse if x.HasFundamentalData and x.Price > 5]

    def FineSelectionFunction(self, fine):
        
        market_cap = {}
        
        for i in fine:
            market_cap[i] = (i.EarningReports.BasicAverageShares.ThreeMonths *
                           i.EarningReports.BasicEPS.TwelveMonths *
                           i.ValuationRatios.PERatio)

        sorted_market_cap = sorted([x for x in fine if market_cap[x] > 0], key=lambda x: market_cap[x])

        self.symbols = [i.Symbol for i in sorted_market_cap[:self.count]]
        return self.symbols

    def Rebalance(self):

        for holdings in self.Portfolio.Values:
            symbol = holdings.Symbol
            if symbol not in self.symbols and holdings.Invested:
                self.Liquidate(symbol)

        # Invest 100% in the selected symbols
        for symbol in self.symbols:
            self.SetHoldings(symbol, .25)