| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
# region imports
from AlgorithmImports import *
# endregion
class HyperActiveOrangeCat(QCAlgorithm):
def Initialize(self):
# Backtesting / Papertrading parameters if necessary
self.SetCash(100000)
self.SetStartDate(2022, 11, 11)
self.SetEndDate(2022, 11, 11)
# Request ES data with tick resolution, filter for expirations in between 5 and 100 days
self.es = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Tick)
self.es.SetFilter(5, 100)
# Variables for both short and long entry and exit tickets, trade cooldowns, prices for trailing stops and cancellations, and contracts per trade
# !!! EXHIBIT EXTREME CAUTION USING LEVERAGE ; MANUALLY MANAGE CONTRACT QUANTITY
self.longEntryTicket = None
self.shortEntryTicket = None
self.longExitTicket = None
self.shortExitTicket = None
self.liquidateTicket = None
self.exitFillTime = datetime.min
self.cancelTime = datetime.min
self.triggerPrice = 0
self.highestPrice = 0
self.lowestPrice = 25000
self.qty = 1
# Variables for price levels
# ! Intended to be updated daily, ensure correct futures contract prices
# Daily Support and Resistance price levels
self.resi6 = 0
self.resi5 = 0
self.resi4 = 0
self.resi3 = 0
self.resi2 = 0
self.resi1 = 0
self.supp1 = 0
self.supp2 = 0
self.supp3 = 0
self.supp4 = 0
self.supp5 = 0
self.supp6 = 0
# Dynamic price levels {e.g. previous day low, overnight high, etc.}
self.dyna1 = 0
self.dyna2 = 0
self.dyna3 = 0
self.dyna4 = 0
self.dyna5 = 0
# Macroenvironment price levels
self.macr1 = 0
self.macr2 = 0
self.macr3 = 0
# Multiples of one-hundred
self.hund1 = 0
self.hund2 = 0
self.hund3 = 0
# Miscellaneous price levels
self.misc1 = 0
self.misc2 = 0
self.misc3 = 0
# Variables to halt entries, cancel open entry orders, and liquidate positions around major news events {intended to be updated daily}
# Variables to ensure no entries occur outside of RTH
self.event1Start = self.Time.replace(hour=1, minute=30, second=0)
self.event1End = self.Time.replace(hour=1, minute=30, second=0)
self.event2Start = self.Time.replace(hour=1, minute=30, second=0)
self.event2End = self.Time.replace(hour=1, minute=30, second=0)
self.stopPreM = self.Time.replace(hour=9, minute=32, second=59)
self.stopAftM = self.Time.replace(hour=15, minute=55, second=59)
def OnData(self, slice):
# Sort contracts for highest Open Interest and create a variable for the highest OI
for chain in slice.FutureChains:
self.popularContracts = [contract for contract in chain.Value if contract.OpenInterest > 1000]
if len(self.popularContracts) == 0:
continue
sortedByOIContracts = sorted(self.popularContracts, key=lambda k : k.OpenInterest, reverse=True)
self.liquidContract = sortedByOIContracts[0]
# Variable for liquid contract price
price = self.Securities[self.liquidContract.Symbol].Price
# Enable 30sec cooldown between exit fills and entry submissions, 15sec cooldown between cancellations and entry submissions
if (self.Time - self.exitFillTime).seconds <= 30 or (self.Time - self.cancelTime).seconds <= 15:
return
# Submit entry order if there are no positions or open orders and time conditions are met
if not self.Portfolio.Invested and not self.Transactions.GetOpenOrders(self.liquidContract.Symbol) and not self.Time < self.stopPreM and not self.Time > self.stopAftM and not self.event1Start < self.Time < self.event1End and not self.event2Start < self.Time < self.event2End:
# Long entry, submit if price comes within 1.5 points above a level
if self.resi6 + 1.5 >= price > self.resi6 or self.resi5 + 1.5 >= price > self.resi5 or self.resi4 + 1.5 >= price > self.resi4 or self.resi3 + 1.5 >= price > self.resi3 or self.resi2 + 1.5 >= price > self.resi2 or self.resi1 + 1.5 >= price > self.resi1 or self.supp6 + 1.5 >= price > self.supp6 or self.supp5 + 1.5 >= price > self.supp5 or self.supp4 + 1.5 >= price > self.supp4 or self.supp3 + 1.5 >= price > self.supp3 or self.supp2 + 1.5 >= price > self.supp2 or self.supp1 + 1.5 >= price > self.supp1 or self.dyna1 + 1.5 >= price > self.dyna1 or self.dyna2 + 1.5 >= price > self.dyna2 or self.dyna3 + 1.5 >= price > self.dyna3 or self.dyna4 + 1.5 >= price > self.dyna4 or self.dyna5 + 1.5 >= price > self.dyna5 or self.macr1 + 1.5 >= price > self.macr1 or self.macr2 + 1.5 >= price > self.macr2 or self.macr3 + 1.5 >= price > self.macr3 or self.hund1 + 1.5 >= price > self.hund1 or self.hund2 + 1.5 >= price > self.hund2 or self.hund3 + 1.5 >= price > self.hund3 or self.misc1 + 1.5 >= price > self.misc1 or self.misc2 + 1.5 >= price > self.misc2 or self.misc3 + 1.5 >= price > self.misc3:
self.longEntryTicket = self.StopMarketOrder(self.liquidContract.Symbol, self.qty, price + 1.25)
# Save price at submission time
self.triggerPrice = price
# Short entry, submit if price comes within 1.5 points below a level
if self.resi6 - 1.5 <= price < self.resi6 or self.resi5 - 1.5 <= price < self.resi5 or self.resi4 - 1.5 <= price < self.resi4 or self.resi3 - 1.5 <= price < self.resi3 or self.resi2 - 1.5 <= price < self.resi2 or self.resi1 - 1.5 <= price < self.resi1 or self.supp6 - 1.5 <= price < self.supp6 or self.supp5 - 1.5 <= price < self.supp5 or self.supp4 - 1.5 <= price < self.supp4 or self.supp3 - 1.5 <= price < self.supp3 or self.supp2 - 1.5 <= price < self.supp2 or self.supp1 - 1.5 <= price < self.supp1 or self.dyna1 - 1.5 <= price < self.dyna1 or self.dyna2 - 1.5 <= price < self.dyna2 or self.dyna3 - 1.5 <= price < self.dyna3 or self.dyna4 - 1.5 <= price < self.dyna4 or self.dyna5 - 1.5 <= price < self.dyna5 or self.macr1 - 1.5 <= price < self.macr1 or self.macr2 - 1.5 <= price < self.macr2 or self.macr3 - 1.5 <= price < self.macr3 or self.hund1 - 1.5 <= price < self.hund1 or self.hund2 - 1.5 <= price < self.hund2 or self.hund3 - 1.5 <= price < self.hund3 or self.misc1 - 1.5 <= price < self.misc1 or self.misc2 - 1.5 <= price < self.misc2 or self.misc3 - 1.5 <= price < self.misc3:
self.shortEntryTicket = self.StopMarketOrder(self.liquidContract.Symbol, -self.qty, price - 1.25)
# Save price at submission for cancellation
self.triggerPrice = price
# Trailing stop and possible cancellation if a long entry order is open
if self.longEntryTicket is not None and self.longEntryTicket.Status != OrderStatus.Filled:
# Trailing stop
if price < self.lowestPrice:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 1.25
self.longEntryTicket.Update(updateFields)
# Cancel order and save time if price is not rejecting the level
if price <= self.triggerPrice - 4:
self.longEntryTicket.Cancel()
self.cancelTime = self.Time
# Cancel order and save time if time nears end of RTH or news/data event
if self.Time > self.stopAftM or self.event1Start < self.Time < self.event1End or self.event2Start < self.Time < self.event2End:
self.longEntryTicket.Cancel()
self.cancelTime = self.Time
# Reset long entry ticket, lowest price, and trigger price variables if order is canceled
if self.longEntryTicket.Status == OrderStatus.Canceled:
self.longEntryTicket = None
self.lowestPrice = 25000
self.triggerPrice = 0
# Trailing stop and possible cancellation if a short entry order is open
if self.shortEntryTicket is not None and self.shortEntryTicket.Status != OrderStatus.Filled:
# Trailing stop
if price > self.highestPrice:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 1.25
self.shortEntryTicket.Update(updateFields)
# Cancel order and save time if price is not rejecting the level
if price >= self.triggerPrice + 4:
self.shortEntryTicket.Cancel()
self.cancelTime = self.Time
# Cancel order and save time if time nears end of RTH or news/data event
if self.Time > self.stopAftM or self.event1Start < self.Time < self.event1End or self.event2Start < self.Time < self.event2End:
self.shortEntryTicket.Cancel()
self.cancelTime = self.Time
# Reset long entry ticket, lowest price, and trigger price variables if order is canceled
if self.shortEntryTicket.Status == OrderStatus.Canceled:
self.shortEntryTicket = None
self.highestPrice = 25000
self.triggerPrice = 0
# Trailing stop and possible cancellation and liquidation if a long closing order is open
if self.longExitTicket is not None and self.Portfolio.Invested:
# Trailing stop which updates as the position moves favorably
if price > self.highestPrice and price < self.longEntryTicket.AverageFillPrice + 1.25:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 1.75
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 1.25 <= price < self.longEntryTicket.AverageFillPrice + 3.5:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 2.25
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 3.5 <= price < self.longEntryTicket.AverageFillPrice + 6:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 3
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 6 <= price < self.longEntryTicket.AverageFillPrice + 8:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 4
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 8 <= price < self.longEntryTicket.AverageFillPrice + 11.5:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 5.75
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 11.5 <= price < self.longEntryTicket.AverageFillPrice + 17.5:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 7.75
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 17.5 <= price < self.longEntryTicket.AverageFillPrice + 23:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 9
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 23 <= price < self.longEntryTicket.AverageFillPrice + 30:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 11.5
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 30 <= price < self.longEntryTicket.AverageFillPrice + 40:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 14
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 40 <= price < self.longEntryTicket.AverageFillPrice + 50:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 20
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 50 <= price < self.longEntryTicket.AverageFillPrice + 70:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 18
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 70 <= price < self.longEntryTicket.AverageFillPrice + 80:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 13
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 80 <= price < self.longEntryTicket.AverageFillPrice + 90:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 8
self.longExitTicket.Update(updateFields)
if price > self.highestPrice and self.longEntryTicket.AverageFillPrice + 90 <= price:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price - 5
self.longExitTicket.Update(updateFields)
# Liquidate position on news/data event and reset relevant variables
if self.event1Start < self.Time < self.event1End or self.event2Start < self.Time < self.event2End:
self.longExitTicket.Cancel()
if self.longExitTicket.Status == OrderStatus.Canceled:
self.liquidateTicket = self.MarketOrder(self.liquidContract.Symbol, -self.qty)
self.longEntryTicket = None
self.longExitTicket = None
self.highestPrice = 0
# Trailing stop and possible cancellation and liquidation if a short closing order is open
if self.shortExitTicket is not None and self.Portfolio.Invested:
# Trailing stop which updates as the position moves favorably
if price < self.lowestPrice and price > self.shortEntryTicket.AverageFillPrice - 1.25:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 1.75
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 1.25 >= price > self.shortEntryTicket.AverageFillPrice - 3.5:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 2.25
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 3.5 >= price > self.shortEntryTicket.AverageFillPrice - 6:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 3
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 6 >= price > self.shortEntryTicket.AverageFillPrice - 8:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 4
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 8 >= price > self.shortEntryTicket.AverageFillPrice - 11.5:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 5.75
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 11.5 >= price > self.shortEntryTicket.AverageFillPrice - 17.5:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 7.75
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 17.5 >= price > self.shortEntryTicket.AverageFillPrice - 23:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 9
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 23 >= price > self.shortEntryTicket.AverageFillPrice - 30:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 11.5
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 30 >= price > self.shortEntryTicket.AverageFillPrice - 40:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 14
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 40 >= price > self.shortEntryTicket.AverageFillPrice - 50:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 20
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 50 >= price > self.shortEntryTicket.AverageFillPrice - 70:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 18
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 70 >= price > self.shortEntryTicket.AverageFillPrice - 80:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 13
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 80 >= price > self.shortEntryTicket.AverageFillPrice - 90:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 8
self.shortExitTicket.Update(updateFields)
if price < self.lowestPrice and self.shortEntryTicket.AverageFillPrice - 90 >= price:
self.lowestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price + 5
self.shortExitTicket.Update(updateFields)
# Liquidate position on news/data event and reset relevant variables
if self.event1Start < self.Time < self.event1End or self.event2Start < self.Time < self.event2End:
self.shortExitTicket.Cancel()
if self.shortExitTicket.Status == OrderStatus.Canceled:
self.liquidateTicket = self.MarketOrder(self.liquidContract.Symbol, self.qty)
self.shortEntryTicket = None
self.shortExitTicket = None
self.lowestPrice = 25000
def OnOrderEvent(self, orderEvent):
if orderEvent.Status != OrderStatus.Filled:
return
# Submit long exit order when long entry is filled
if self.longEntryTicket is not None and self.Portfolio.Invested:
self.longExitTicket = self.StopMarketOrder(self.liquidContract.Symbol, -self.qty, self.longEntryTicket.AverageFillPrice - 1.75)
# Reset price variables
self.triggerPrice = 0
self.highestPrice = 0
self.lowestPrice = 25000
# Submit short exit order when short entry is filled
if self.shortEntryTicket is not None and self.Portfolio.Invested:
self.shortExitTicket = self.StopMarketOrder(self.liquidContract.Symbol, self.qty, self.shortEntryTicket.AverageFillPrice + 1.75)
# Reset price variables
self.triggerPrice = 0
self.highestPrice = 0
self.lowestPrice = 25000
# Save time and reset price and ticket variables when a long exit order fills:
if self.longExitTicket is not None and self.longExitTicket.OrderId == orderEvent.OrderId:
self.exitFillTime = self.Time
self.longEntryTicket = None
self.longExitTicket = None
self.highestPrice = 0
self.lowestPrice = 25000
# Save time and reset price and ticket variables when a short exit order fills:
if self.shortExitTicket is not None and self.shortExitTicket.OrderId == orderEvent.OrderId:
self.exitFillTime = self.Time
self.shortEntryTicket = None
self.shortExitTicket = None
self.highestPrice = 0
self.lowestPrice = 25000