| 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