Overall Statistics |
Total Trades 204 Average Win 0.24% Average Loss -0.16% Compounding Annual Return 2.718% Drawdown 4.300% Expectancy 0.277 Net Profit 3.240% Sharpe Ratio 0.452 Loss Rate 48% Win Rate 52% Profit-Loss Ratio 1.45 Alpha 0.118 Beta -5.051 Annual Standard Deviation 0.058 Annual Variance 0.003 Information Ratio 0.136 Tracking Error 0.058 Treynor Ratio -0.005 Total Fees $205.74 |
class BensdorbMeanReversionLong(QCAlgorithm): cur_sec={} indic={} indic_adx={} def Initialize(self): self.SetStartDate(2017, 1, 18) # Set Start Date self.SetEndDate(2018, 12, 30) # Set Start Date self.SetCash(10000) # Set Strategy Cash self.__numberOfSymbols = 10 self.UniverseSettings.Resolution = Resolution.Daily self.UniverseSettings.Leverage = 1 self.AddUniverse(self.CoarseSelectionFunction) def CoarseSelectionFunction(self, coarse): filtered = [ x for x in coarse if x.Price > 1 and x.DollarVolume > 2500000 ] #self.Debug("------------") #self.Debug(len(filtered)) #indicators without adx #self.indic.clear() for cf in filtered: if cf.Symbol not in self.indic: self.indic[cf.Symbol] = SymbolData(cf.Symbol,self) # indic_cond=self.indic[cf.Symbol] indic_cond.update(cf.EndTime, cf.AdjustedPrice) filtered=[x for x in self.indic.values() if x.is_above_ema \ and x.is_rsi_cond ] #adx indicator #self.indic_adx.clear() for indic in filtered: symb=indic.symbol #if symb not in self.indic_adx: try: self.indic_adx[symb] = SymbolDataADX(indic) self.AddEquity(str(symb.Value),Resolution.Daily) self._updateADX(symb) except Exception as e: self.Debug(e) self.Log(e) # filtered_adx=[x for x in self.indic_adx.values() if x.is_adx_cond \ and x.is_atr_cond] # if len(filtered_adx)>0: self.Debug("###") self.Debug(len(filtered_adx)) # values=sorted(filtered_adx, key = lambda x: x.symb_data.rsi, \ reverse=False)[:self.__numberOfSymbols] return [ x.symb_data.symbol for x in values] def OnSecuritiesChanged(self, changes): self.changes = changes for security in changes.AddedSecurities: symb=security.Symbol if not security.IsTradable: continue try: price=security.Close if price>0 and symb not in self.cur_sec: self.cur_sec[symb]={'entry_price' : price,\ 'stop_price': .0, \ 'profit_price': price + price * 0.03, \ 'bars_since_entry' : 0} except Exception as e: self.Debug(e) self.Log(e) def OnData(self, data): lst_to_del=[] for symb in self.cur_sec: symb_str=str(symb.Value) try: if (data.ContainsKey(symb_str))==False or data[symb_str]==None: continue price=data[symb_str].Close #enter long if self.cur_sec[symb]['entry_price'] <price - price * 0.01 \ and self.cur_sec[symb]['bars_since_entry']==1 : self.SetHoldings(symb, 0.1) #exit long elif price>self.cur_sec[symb]['profit_price'] \ or price < self.cur_sec[symb]['stop_price'] \ or self.cur_sec[symb]['bars_since_entry'] > 4 : # self.Liquidate(symbolToLiquidate=symb_str) lst_to_del.append(symb) self.cur_sec[symb]['bars_since_entry']=0 else: if self.cur_sec[symb]['bars_since_entry']>2: self._updateADX(symb) self.cur_sec[symb]['stop_price']= price -\ self.indic_adx[symb].atr.Current.Value / price * 2.5 self.cur_sec[symb]['bars_since_entry']+=1 # except Exception as e: self.Debug(e) self.Log(e) for symb in lst_to_del: self.cur_sec.pop(symb) if symb in self.indic: self.indic.pop(symb) if symb in self.indic_adx: self.indic_adx.pop(symb) self.RemoveSecurity(str(symb.Value)) def _updateADX(self,symb): try: self.AddEquity(str(symb.Value),Resolution.Daily) tradeBarHistory = self.History(str(symb.Value), 7, Resolution.Daily) for tradeBar in tradeBarHistory: self.indic_adx[symb].update(tradeBar); except Exception as e: self.Debug(e) self.Log(e) class SymbolData(object): def __init__(self, symbol,strat): self.strat=strat self.price=0 self.symbol=symbol self.ema = ExponentialMovingAverage(150) self.rsi =RelativeStrengthIndex(3) self.is_above_ema = False self.is_rsi_cond= False def update(self,time, value): #self.strat.Debug("indic value: " + str(value)) #self.strat.Debug("time: " + str(time)) if self.ema.Update(time,value) and self.rsi.Update(time,value): self.price=value ema = self.ema.Current.Value rsi = self.rsi.Current.Value self.is_above_ema = value > ema #self.strat.Debug("ema: " + str(ema)) self.is_rsi_cond = rsi < 30 class SymbolDataADX(object): def __init__(self, symb_data): self.symb_data=symb_data self.atr= AverageTrueRange("",10) self.adx = AverageDirectionalIndex("",7) self.is_adx_cond =False self.is_atr_cond =False def update(self, bar): if self.adx.Update(bar) and self.atr.Update(bar): # atr=self.atr.Current.Value adx=self.adx.Current.Value #self.symb_data.strat.Debug("update atr: "+ str(atr/bar.Close)) self.is_atr_cond = atr/bar.Close > 0.04 self.is_adx_cond = adx > 45