Overall Statistics |
Total Trades 3431 Average Win 0.00% Average Loss 0.00% Compounding Annual Return -0.196% Drawdown 0.600% Expectancy -0.252 Net Profit -0.392% Sharpe Ratio -0.638 Probabilistic Sharpe Ratio 0.128% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 0.60 Alpha -0.002 Beta 0.007 Annual Standard Deviation 0.002 Annual Variance 0 Information Ratio -0.454 Tracking Error 0.213 Treynor Ratio -0.201 Total Fees $7376.65 Estimated Strategy Capacity $0 Lowest Capacity Asset ES WY1XIAJHWDFL |
#region imports from datetime import datetime, timedelta import datetime from AlgorithmImports import * import pandas as pd from QuantConnect.Python import * from QuantConnect.Indicators import RollingWindow #endregion class RetrospectiveTanButterfly(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 9, 17) # Set Start Date self.SetEndDate(2020, 9, 16) self.SetCash(1000000000) # Set Strategy Cash self.symbolData = {} self.canLong = True self.canShort = True self.contract = self.AddFuture(Futures.Indices.SP500EMini , Resolution.Tick, extendedMarketHours = False, dataNormalizationMode = DataNormalizationMode.BackwardsRatio, dataMappingMode = DataMappingMode.OpenInterest , contractDepthOffset = 0) symbol = self.contract.Symbol #symbol.SetFilter(0, 90) #Futures.Grains.Corn, Futures.Indices.SP500EMini, Futures.Energies.CrudeOilWTI #Energies.CrudeOilWTI self.symbolData[symbol] = SymbolData() self.symbolData[symbol].bidPrice = self.Securities[symbol].BidPrice self.symbolData[symbol].askPrice = self.Securities[symbol].AskPrice self.v_quantity_window = RollingWindow[float](10000) self.v_price_window = RollingWindow[float](10000) self.marketclose = 17*60 self.tickcount = 0 """ test which method is better """ self.askcooldown = True self.bidcooldown = True self.askcooldown = datetime(2000,7,6,10,0,0) self.bidcooldown = datetime(2000,7,6,10,0,0) self.bidreset = 0 self.askreset = 0 self.pricehreset = 0 self.pricelreset = 0 self.tickcount = 0 self.ticklist = [] self.askLimitTicket = 0 self.bidLimitTicket = 0 self.asklock = 0 self.bidlock = 0 self.ask_ice_exp = 0 self.ask_ice_exp = 0 self.askice0reset =0 self.bidice0reset =0 self.dbug = False #delete """ need to add code that will trigger after close and have a 5 min cooldown after open to start algo """ def OnData(self, data): for changedEvent in data.SymbolChangedEvents.Values: if changedEvent.Symbol == self.contract.Symbol: self.Log(f"SymbolChanged event: {changedEvent}") self.Log(f"contract mapped symbol: {self.contract.Mapped}") #if self.ask_ice_exp == 0: # self.ask_ice_exp = self.Time + timedelta(minutes=5) #if self.bid_ice_exp == 0: # self.bid_ice_exp = self.Time + timedelta(minutes=5) #if contract.Exchange. for symbol, symbolData in self.symbolData.items(): if not data.Ticks.ContainsKey(symbol): continue #underlying = symbol.Underlying ticks = data.Ticks[symbol] for tick in ticks: if tick.TickType == TickType.Quote: symbolData.bidPrice = tick.BidPrice if tick.BidPrice != 0 else symbolData.bidPrice symbolData.askPrice = tick.AskPrice if tick.AskPrice != 0 else symbolData.askPrice #symbolData.bidSize = tick.BidSize if tick.BidSize != 0 else symbolData.bidSize #symbolData.askSize = tick.AskSize if tick.AskSize != 0 else symbolData.askSize if tick.TickType == TickType.Trade: self.tickcount += 1 #delete this #if int(self.Time.strftime('%H')) == 1 and int(self.Time.strftime('%M')) == 33 and int(self.Time.strftime('%S')) == 1 and self.dbug: # self.Log(f'tick price current: {tick.Price}') # self.Log(f'time {self.Time} ice {symbolData.askIceberg} count {symbolData.askCounter}') #if int(self.Time.strftime('%H')) == 12 and int(self.Time.strftime('%M')) == 43 and int(self.Time.strftime('%S')) == 1 and self.dbug: # self.Log(f'tick price current: {tick.Price}') def ask_count_reset(): symbolData.askCounter = 0 if not self.askLimitTicket == 0: askTag = str(symbolData.askCounter) self.askLimitTicket.Cancel(askTag) self.askLimitTicket = 0 #self.askcooldown = True #self.ask_ice_exp = self.Time + timedelta(minutes=5) def bid_count_reset(): symbolData.bidCounter = 0 if not self.bidLimitTicket == 0: bidTag = str(symbolData.bidCounter) self.bidLimitTicket.Cancel(bidTag) self.bidLimitTicket = 0 #self.bidcooldown = True #self.bid_ice_exp = self.Time + timedelta(minutes=5) #if self.ask_ice_exp < self.Time: # ask_count_reset() # symbolData.askIceberg = 0 # self.Log(f'test ask reset 5 min') #if self.bid_ice_exp < self.Time: # bid_count_reset() # symbolData.bidIceberg = 0 # self.Log(f'test bid reset 5 min') if symbolData.bidIceberg == 0 and symbolData.bidPrice != 0: bid_count_reset() symbolData.bidIceberg = symbolData.bidPrice self.bidice0reset += 1 if tick.Price < symbolData.bidIceberg: bid_count_reset() symbolData.bidIceberg = tick.Price self.pricelreset += 1 if tick.Price == symbolData.bidIceberg: symbolData.bidCounter += tick.Quantity if tick.Price > symbolData.bidIceberg / 0.995: bid_count_reset() symbolData.bidIceberg = 0 self.bidreset += 1 #delete if symbolData.askIceberg == 0 and symbolData.askPrice != 0: ask_count_reset() symbolData.askIceberg = symbolData.askPrice self.askice0reset += 1 if tick.Price > symbolData.askIceberg: ask_count_reset() symbolData.askIceberg = tick.Price self.pricehreset += 1 if tick.Price == symbolData.askIceberg: symbolData.askCounter += tick.Quantity if tick.Price < symbolData.askIceberg * 0.995: ask_count_reset() symbolData.askIceberg = 0 self.askreset += 1 #delete if symbolData.bidSize > 400: symbolData.bidPacman = symbolData.bidPrice if symbolData.askSize > 400: symbolData.askPacman = symbolData.askPrice #symbolData.bidPrice = symbolData #mark bid price as variable, so that price cant be used as an iceberg #if self.tickcount < 1075 and self.tickcount > 1000: #self.Log(f"tick price->: {tick.Price} tick quantity->: {tick.Quantity} bid ice->: {symbolData.bidIceberg} ask ice->: {symbolData.askIceberg} bid count->: {symbolData.bidCounter} ask count->: {symbolData.askCounter} bid price->: {symbolData.bidPrice} ask price->: {symbolData.askPrice} tick sus->: {tick.Suspicious}") #if tick.Time > datetime(2020,7,6,10,0,0) and tick.Time < datetime(2020,7,6,10,0,10):#2020-07-06 10:00:03 #self.Log(f"tick price->: {tick.Price} tick quantity->: {tick.Quantity} bid ice->: {symbolData.bidIceberg} ask ice->: {symbolData.askIceberg} bid count->: {symbolData.bidCounter} ask count->: {symbolData.askCounter} bid price->: {symbolData.bidPrice} ask price->: {symbolData.askPrice} tick sus->: {tick.Suspicious}") #if symbolData.askCounter < 100: # symbolData.askIceberg = 0 # symbolData.askCounter = 0 # self.askreset += 1 #delete if symbolData.askCounter > 700 and tick.Time > self.askcooldown and self.asklock != symbolData.askIceberg and not self.contract.Exchange.IsClosingSoon(75): #and symbolData.askPacman == symbolData.askIceberg: self.MarketOrder(self.contract.Mapped, 1) #self.askcooldown = False self.askcooldown = tick.Time + timedelta(minutes=5) self.Log(f"ask counter: {symbolData.askCounter}") self.Log(f"ask lock: {self.asklock}") self.asklock = symbolData.askIceberg #symbolData.askCounter = 0 #symbolData.askIceberg = 0 self.askLimitTicket = self.LimitOrder(self.contract.Mapped, 1, 1) #self.Log(f'is closing soon {self.contract.Exchange.IsClosingSoon(75)}') if symbolData.bidCounter > 700 and tick.Time > self.bidcooldown and self.bidlock != symbolData.bidIceberg and not self.contract.Exchange.IsClosingSoon(75): # and symbolData.bidPacman == symbolData.bidIceberg: self.MarketOrder(self.contract.Mapped, -1) #self.bidcooldown = False self.bidcooldown = tick.Time + timedelta(minutes=5) self.Log(f"bid counter: {symbolData.bidCounter}") self.Log(f"bid lock: {self.bidlock}") self.bidlock = symbolData.bidIceberg #symbolData.bidCounter = 0 #symbolData.bidIceberg = 0 self.bidLimitTicket = self.LimitOrder(self.contract.Mapped, 1, 1) #self.Log(f'is closing soon {self.contract.Exchange.IsClosingSoon(75)}') def OnEndOfDay(self, symbol): symbolData = self.symbolData[symbol] #self.Debug(f"{symbol.Value}'s buy volume is {symbolData.buyVolume} and sell volume is {symbolData.sellVolume} for today") #self.Log(f"{symbol.Value}'s buy volume is {symbolData.buyVolume} and sell volume is {symbolData.sellVolume} for today") #self.v_quantity_window.Reset() #self.v_price_window.Reset() self.Log(f"bid resets for today {self.bidreset}") self.Log(f"ask resets for today {self.askreset}") self.bidreset = 0 self.askreset = 0 self.Log(f"bid higher resets for today {self.pricehreset}") self.Log(f"ask lower resets for today {self.pricelreset}") self.pricehreset = 0 self.pricelreset = 0 self.Log(f"bid 0 resets for today {self.bidice0reset}") self.Log(f"ask 0 resets for today {self.askice0reset}") self.bidice0reset = 0 self.askice0reset = 0 self.askcooldown = datetime(2000,7,6,10,0,0) self.bidcooldown = datetime(2000,7,6,10,0,0) class SymbolData: def __init__(self): self.buyVolume = 0 self.sellVolume = 0 self.bidPrice = 0 self.askPrice = 0 self.bidCounter = 0 self.askCounter = 0 self.bidIceberg = 0 self.askIceberg = 0 self.bidSize = 0 self.askSize = 0 self.bidPacman = 0 self.askPacman = 0