Overall Statistics
Total Trades
3
Average Win
2.77%
Average Loss
0%
Compounding Annual Return
32.805%
Drawdown
0.200%
Expectancy
0
Net Profit
2.758%
Sharpe Ratio
3.931
Probabilistic Sharpe Ratio
95.666%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
0.284
Beta
-0.017
Annual Standard Deviation
0.069
Annual Variance
0.005
Information Ratio
-2.416
Tracking Error
0.247
Treynor Ratio
-15.932
Total Fees
$3.00
class ResistanceVentralThrustAssembly(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2018, 12, 20) # Set Start Date
        self.SetEndDate(2019, 1, 23)
        self.SetCash(10000)  # Set Strategy Cash
        
        # Strategy is for Daily data
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.MyCoarseFilterFunction)
        self.AddAlpha(MyRSIModel())
        self.SetExecution(ImmediateExecutionModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        self.SetRiskManagement(TrailingStopRiskManagementModel(0.03))
        self.__numberOfSymbols = 1
        self.symbolData = {}

    def MyCoarseFilterFunction(self, coarse):
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        filtered = [x.Symbol for x in sortedByDollarVolume if x.AdjustedPrice > 10 ]
        return filtered[:self.__numberOfSymbols]
    
class MyRSIModel(AlphaModel):
    def __init__(self):
        self.symbolData = {}
    
    def Update(self, algorithm, data):
        insights = []
        for symbol in self.symbolData:
            if symbol in data.Bars:
                self.symbolData[symbol].update(data.Time, data[symbol].Close)
                if self.symbolData[symbol].RSIcross:
                    insights.append(Insight(symbol, timedelta(1), InsightType.Price, InsightDirection.Up))
        return Insight.Group(insights)
    
    def OnSecuritiesChanged(self, algorithm, changes):
        added_symbols = [s.Symbol for s in changes.AddedSecurities]
        history = algorithm.History(added_symbols, 16, Resolution.Daily)
        for s in changes.AddedSecurities:
            self.symbolData[s.Symbol] = SymbolData(s.Symbol, history.loc[s.Symbol])
    
        for s in changes.RemovedSecurities:
            self.symbolData.pop(s.Symbol, None)
    
    
class SymbolData:
    def __init__(self, symbol, history, period=14):
        self.rsi = RelativeStrengthIndex(period, MovingAverageType.Wilders)
        self.rollingRSI = RollingWindow[float](2)
        
        self.RSIcross = False
        for idx, row in history.iterrows():
            self.update(idx, row.close)
        

    def update(self, time, price):
        self.rsi.Update(time, price)
        
        if not self.rsi.IsReady:
            return 
        
        self.rollingRSI.Add(self.rsi.Current.Value)
        
        if not self.rollingRSI.IsReady:
            return
        
        self.RSIcross = self.rollingRSI[1] < 30 and self.rollingRSI[0] > 30