Hi All, I'm fairly new to QuantConnect, but really enjoying the power it gives me to tailor my algorithms to the detail that I'd want. I'm working on Universe Selection for a trend following strategy right now, and want to do the following:
Filters:
- Average Daily Dollar Volume for last 20 days > $50M
- Price > 5
- SMA(Close, 25) > SMA(Close, 50)
Ranking:
- Rank by highest price percentage increase over last 200 trading days: Close / Close[200]
I have no clue if I'm doing this in the most efficient way. Specifically, I'm pulling history data for every security on a daily basis in order to compute the rank score.
I also realize that since I'm using indicators, I probably need to warm up the data so that I have some values on the start date. I ran SetWarmUp in the Initialize method, but not sure if that data is getting sent to the CoarseFilter method or not. It didn't seem like it was working. Worst case, I don't mind waiting for the indicators to be ready, but I wasn't sure how to make that work with Universe selection either.
Any help to solve the filtering and ranking I'm trying to do in the best way would be greatly appreciated!
Thanks,
Chetan
# region imports
from AlgorithmImports import *
# endregion
class TrendFollowing(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 1, 1) # Set Start Date
self.SetEndDate(2022, 9, 25)
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.stateData = {}
#self.SetWarmUp(50, Resolution.Daily)
self.AddUniverse(self.CoarseFilter)
def CoarseFilter(self, coarse: List[CoarseFundamental]) -> List[Symbol]:
for c in coarse:
if c.Symbol not in self.stateData:
self.stateData[c.Symbol] = SelectionData(c.Symbol, c.HasFundamentalData)
avg = self.stateData[c.Symbol]
try:
price_200 = self.History(c.Symbol, 200, Resolution.Daily)["close"]
avg.update(c.Time, c.Price, c.DollarVolume, price_200[-1])
except:
continue
symbols = [x for x in self.stateData.values() if x.sma_dv_20.Current.Value > 5000000and x.price > 5 and x.has_fundamental_data and x.sma_price_25.Current.Value > x.sma_price_50.Current.Value]
symbols.sort(key=lambda x: x.price_200_ratio, reverse=True)
list_of_symbols = [x.symbol for x in symbols]
return list_of_symbols
def onData(self, data):
pass
class SelectionData(object):
def __init__(self, symbol, has_fundamental_data):
self.symbol = symbol
self.has_fundamental_data = has_fundamental_data
self.price = 0.0
self.price_200_ratio = 0.0
self.sma_dv_20 = SimpleMovingAverage(20)
self.sma_price_25 = SimpleMovingAverage(25)
self.sma_price_50 = SimpleMovingAverage(50)
def update(self, time, price, dollar_volume, price_200):
self.sma_dv_20.Update(time, dollar_volume)
self.sma_price_25.Update(time, price)
self.sma_price_50.Update(time, price)
self.price = price
self.price_200_ratio = price / price_200
Derek Melchin
Hi Chetan,
Instead of making a history request every time CoarseFilter runs, move the history request to the SelectionData constructor to warm up the indicators. We can also replace the `price / price_200` calculation with a Rate Of Change indicator and update it during the update method.
Best,
Derek Melchin
Want to invest in QuantConnect as we build the Linux of quant finance? Check out our Wefunder campaign to join the revolution.
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.
Chetan Prabhu
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!