I've set up a universe and some filters and was wondering how I would go about replacing the symbol for "SPY" with the results of the filter
import numpy as np
class MyCoarseUniverseAlgorithm(QCAlgorithm):
def Initialize(self):
self.AddUniverse(self.MyCoarseFilterFunction)
self.UniverseSettings.Resolution = Resolution.Daily
self.SetStartDate(2020, 6, 10)
self.SetCash(100000)
self.lookback = 20
self.ceiling, self.floor = 30, 10
self.initialStopRisk = 0.98
self.trailingStopRisk = 0.9
self.Schedule.On(self.DateRules.EveryDay(self.symbol), \
self.TimeRules.AfterMarketOpen(self.symbol, 20), \
Action(self.EveryMarketOpen))
self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
def MyCoarseFilterFunction(self, coarse):
pass
# setup state storage in initialize method
class SelectionData(object):
def __init__(self, symbol, period):
self.volume = 0
self.symbol = symbol
self.ema = ExponentialMovingAverage(period)
self.is_above_ema = False
def update(self, time, price, volume):
self.volume = volume
if self.ema.Update(time, price):
self.is_above_ema = price > ema
def MyCoarseFilterFunction(self, coarse):
# We are going to use a dictionary to refer the object that will keep the moving averages
for c in coarse:
if c.Symbol not in self.stateData:
self.stateData[c.Symbol] = SelectionData(c.Symbol, 200)
# Updates the SymbolData object with current EOD price
avg = self.stateData[c.Symbol]
avg.update(c.EndTime, c.AdjustedPrice, c.DollarVolume)
# Filter the values of the dict to those above EMA and more than $1B vol.
values = [x for x in self.stateData.values() if x.is_above_ema and x.volume > 1000000000]
# sort by the largest in volume.
values.sort(key=lambda x: x.volume, reverse=True)
# we need to return only the symbol objects
return [ x.symbol for x in values[:10] ]
def OnData(self, data):
# Plot security's price
self.Plot("Data Chart", self.symbol, self.Securities[self.symbol].Close)
def EveryMarketOpen(self):
# Dynamically determine lookback length based on 30 day volatility change rate
close = self.History(self.symbol, 31, Resolution.Daily)["close"]
todayvol = np.std(close[1:31])
yesterdayvol = np.std(close[0:30])
deltavol = (todayvol - yesterdayvol) / todayvol
self.lookback = round(self.lookback * (1 + deltavol))
# Account for upper/lower limit of lockback length
if self.lookback > self.ceiling:
self.lookback = self.ceiling
elif self.lookback < self.floor:
self.lookback = self.floor
# List of daily highs
self.high = self.History(self.symbol, self.lookback, Resolution.Daily)["high"]
# Buy in case of breakout
if not self.Securities[self.symbol].Invested and \
self.Securities[self.symbol].Close >= max(self.high[:-1]):
self.SetHoldings(self.symbol, 1)
self.breakoutlvl = max(self.high[:-1])
self.highestPrice = self.breakoutlvl
# Create trailing stop loss if invested
if self.Securities[self.symbol].Invested:
# If no order exists, send stop-loss
if not self.Transactions.GetOpenOrders(self.symbol):
self.stopMarketTicket = self.StopMarketOrder(self.symbol, \
-self.Portfolio[self.symbol].Quantity, \
self.initialStopRisk * self.breakoutlvl)
# Check if the asset's price is higher than highestPrice & trailing stop price not below initial stop price
if self.Securities[self.symbol].Close > self.highestPrice and \
self.initialStopRisk * self.breakoutlvl < self.Securities[self.symbol].Close * self.trailingStopRisk:
# Save the new high to highestPrice
self.highestPrice = self.Securities[self.symbol].Close
# Update the stop price
updateFields = UpdateOrderFields()
updateFields.StopPrice = self.Securities[self.symbol].Close * self.trailingStopRisk
self.stopMarketTicket.Update(updateFields)
# Print the new stop price with Debug()
self.Debug(updateFields.StopPrice)
# Plot trailing stop's price
self.Plot("Data Chart", "Stop Price", self.stopMarketTicket.Get(OrderField.StopPrice))
Caio Navarro
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!