Overall Statistics
Total Trades
2071
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
0.316%
Drawdown
0.100%
Expectancy
0.505
Net Profit
0.080%
Sharpe Ratio
1.518
Probabilistic Sharpe Ratio
62.801%
Loss Rate
37%
Win Rate
63%
Profit-Loss Ratio
1.37
Alpha
0.001
Beta
0.006
Annual Standard Deviation
0.001
Annual Variance
0
Information Ratio
-0.808
Tracking Error
0.201
Treynor Ratio
0.366
Total Fees
$4452.65
Estimated Strategy Capacity
$0
Lowest Capacity Asset
ES XZDYPWUWC7I9
#region imports
from datetime import timedelta
from AlgorithmImports import *
#endregion
class RetrospectiveTanButterfly(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 5, 17)  # Set Start Date
        self.SetEndDate(2022, 8, 17)
        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.futureSP500 = self.AddFuture(Futures.Indices.SP500EMini, extendedMarketHours = True)
        #self.futureGold = self.AddFuture(Futures.Metals.Gold, extendedMarketHours = True)

        #future = self.AddFuture(Futures.Indices.SP500EMini , Resolution.Tick, extendedMarketHours = False) 
        #future.SetFilter(0, 90)
        #symbol = future.Symbol
        #continuousContract = [Futures.Indices.SP500EMini]
        #currentContract = self.Securities[symbol.Mapped]
        
        self.symbolData[symbol] = SymbolData()
        self.symbolData[symbol].bidPrice = self.Securities[symbol].BidPrice
        self.symbolData[symbol].askPrice = self.Securities[symbol].AskPrice

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


        #tickers = ["SPY", "QQQ"]
        #for ticker in tickers:
        #    symbol = self.AddEquity(ticker, Resolution.Tick).Symbol
            
        #    self.symbolData[symbol] = SymbolData()
        #    self.symbolData[symbol].bidPrice = self.Securities[symbol].BidPrice
        #    self.symbolData[symbol].askPrice = self.Securities[symbol].AskPrice
            
            
    def OnData(self, data):
        for symbol, symbolData in self.symbolData.items():
            if not data.Ticks.ContainsKey(symbol): continue
            #underlying = symbol.Underlying

            if self.Time.second == 00 or self.Time.second == 30:
                symbolData.buyRollingVolume5 = symbolData.buyRollingVolume4
                symbolData.sellRollingVolume5 = symbolData.sellRollingVolume4

                symbolData.buyRollingVolume4 = symbolData.buyRollingVolume3
                symbolData.sellRollingVolume4 = symbolData.sellRollingVolume3

                symbolData.buyRollingVolume3 = symbolData.buyRollingVolume2
                symbolData.sellRollingVolume3 = symbolData.sellRollingVolume2

                symbolData.buyRollingVolume2 = symbolData.buyRollingVolume1
                symbolData.sellRollingVolume2 = symbolData.sellRollingVolume1

                symbolData.buyRollingVolume1 = 0
                symbolData.sellRollingVolume1 = 0


            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

                elif tick.TickType == TickType.Trade:
                    if tick.Price - symbolData.bidPrice > symbolData.askPrice - tick.Price:
                        symbolData.sellVolume += tick.Quantity
                        symbolData.sellRollingVolume1 += tick.Quantity
                    else:
                        symbolData.buyVolume += tick.Quantity
                        symbolData.buyRollingVolume1 += tick.Quantity
                
                if (symbolData.buyRollingVolume1 + symbolData.buyRollingVolume2 + symbolData.buyRollingVolume3 + symbolData.buyRollingVolume4 + symbolData.buyRollingVolume5) - (symbolData.sellRollingVolume1 + symbolData.sellRollingVolume2 + symbolData.sellRollingVolume3 + symbolData.sellRollingVolume4 + symbolData.sellRollingVolume5) < 5: #and > 5:
                    #self.Log(f"Can Long volume buy Delta: {symbolData.buyIntraVolume - symbolData.sellIntraVolume}")
                    self.canLong = True
                elif (symbolData.sellRollingVolume1 + symbolData.sellRollingVolume2 + symbolData.sellRollingVolume3 + symbolData.sellRollingVolume4 + symbolData.sellRollingVolume5) - (symbolData.buyRollingVolume1 + symbolData.buyRollingVolume2 + symbolData.buyRollingVolume3 + symbolData.buyRollingVolume4 + symbolData.buyRollingVolume5) < 5:
                    #self.Log(f"Can Short volume sell Delta: {symbolData.sellIntraVolume - symbolData.buyIntraVolume}")
                    self.canShort = True


                if (symbolData.buyRollingVolume1 + symbolData.buyRollingVolume2 + symbolData.buyRollingVolume3 + symbolData.buyRollingVolume4 + symbolData.buyRollingVolume5) - (symbolData.sellRollingVolume1 + symbolData.sellRollingVolume2 + symbolData.sellRollingVolume3 + symbolData.sellRollingVolume4 + symbolData.sellRollingVolume5) >= 700 and self.canLong == True:
                    self.Log(f"volume buy Delta: {(symbolData.buyRollingVolume1 + symbolData.buyRollingVolume2 + symbolData.buyRollingVolume3 + symbolData.buyRollingVolume4 + symbolData.buyRollingVolume5) - (symbolData.sellRollingVolume1 + symbolData.sellRollingVolume2 + symbolData.sellRollingVolume3 + symbolData.sellRollingVolume4 + symbolData.sellRollingVolume5)}")
                    self.canLong = False
                    self.MarketOrder(self.contract.Mapped, 1)
                    #self.Buy(symbol, 1)

                elif (symbolData.sellRollingVolume1 + symbolData.sellRollingVolume2 + symbolData.sellRollingVolume3 + symbolData.sellRollingVolume4 + symbolData.sellRollingVolume5) - (symbolData.buyRollingVolume1 + symbolData.buyRollingVolume2 + symbolData.buyRollingVolume3 + symbolData.buyRollingVolume4 + symbolData.buyRollingVolume5) >= 700 and self.canShort == True:
                    self.Log(f"volume sell Delta: {(symbolData.sellRollingVolume1 + symbolData.sellRollingVolume2 + symbolData.sellRollingVolume3 + symbolData.sellRollingVolume4 + symbolData.sellRollingVolume5) - (symbolData.buyRollingVolume1 + symbolData.buyRollingVolume2 + symbolData.buyRollingVolume3 + symbolData.buyRollingVolume4 + symbolData.buyRollingVolume5)}")
                    self.canShort = False
                    self.MarketOrder(self.contract.Mapped, -1)
                    #self.Buy(symbol, -1)
    
    
    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")
        
        symbolData.ClearDay()


        
class SymbolData:
    
    def __init__(self):
        self.buyVolume = 0
        self.sellVolume = 0
        self.buyRollingVolume1 = 0
        self.sellRollingVolume1 = 0
        self.buyRollingVolume2 = 0
        self.sellRollingVolume2 = 0
        self.buyRollingVolume3 = 0
        self.sellRollingVolume3 = 0
        self.buyRollingVolume4 = 0
        self.sellRollingVolume4 = 0
        self.buyRollingVolume5 = 0
        self.sellRollingVolume5 = 0
        self.buyRollingVolume = self.buyRollingVolume1 + self.buyRollingVolume2 + self.buyRollingVolume3 + self.buyRollingVolume4 + self.buyRollingVolume5
        self.sellRollingVolume = self.sellRollingVolume1 + self.sellRollingVolume2 + self.sellRollingVolume3 + self.sellRollingVolume4 + self.sellRollingVolume5
        self.bidPrice = 0
        self.askPrice = 0
        self.canShort = True
        self.canLong = True
        
    def ClearDay(self):
        self.buyVolume = 0
        self.sellVolume = 0

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