Overall Statistics
Total Trades
438
Average Win
0.58%
Average Loss
-0.40%
Compounding Annual Return
-34.856%
Drawdown
20.100%
Expectancy
0.017
Net Profit
-3.575%
Sharpe Ratio
-0.273
Probabilistic Sharpe Ratio
34.183%
Loss Rate
58%
Win Rate
42%
Profit-Loss Ratio
1.44
Alpha
-0.5
Beta
1.184
Annual Standard Deviation
0.601
Annual Variance
0.362
Information Ratio
-0.752
Tracking Error
0.595
Treynor Ratio
-0.139
Total Fees
$1130.55
Estimated Strategy Capacity
$25000000.00
Lowest Capacity Asset
GME SC72NCBXXAHX
class WellDressedSkyBlueSardine(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 12, 1)
        self.SetEndDate(2020, 12, 31)
        self.SetCash(100000)
        
        self.AddUniverse(self.CoarseFilter, self.FineFilter)
        self.UniverseSettings.Resolution = Resolution.Hour
        
        self.Data = {}
        
    def CoarseFilter(self, coarse):
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        return [x.Symbol for x in sortedByDollarVolume if x.Price > 10
                                                and x.HasFundamentalData][:200]

    def FineFilter(self, fine):
        sortedByPE = sorted(fine, key=lambda x: x.MarketCap)
        return [x.Symbol for x in sortedByPE if x.MarketCap > 0][:10]

    def OnSecuritiesChanged(self, changes):
        # close positions in removed securities
        for x in changes.RemovedSecurities:
            self.Liquidate()
            if x.Symbol in self.Data:
                del self.Data[x.Symbol]
        
        # can't open positions here since data might not be added correctly yet
        for x in changes.AddedSecurities:
            self.Data[x.Symbol] = SCTR("SCTR",x.Symbol)
            self.RegisterIndicator(x.Symbol,self.Data[x.Symbol],Resolution.Daily)
            history = self.History(x.Symbol, 200, Resolution.Daily)
            if history.empty or 'close' not in history.columns:
                    continue
            for bar in history.loc[x.Symbol, :].itertuples():
                    tradebar = TradeBar(bar.Index, x.Symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
                    self.Data[x.Symbol].Update(tradebar)
    def OnData(self, data): 
        
        SCTR = {}
        
        for symboldata in self.Data.values():
            if symboldata.IsReady:
                self.Debug(f'{symboldata.symbol}\'s SCTR = {symboldata.Value} in {self.Time}')
                SCTR[symboldata.symbol] = symboldata.Value
                
        [self.SetHoldings(symbol, sctr/sum(list(SCTR.values()))) for symbol, sctr in SCTR.items()]
        
class SCTR(PythonIndicator):
    def __init__(self, name,symbol):
        self.Name = name
        self.symbol = symbol
        
        
        self.Value = 0
        self.EMA200 = ExponentialMovingAverage(200)
        self.EMA50 = ExponentialMovingAverage(50)
        self.ROC125 = RateOfChange(125)
        self.ROC20 = RateOfChange(20)
        self.PPO = PercentagePriceOscillator(12,26,MovingAverageType.Exponential)
        self.RSI14 = RelativeStrengthIndex(14)
        self.PPOWindow = RollingWindow[float](3)

    def Update(self, bar):
        self.EMA200.Update(bar.Time, bar.Close)
        self.EMA50.Update(bar.Time, bar.Close)
        self.ROC125.Update(bar.Time, bar.Close)
        self.ROC20.Update(bar.Time, bar.Close)
        self.PPO.Update(bar.Time, bar.Close)
        self.RSI14.Update(bar.Time, bar.Close)
            
        self.PPOWindow.Add(self.PPO.Current.Value)
        if self.isReady():
            self.Value = self.SCTR()
            return True
        self.Value = 0
        return False

    def SCTR(self):
        return self.EMA200.Current.Value*0.3 + self.EMA50.Current.Value*0.15 + self.ROC125.Current.Value*0.3 + self.ROC20.Current.Value*0.15 \
                + (self.PPOWindow[0] - self.PPOWindow[2])/(3*self.PPOWindow[2]) *0.05 + self.RSI14.Current.Value*0.05
    def isReady(self):
        return self.EMA200.IsReady and self.EMA50.IsReady \
                    and self.ROC125.IsReady and self.ROC20.IsReady\
                    and self.PPO.IsReady and self.RSI14.IsReady