Skip to content

Instantly share code, notes, and snippets.

@ipl31
Created March 13, 2020 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ipl31/10a3fa9622fe1fbf3ea1d8e360130e1e to your computer and use it in GitHub Desktop.
Save ipl31/10a3fa9622fe1fbf3ea1d8e360130e1e to your computer and use it in GitHub Desktop.
Quant Connect Shareholder Yield Strategy
""" Shareholder Yield Algo.
This is for learning the QuantConnect Algo Framework. I don't expect it to be useful outside of that.
The goal of this algo is:
- create a universe of liquid stocks with the best share holder yield (dividends + buybacks) relative to the market.
- buy an equal weighted portfolio of these stocks.
- rebalance monthly based on share holder yield.
Classes:
- ShareHolderYieldAlgo() is the main class that configures and instantiates the QuantConnect algo framework.
- LiquidTotalYieldUniverseSelectionModel() is a class which creates a liquid universe of stocks ranking by
dollar volume, then filters the list down for the top X yielders based on share holder yield.
- LongShareHolderYieldAlphaModel() is an alpha model class which emits buy and sell signals based on changes
to the universe selection.
"""
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
class ShareHolderYieldAlgo(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2005, 1, 1) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverseSelection(LiquidTotalYieldUniverseSelectionModel())
self.AddAlpha(LongShareHolderYieldAlphaModel())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
class LiquidTotalYieldUniverseSelectionModel(FundamentalUniverseSelectionModel):
def __init__(self):
super().__init__(True, None, None)
self.lastMonth = -1
# Use this to determined how many stocks we take off the dollar volume sorted list.
self.dollarVolumeListSize = 200
# Number of securities to select and return from universe.
self.selectionSize = 10
def SelectCoarse(self, algorithm, coarse):
if self.lastMonth == algorithm.Time.month:
return Universe.Unchanged
self.lastMonth = algorithm.Time.month
sortedByDollarVolume = sorted([x for x in coarse if x.HasFundamentalData],
key=lambda x: x.DollarVolume, reverse=True)
return [x.Symbol for x in sortedByDollarVolume[:self.dollarVolumeListSize]]
def SelectFine(self, algorithm, fine):
sortedByYields = sorted(fine, key=lambda f: f.ValuationRatios.TotalYield, reverse=True)
universe = sortedByYields[:self.selectionSize]
return [f.Symbol for f in universe]
class LongShareHolderYieldAlphaModel(AlphaModel):
def __init__(self):
self.insights = []
self.lastMonth = -1
def Update(self, algorithm, data):
if self.lastMonth == algorithm.Time.month:
return []
self.lastMonth = algorithm.Time.month
# should I return an empty list if there have been no changes?
# Or is it ok to return the same insights again?
return self.insights
def OnSecuritiesChanged(self, algorithm, changes):
added = [x for x in changes.AddedSecurities]
removed = [x for x in changes.RemovedSecurities]
changedInsights = []
for security in added:
changedInsights.append(Insight.Price(security.Symbol, timedelta(28), InsightDirection.Up))
for security in removed:
changedInsights.append(Insight.Price(security.Symbol, timedelta(28), InsightDirection.Flat))
self.insights = changedInsights
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment