| Overall Statistics |
|
Total Trades 1111 Average Win 0.00% Average Loss 0.00% Compounding Annual Return -0.021% Drawdown 0.200% Expectancy -0.092 Net Profit -0.042% Sharpe Ratio -0.187 Probabilistic Sharpe Ratio 2.129% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 0.90 Alpha -0 Beta 0.001 Annual Standard Deviation 0.001 Annual Variance 0 Information Ratio -0.368 Tracking Error 0.151 Treynor Ratio -0.125 Total Fees $2388.65 Estimated Strategy Capacity $0 Lowest Capacity Asset NQ 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.NASDAQ100EMini , 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:
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
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
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.askIceberg:
symbolData.askCounter += tick.Quantity
if tick.Price < symbolData.askIceberg * 0.995:
symbolData.askIceberg = 0
symbolData.askCounter = 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 and tick.Time > self.askcooldown: #and symbolData.askPacman == symbolData.askIceberg:
self.MarketOrder(self.contract.Mapped, -1)
self.askcooldown = tick.Time + timedelta(minutes=5)
symbolData.askCounter = 0
symbolData.askIceberg = 0
if symbolData.bidCounter > 100 and tick.Time > self.bidcooldown: # and symbolData.bidPacman == symbolData.bidIceberg:
#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
self.bidSize = 0
self.askSize = 0
self.bidPacman = 0
self.askPacman = 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