Overall Statistics |
Total Trades 351 Average Win 2.75% Average Loss -2.95% Compounding Annual Return 8.333% Drawdown 14.300% Expectancy 0.190 Net Profit 105.603% Sharpe Ratio 0.726 Probabilistic Sharpe Ratio 16.111% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 0.93 Alpha 0.073 Beta 0.003 Annual Standard Deviation 0.101 Annual Variance 0.01 Information Ratio -0.38 Tracking Error 0.18 Treynor Ratio 22.328 Total Fees $11403.83 Estimated Strategy Capacity $3600000.00 Lowest Capacity Asset EWA R735QTJ8XC9X |
class EMAMomentumUniverse(QCAlgorithm): def Initialize(self): # Define backtest window and portfolio cash self.SetStartDate(2012, 6, 10) self.SetEndDate(2021, 6, 9) self.SetCash(100000) # Add the assets to be fed into the algorithm and save the symbol objects (to be referred later) self.ewc_symbol = self.AddEquity('EWC', Resolution.Daily).Symbol self.ewa_symbol = self.AddEquity('EWA', Resolution.Daily).Symbol # Create two identity indicators (a indicator that repeats the value without any processing) self.ewc_identity = Identity("My_EWC") self.ewa_identity = Identity("My_EWA") # Set these indicators to receive the data from EWC and EWA self.RegisterIndicator(self.ewc_symbol, self.ewc_identity, Resolution.Daily) self.RegisterIndicator(self.ewa_symbol, self.ewa_identity, Resolution.Daily) # create the portfolio as a new indicator # this is handy as the portfolio will be updated as new data comes in, without the necessity of updating the values manually # as the QCAlgorithm already has a Portfolio attribute, we will call our combined portfolio as series self.series = IndicatorExtensions.Minus(self.ewc_identity, IndicatorExtensions.Times(self.ewa_identity, 1.312)) # We then create a bollinger band with 120 steps for lookback period self.bb = BollingerBands(120, 0.5, MovingAverageType.Exponential) # Define the objectives when going long or going short (long=buy EWC and sell EWA) (short=sell EWC and buy EWA) self.long_targets = [PortfolioTarget(self.ewc_symbol, 0.9), PortfolioTarget(self.ewa_symbol, -0.9)] self.short_targets = [PortfolioTarget(self.ewc_symbol, -0.9), PortfolioTarget(self.ewa_symbol, 0.9)] self.is_invested = None def OnData(self, data): # for daily bars data is delivered at 00:00 of the day containing the closing price of the previous day (23:59:59) if (not data.Bars.ContainsKey(self.ewc_symbol)) or (not data.Bars.ContainsKey(self.ewa_symbol)): return #update the Bollinger Band value self.bb.Update(self.Time, self.series.Current.Value) # check if the bolllinger band indicator is ready (filled with 120 steps) if not self.bb.IsReady: return serie = self.series.Current.Value self.Plot("EWA Prices", "Open", self.Securities[self.ewa_symbol].Open) self.Plot("EWA Prices", "Close", self.Securities[self.ewa_symbol].Close) self.Plot("Indicators", "Serie", serie) self.Plot("Indicators", "Middle", self.bb.MiddleBand.Current.Value) self.Plot("Indicators", "Upper", self.bb.UpperBand.Current.Value) self.Plot("Indicators", "Lower", self.bb.LowerBand.Current.Value) # if it is not invested, see if there is an entry point if not self.is_invested: # if our portfolio is bellow the lower band, enter long if serie < self.bb.LowerBand.Current.Value: self.SetHoldings(self.long_targets) self.Debug('Entering Long') self.is_invested = 'long' # if our portfolio is above the upper band, go short if serie > self.bb.UpperBand.Current.Value: self.SetHoldings(self.short_targets) self.Debug('Entering Short') self.is_invested = 'short' # if it is invested in something, check the exiting signal (when it crosses the mean) elif self.is_invested == 'long': if serie > self.bb.MiddleBand.Current.Value: self.Liquidate() self.Debug('Exiting Long') self.is_invested = None elif self.is_invested == 'short': if serie < self.bb.MiddleBand.Current.Value: self.Liquidate() self.Debug('Exiting Short') self.is_invested = None