Overall Statistics
Total Trades
210
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
0.128%
Drawdown
0.000%
Expectancy
-0.528
Net Profit
0.001%
Sharpe Ratio
3.451
Probabilistic Sharpe Ratio
0%
Loss Rate
69%
Win Rate
31%
Profit-Loss Ratio
0.52
Alpha
0.045
Beta
-0.013
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-139.442
Tracking Error
0.024
Treynor Ratio
-0.084
Total Fees
$451.50
Estimated Strategy Capacity
$0
Lowest Capacity Asset
ES WSVU0MELFS3L
#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, 1, 1)  # Set Start Date
        self.SetEndDate(2018, 1, 4)
        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)
        #symbol.SetFilter(lambda x: x.FrontMonth().OnlyApplyFilterAtMarketOpen())
        self.marketclose = 17*60
        self.tickcount = 0

        #self.treset = datetime(2000,7,6,10,0,0)
        self.askcooldown = True
        self.bidcooldown = True

        self.bidreset = 0
        self.askreset = 0
        self.pricehreset = 0
        self.pricelreset = 0
        self.tickcount = 0

        self.orderIDs = pd.DataFrame([],columns=['id','fillprice','quantity','time'])
        self.BuyFlag = False
        self.trigger = False
        self.ticklist = []
        self.askLimitTicket = 0
        self.bidLimitTicket = 0
        self.asklock = 0
        self.bidlock = 0
            
    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}")

        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

                    def ask_ticket_reset():
                        if not self.askLimitTicket == 0:
                            askTag = str(symbolData.askCounter)
                            self.askLimitTicket.Cancel(askTag)
                            self.askLimitTicket = 0
                            symbolData.askCounter = 0
                            self.askcooldown = True

                    def bid_ticket_reset():
                        if not self.bidLimitTicket == 0:
                            bidTag = str(symbolData.bidCounter)
                            self.bidLimitTicket.Cancel(bidTag)
                            self.bidLimitTicket = 0
                            symbolData.bidCounter = 0
                            self.bidcooldown = True

                    
                    if symbolData.bidIceberg == 0 and symbolData.bidPrice != 0: 
                        bid_ticket_reset()
                        symbolData.bidIceberg = symbolData.bidPrice
                        
                    if tick.Price < symbolData.bidIceberg:
                        bid_ticket_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_ticket_reset()
                        symbolData.bidIceberg = 0
                        #self.bidreset += 1 #delete
                        
                    if symbolData.askIceberg == 0 and symbolData.askPrice != 0:
                        ask_ticket_reset()
                        symbolData.askIceberg = symbolData.askPrice
                        
                    if tick.Price > symbolData.askIceberg:
                        ask_ticket_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_ticket_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 > 400 and self.askcooldown and self.asklock != symbolData.askIceberg: #and symbolData.askPacman == symbolData.askIceberg:
                    self.BuyFlag = True
                    self.MarketOrder(self.contract.Mapped, 1)
                    self.askcooldown = False
                    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)

                    
                    
                if symbolData.bidCounter > 400 and self.bidcooldown and self.bidlock != symbolData.bidIceberg: # and symbolData.bidPacman == symbolData.bidIceberg:
                    self.BuyFlag = True
                    self.MarketOrder(self.contract.Mapped, -1)
                    self.bidcooldown = False
                    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)

                    
        
    
    def OnEndOfDay(self, symbol):
        #symbolData = self.symbolData[symbol]
        x = 5
        #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


        
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