Overall Statistics
Total Trades
132
Average Win
0.15%
Average Loss
-0.07%
Compounding Annual Return
71.280%
Drawdown
8.900%
Expectancy
1.789
Net Profit
27.721%
Sharpe Ratio
3.64
Probabilistic Sharpe Ratio
92.077%
Loss Rate
11%
Win Rate
89%
Profit-Loss Ratio
2.15
Alpha
0.436
Beta
0.543
Annual Standard Deviation
0.162
Annual Variance
0.026
Information Ratio
1.95
Tracking Error
0.158
Treynor Ratio
1.085
Total Fees
$155.00
Estimated Strategy Capacity
$3900000.00
Lowest Capacity Asset
SRC VA4L1G2O9B39
class MyAlphaModel(AlphaModel):
    
    def __init__(self):
        self.lastMonth = None

    
    def OnSecuritiesChanged(self, algorithm, changes):
        pass


    def Update(self, algorithm, data):
        insights = []
        
        if self.lastMonth == algorithm.Time.month:
            return insights
        
        self.lastMonth = algorithm.Time.month
        
        for security in algorithm.ActiveSecurities.Values:
            insights.append(Insight.Price(security.Symbol, timedelta(365), InsightDirection.Up)) 
        
        return insights


class SquareBrownScorpion(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2021, 1, 1)
        self.SetCash(100000) 
        
        self.lastMonth = None
        self.lastRebalanceMonth = -1
        
        self.Settings.RebalancePortfolioOnInsightChanges = False
        self.Settings.RebalancePortfolioOnSecurityChanges = False
        
        self.SetBenchmark("SPY")
        
        self.AddUniverseSelection(FineFundamentalUniverseSelectionModel(self.SelectCoarse, self.SelectFine))
        self.AddAlpha( MyAlphaModel() )
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(self.RebalanceFunction))
        self.AddRiskManagement( NullRiskManagementModel() )
        self.SetExecution( ImmediateExecutionModel() ) 
    
    
    def RebalanceFunction(self, time):
        if self.Time.month != self.lastRebalanceMonth:
            self.lastRebalanceMonth = self.Time.month
            return time
    
    
    def SelectCoarse(self, coarse):
        sorted_by_dollarvolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        return [x.Symbol for x in coarse if x.DollarVolume > 20000000 and x.HasFundamentalData]
    
    
    def SelectFine(self, fine):
        sorted_by_dividend = sorted(fine, key=lambda c: c.ValuationRatios.DivYield5Year, reverse=True)
        return [c.Symbol for c in sorted_by_dividend if c.MarketCap > 5000000000][:20]