Overall Statistics |
Total Trades 38 Average Win 1.93% Average Loss -1.18% Compounding Annual Return -15.861% Drawdown 13.500% Expectancy -0.584 Net Profit -12.434% Sharpe Ratio -2.072 Probabilistic Sharpe Ratio 0.076% Loss Rate 84% Win Rate 16% Profit-Loss Ratio 1.63 Alpha -0.172 Beta 0.093 Annual Standard Deviation 0.075 Annual Variance 0.006 Information Ratio -0.963 Tracking Error 0.343 Treynor Ratio -1.675 Total Fees $49.50 |
class experiment1(QCAlgorithm): def CreateBracketOrder(self, ticker, posSize, entry, limit, sl, pt, risk): return experiment1.bracket(self, ticker, posSize, entry, limit, sl, pt, risk) class bracket: def __init__(self, outer, ticker, posSize, entry, limit, sl, pt, risk): self.outer = outer self.ticker = ticker self.posSize = posSize self.entry = entry self.sl = sl self.pt = pt self.risk = risk self.entryTix = self.outer.StopLimitOrder(ticker, posSize, entry, limit) self.slTix = None self.ptTix = None self.entryTime = None def getExits(self): return [ self.slTix.OrderId if self.slTix is not None else None, self.ptTix.OrderId if self.ptTix is not None else None, ] def createExits(self): self.outer.Log(f"buy {self.posSize} {self.ticker} at {self.entry}") self.entryTime = self.outer.Time self.slTix = self.outer.StopMarketOrder(self.ticker, -self.posSize, self.sl) self.ptTix = self.outer.LimitOrder(self.ticker, -self.posSize, self.pt) def cancelExits(self, orderID): if orderID == self.slTix.OrderId: self.outer.Log(f"sl {self.posSize} {self.ticker} at {self.sl}") self.ptTix.Cancel() else: self.outer.Log(f"pt {self.posSize} {self.ticker} at {self.pt}") self.slTix.Cancel() def Initialize(self): self.SetStartDate(2020, 1, 1) # Set Start Date self.SetCash(10000) # Set Strategy Cash self.openOrders = {} self.orderPrecision = 2 # self.UniverseSettings.Resolution = Resolution.Hour # self.UniverseSettings.Leverage = 1 # self.AddUniverse(self.CoarseSelectionFilter) self.tmp = self.AddEquity("GE", Resolution.Hour) self.tmp.SetDataNormalizationMode(DataNormalizationMode.Raw) # def CoarseSelectionFilter(self, coarse): # sortedByDollarVolume = sorted( # coarse, key=lambda x: x.DollarVolume, reverse=True # ) # filtered = [ # x.Symbol # for x in sortedByDollarVolume # if x.Price > 10 and x.DollarVolume > 10000000 # ][:10] # self.Debug(str(len(filtered))) # return filtered # def OnSecuritiesChanged(self, changes): # self.Debug(f"{self.Time.date()} {self.Time.hour} {self.Time.minute}") def OnData(self, data): # risk 1% of portfolio per trade # risk per share = entry - stop loss # pos size = 1% portfolio / risk per share if "GE" not in self.openOrders: entry = round(self.Securities["GE"].Close, self.orderPrecision) limit = round(entry * 1.001, self.orderPrecision) sl = round(entry * 0.95, self.orderPrecision) risk = round(entry - sl, self.orderPrecision) pt = round(entry + 2 * risk, self.orderPrecision) posSize = int((self.Portfolio.TotalPortfolioValue * 0.01) / risk) self.openOrders["GE"] = self.CreateBracketOrder( "GE", posSize, entry, limit, sl, pt, risk ) # self.Debug("{} {}".format(self.Portfolio.Cash, self.Portfolio.TotalPortfolioValue)) # self.Debug("{} {} {} {} {}".format(entry, risk, sl, pt, risk, posSize)) for k, v in self.openOrders.items(): if ( v.entryTime is not None and (self.Time - v.entryTime).days > 2 and v.slTix.Get(OrderField.StopPrice) < v.entry and self.Securities[v.ticker].Close > v.entry + 0.5 * v.risk ): # pass self.Debug( f"updating SL from {v.slTix.Get(OrderField.StopPrice)} to {v.entry}." ) v.slTix.UpdateStopPrice(v.entry) def OnOrderEvent(self, orderevent): if orderevent.Status == OrderStatus.UpdateSubmitted: tmp = self.openOrders["GE"].slTix.Get(OrderField.StopPrice) self.Debug(f"SL update submitted: {tmp} ") if orderevent.Status != OrderStatus.Filled: return # handle OCO orders for k, v in self.openOrders.items(): if orderevent.OrderId == v.entryTix.OrderId: v.createExits() elif orderevent.OrderId in v.getExits(): v.cancelExits(orderevent.OrderId) self.openOrders.pop(k) break