Overall Statistics
Total Trades
183
Average Win
0.26%
Average Loss
-0.19%
Compounding Annual Return
32.009%
Drawdown
4.100%
Expectancy
0.349
Net Profit
4.671%
Sharpe Ratio
1.798
Loss Rate
42%
Win Rate
58%
Profit-Loss Ratio
1.33
Alpha
-0.087
Beta
18.789
Annual Standard Deviation
0.168
Annual Variance
0.028
Information Ratio
1.676
Tracking Error
0.168
Treynor Ratio
0.016
Total Fees
$791.98
import decimal as d


class RSIUniverseSelectionAlgorithm(QCAlgorithm):

    def Initialize(self):
        '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''

        self.SetStartDate(2010,1,1)  #Set Start Date
        self.SetEndDate(2010,3,1)    #Set End Date
        self.SetCash(100000)         #Set Strategy Cash

        self.UniverseSettings.Resolution = Resolution.Daily
        self.UniverseSettings.Leverage = 2

        self.coarse_count = 10
        self.averages = { }

        # this add universe method accepts two parameters:
        # - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol>
        self.AddUniverse(self.CoarseSelectionFunction)


    # sort the data by daily dollar volume and take the top 'NumberOfSymbols'
    def CoarseSelectionFunction(self, coarse):

        # We are going to use a dictionary to refer the object that will keep the moving averages
        for cf in coarse:
            if cf.Symbol not in self.averages:
                self.averages[cf.Symbol] = SymbolData(cf.Symbol)

            # Updates the SymbolData object with current EOD price
            avg = self.averages[cf.Symbol]
            avg.update(cf.EndTime, cf.AdjustedPrice)

        # Filter the values of the dict: we only want up-trending securities
        values = list(filter(lambda x: (x.close > 4 and x.rsi.IsReady and x.is_uptrend), self.averages.values()))
  
        # we need to return only the symbol objects
        return [ x.symbol for x in values[:self.coarse_count] ]

    # this event fires whenever we have changes to our universe
    def OnSecuritiesChanged(self, changes):
        # liquidate removed securities
        for security in changes.RemovedSecurities:
            if security.Invested:
                self.Liquidate(security.Symbol)

        # we want 20% allocation in each security in our universe
        for security in changes.AddedSecurities:
            self.SetHoldings(security.Symbol, 0.1)


class SymbolData(object):
    def __init__(self, symbol):
        self.symbol = symbol
        self.rsi = RelativeStrengthIndex(14, MovingAverageType.Simple)
        self.is_uptrend = False
        self.close = None

    def update(self, time, value):
        self.close = value
        self.rsi.Update(time, value)
        self.is_uptrend = self.rsi.Current.Value < 30