Hello all, 

Sorry for dumping the code as is instead of attaching the backtest. The backtest of another project keeps running instead.

Anyways, I'm trying to get familiar with stop market orders and I was wondering if someone would be able to help me with this:

I have a list of stocks as you can see, say:  tickers = ["SPY", "TLT", "BND"]

I want to create a dictionary for stop buys and stop sells, each containing tickers as keys, and can be executed and updated. I am trying to do this with these two dictionaries: self.stopbuys[symbol] and self.stopsells[symbol] , and initializing both with values of None for each ticker. And afterwards be able to update each for each ticker accordingly. Also, I am trying to track the time that each stop market order was FILLED with these two dictionaries: self.stopbuys_time and self.stopsells_time.

This did not execute: 

self.stopbuys[symbol] = self.StopMarketOrder(symbol, shares_to_buy, round(value.window3[0].High, 2)) 

but without assinging the variable to it, it works, like this:

self.StopMarketOrder(symbol, shares_to_buy, round(value.window3[0].High, 2)) 

I don't think the update is working either. Is there a better way of tracking stop market orders for a list of stocks? 

Also, would this be if statement execute on the day a new stop market is ASSIGNED or the day it is FILLED?

if (self.Time - self.stopbuys_time[symbol]).days == 0:
            #   do something

Thanks a bunch, I appreciate it.

 

Code:

class MyAlgorithm(QCAlgorithm):

def Initialize(self):

self.SetStartDate(2019,1,1)
self.SetCash(100000)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
tickers = ["SPY", "TLT", "BND"]

# Creates empty dictionary to later hold daily Tradebar price rolling windows
self.symbolData = {}
# Creates empty dictionary to later hold stop buy values
self.stopbuys = {}
# Creates empty dictionary to later hold stop sell values
self.stopsells = {}
# Creates empty dictionary to later hold time of buy breakout occurrence
self.stopbuys_time = {}
# Creates empty dictionary to later hold time of sell breakout occurrence
self.stopsells_time = {}

for ticker in tickers:

self.equity = self.AddEquity(ticker, Resolution.Hour)
self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.equity.SetLeverage(1.0)


#symbol_window = self.equity.Symbol
symbol = self.equity.Symbol


self.stopbuys[symbol] = None
self.stopsells[symbol] = None

self.stopbuys_time[symbol] = datetime.min
self.stopsells_time[symbol] = datetime.min

# Consolidator
consolidator_daily = TradeBarConsolidator(timedelta(days = 1))
consolidator_daily.DataConsolidated += self.OnDailyData
self.SubscriptionManager.AddConsolidator(symbol, consolidator_daily)
self.symbolData[symbol] = SymbolData(self, symbol)

self.SetWarmUp(1000)


# Adding daily bar data to 3,2,1 etc.. rolling windows
def OnDailyData(self, sender, bar):

self.symbolData[bar.Symbol].window4.Add(bar)
self.symbolData[bar.Symbol].window3.Add(bar)
self.symbolData[bar.Symbol].window2.Add(bar)


def OnData(self, data):

for symbol, value in self.symbolData.items():
if not data.ContainsKey(symbol.Value):
return

for symbol, value in self.symbolData.items():

value.window4.Add(data[symbol.Value])
value.window3.Add(data[symbol.Value])
value.window2.Add(data[symbol.Value])

if self.IsWarmingUp:
return

for symbol, value in self.symbolData.items():
if not (value.window4.IsReady and value.window3.IsReady and value.window2.IsReady):
return

for symbol, value in self.symbolData.items():

shares_to_buy = 50
if value.window3[0].Close > value.window3[1].Close > value.window3[2].Close:
if self.stopbuys[symbol] == None:
#self.stopbuys[symbol] = self.StopMarketOrder(symbol, shares_to_buy, round(value.window3[0].High, 2))
self.StopMarketOrder(symbol, shares_to_buy, round(value.window3[0].High, 2))
else:
updateSettings = UpdateOrderFields()
updateSettings.StopPrice = round(value.window3[0].High, 2)
updateSettings.Quantity = round(shares_to_buy)
updateSettings.Tag = "Stop Buy Updated for {}".format(symbol)
self.stopbuys[symbol].Update(updateSettings)
else:
if self.stopbuys[symbol] == None:
#self.stopsells[symbol] = self.StopMarketOrder(symbol, -self.Portfolio[symbol].Quantity, round(value.window3[0].Low, 2))
self.StopMarketOrder(symbol, -self.Portfolio[symbol].Quantity, round(value.window3[0].Low, 2))
else:
updateSettings = UpdateOrderFields()
updateSettings.StopPrice = round(value.window3[0].Low, 2)
updateSettings.Quantity = -self.Portfolio[symbol].Quantity
updateSettings.Tag = "Stop Sell Updated for {}".format(symbol)
self.stopsells[symbol].Update(updateSettings)

# Is this the time a stop buy was entered or updated ? Or is it the time it was filled??
# How do we get the time a stopbuy was filled instead?
# if (self.Time - self.stopbuys_time[symbol]).days == 0:
# do something

def OnOrderEvent(self, orderEvent):
# Event when the order is filled. Debug log the order fill. :OrderEvent:

#if OrderEvent.FillQuantity == 0:
if orderEvent.Status != OrderStatus.Filled:
return

fetched = self.Transactions.GetOrderById(orderEvent.OrderId)

self.Debug("{} was filled. Symbol: {}. Quantity: {}. Direction: {}"
.format(str(fetched.Type),
str(orderEvent.Symbol),
str(orderEvent.FillQuantity),
str(orderEvent.Direction)))

if self.stopbuys[orderEvent.Symbol] is not None and self.stopbuys[orderEvent.Symbol].OrderId == orderEvent.OrderId:
self.stopbuys_time[orderEvent.Symbol] = self.Time
self.Debug(str(self.stopbuys_time[orderEvent.Symbol]))


class SymbolData:

def __init__(self, algorithm, symbol):

self.algorithm = algorithm
self.symbol = symbol

self.window4 = RollingWindow[TradeBar](4)
self.window3 = RollingWindow[TradeBar](3)
self.window2 = RollingWindow[TradeBar](2)