Overall Statistics
Total Trades
2177
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
-0.215%
Drawdown
0.500%
Expectancy
-0.476
Net Profit
-0.433%
Sharpe Ratio
-1.133
Probabilistic Sharpe Ratio
0.011%
Loss Rate
66%
Win Rate
34%
Profit-Loss Ratio
0.55
Alpha
-0.002
Beta
0.004
Annual Standard Deviation
0.001
Annual Variance
0
Information Ratio
-0.378
Tracking Error
0.151
Treynor Ratio
-0.366
Total Fees
$4680.55
Estimated Strategy Capacity
$0
Lowest Capacity Asset
ES XKGCMV4QK9VL
#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(2020, 9, 17)  # Set Start Date
        self.SetEndDate(2022, 9, 23)
        self.SetCash(1000000000)  # Set Strategy Cash
        self.symbolData = {}

        self.canLong = True
        self.canShort = True

        #symbol = self.AddSecurity(SecurityType.Future, Futures.Indices.SP500EMini , Resolution.Tick, extendedMarketHours = False, dataNormalizationMode = DataNormalizationMode.BackwardsRatio, dataMappingMode = DataMappingMode.OpenInterest, contractDepthOffset = 0).Symbol
        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)

        
        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.v_price_window = RollingWindow[list()](5)

        #symbol.SetFilter(lambda x: x.FrontMonth().OnlyApplyFilterAtMarketOpen())
        #self.contracts = [symbol]

        self.printonce = True

        #self.SetWarmUp(5)
        self.dfmax = 0
        self.dfmin = 0
        self.volumeBoxReady = False
        self.tickcount = 0

        self.bidCounter = 0
        self.askCounter = 0
        self.bidIceberg = 0
        self.askIceberg = 0
        self.askcooldown = datetime(2000,7,6,10,0,0)
        self.bidcooldown = datetime(2000,7,6,10,0,0)
            
        self.print1 = True
        self.print2 = True
        self.print3 = True
        self.print4 = True

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

        self.tickcount = 0
            
    def OnData(self, data):
        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:
                    #if self.print2:
                    #    self.Debug(f"quote bid price {tick.BidPrice} ask price {tick.AskPrice} tick price {tick.Price}")
                    #    self.print2 = False

                    symbolData.bidPrice = tick.BidPrice if tick.BidPrice != 0 else symbolData.bidPrice
                    symbolData.askPrice = tick.AskPrice if tick.AskPrice != 0 else symbolData.askPrice

                if tick.TickType == TickType.Trade:
                    #if tick.Price - symbolData.bidPrice > symbolData.askPrice - tick.Price:
                    self.tickcount += 1

                    
                    if symbolData.bidIceberg == 0 and symbolData.bidPrice != 0: #fix this logic, how do i know if its a ask ice or bid ice
                        symbolData.bidIceberg = symbolData.bidPrice
                        symbolData.bidCounter = 0
                    if tick.Price < symbolData.bidIceberg:
                        symbolData.bidIceberg = tick.Price
                        symbolData.bidCounter = 0
                        self.pricelreset += 1
                        #self.Log(f"price l reset time->: {tick.Time}")
                    #if tick.Price == symbolData.bidPrice and tick.Price == symbolData.bidIceberg:
                    if tick.Price == symbolData.bidIceberg:
                        symbolData.bidCounter += tick.Quantity
                    if tick.Price > symbolData.bidIceberg / 0.995:
                        symbolData.bidIceberg = 0
                        symbolData.bidCounter = 0
                        self.bidreset += 1 #delete

                    if symbolData.askIceberg == 0 and symbolData.askPrice != 0:
                        symbolData.askIceberg = symbolData.askPrice
                        symbolData.askCounter = 0
                    if tick.Price > symbolData.askIceberg:
                        symbolData.askIceberg = tick.Price
                        symbolData.askCounter = 0
                        self.pricehreset += 1
                    #if tick.Price == symbolData.askPrice and tick.Price == symbolData.askIceberg:
                    if tick.Price == symbolData.askIceberg:
                        symbolData.askCounter += tick.Quantity
                    if tick.Price < symbolData.askIceberg * 0.995:
                        symbolData.askIceberg = 0
                        symbolData.askCounter = 0
                        self.askreset += 1 #delete

                    #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.bidPrice > 10 and self.print1:
                #    self.Log(f"symbol bid price {symbolData.bidPrice}")
                #    self.print1 = False
                #if symbolData.askPrice > 10 and self.print2:
                #    self.Log(f"symbol ask price {symbolData.askPrice}")
                #    self.print2 = False
                #if symbolData.bidIceberg > 10 and self.print3:
                #    self.Log(f"symbol bid ice {symbolData.bidIceberg}")
                #    self.print3 = False
                #if symbolData.askIceberg > 10 and self.print4:
                #    self.Log(f"symbol ask ice {symbolData.askIceberg}")
                #    self.print4 = False

                #add oneshot logic when askcooldown ends:
                    


                if symbolData.askCounter > 700 and tick.Time > self.askcooldown:
                    self.MarketOrder(self.contract.Mapped, -1)
                    self.askcooldown = tick.Time + timedelta(minutes=5)
                    symbolData.askCounter = 0
                    symbolData.askIceberg = 0

                if symbolData.bidCounter > 700 and tick.Time > self.bidcooldown:
                    #self.Log(f"{test}")
                    self.MarketOrder(self.contract.Mapped, 1)
                    self.bidcooldown = tick.Time + timedelta(minutes=5)
                    symbolData.bidCounter = 0
                    symbolData.bidIceberg = 0

            #self.MarketOrder(self.contract.Mapped, -1)
                
                """tick_df = self.PandasConverter.GetDataFrame[Tick](self.volume_window)"""


    
    
    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
        symbolData.ClearDay()

        
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

        
    def ClearDay(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

    def ClearIntra(self):
        self.buyIntraVolume = 0
        self.sellIntraVolume = 0