diff --git a/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/05 Chain Fundamental and Alternative Data.html b/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/05 Chain Fundamental and Alternative Data.html
index 13211630a6..c6a7a405a7 100644
--- a/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/05 Chain Fundamental and Alternative Data.html
+++ b/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/05 Chain Fundamental and Alternative Data.html
@@ -7,90 +7,96 @@
QuiverCNBCsUniverse alternative universe
- . It first selects the 100 most liquid US Equities and then filters them down to those mentioned by CNBC commentator/trader Jim Cramer. The output of the alternative universe selection method is the output of the chained universe.
+ . It stores every US Equity fundamental, intersects them with the names CNBC commentator Jim Cramer mentions, and trades the 100 most liquid intersection members each morning.
public class ChainedUniverseAlgorithm : QCAlgorithm
{
- private List<Symbol> _fundamental = new();
+ private List<Fundamental> _fundamental = [];
+ private Universe _universe;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(100000);
-
- // Filter the top 100 liquid equities of the last trading day, and save the symbols for the next filtering.
+ Settings.SeedInitialPrices = true;
+ UniverseSettings.Resolution = Resolution.Minute;
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Filter the equities being commented on by CNBC analyst Cramer, then select the ones that intersect with the fundamental universe.
- AddUniverse<QuiverCNBCsUniverse>(altCoarse =>
+ // Second universe: equities mentioned by Cramer, ranked by dollar volume.
+ _universe = AddUniverse<QuiverCNBCsUniverse>(altCoarse =>
{
- var followers = from d in altCoarse.OfType<QuiverCNBCsUniverse>()
- where d.Traders.ToLower().Contains("cramer")
- select d.Symbol;
- return _fundamental.Intersect(followers);
+ var alt = altCoarse.OfType<QuiverCNBCsUniverse>()
+ .Where(d => d.Traders.ToLower().Contains("cramer"))
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
+ // Rebalance before market open to trade today's intersection.
+ Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance);
}
- public override void OnSecuritiesChanged(SecurityChanges changes)
- {
- // Request CNBC data for the selected stocks.
- foreach (var added in changes.AddedSecurities)
- {
- AddData<QuiverCNBCs>(added.Symbol);
- }
- }
-
- public override void OnData(Slice data)
+ private void Rebalance()
{
- foreach (var dataPoint in data.Get<QuiverCNBCs>().SelectMany(x=> x.Value.OfType<QuiverCNBC>()))
+ if (_universe.Selected.Count == 0)
{
- Debug($"{dataPoint.Symbol} traders at {data.Time}: {dataPoint.Traders}");
+ return;
}
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
+ var targets = _universe.Selected
+ .Select(symbol => new PortfolioTarget(symbol, weight))
+ .ToList();
+ SetHoldings(targets, true);
}
}
from AlgorithmImports import *
+
class ChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100000)
- self.add_universe(self._fundamental_filter_function)
- self.add_universe(QuiverCNBCsUniverse, self._mad_money_selection)
-
- def _fundamental_filter_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
- # Filter the top 100 liquid equities of the last trading day, and save the symbols for the next filtering.
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume, reverse=True)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[:100]]
+ self.settings.seed_initial_prices = True
+ self.universe_settings.resolution = Resolution.MINUTE
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
+ self.add_universe(self._fundamental_filter)
+ # Second universe: equities mentioned by Cramer, ranked by dollar volume.
+ self._universe = self.add_universe(QuiverCNBCsUniverse, self._select_assets)
+ # Rebalance before market open to trade today's intersection.
+ self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(9, 0, 0), self._rebalance)
+
+ def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
+ self._fundamental = fundamental
return Universe.UNCHANGED
-
- def _mad_money_selection(self, alt_coarse: List[QuiverCNBCsUniverse]) -> List[Symbol]:
- # Filter the equities being commented on by CNBC analyst Cramer, then select the ones that intersect with the fundamental universe.
- madmoney = [d.symbol for d in alt_coarse if 'Cramer' in d.traders]
- return list(set(self._fundamental) & set(madmoney))
-
- def on_securities_changed(self, changes: SecurityChanges) -> None:
- # Request CNBC data for the selected stocks.
- for added in changes.added_securities:
- self.add_data(QuiverCNBCs, added.symbol)
-
- def on_data(self, data: Slice) -> None:
- # Prices in the slice from the universe selection
- # Alternative data in a slice from OnSecuritiesChanged Addition
- # for ticker,bar in data.bars.items():
- # pass
- for dataset_symbol, data_points in data.get(QuiverCNBCs).items():
- for data_point in data_points:
- self.debug(f"{dataset_symbol} traders at {data.time}: {data_point.traders}")
+
+ def _select_assets(self, alt_coarse: List[QuiverCNBCsUniverse]) -> List[Symbol]:
+ # Keep symbols mentioned by Cramer.
+ alt = {d.symbol for d in alt_coarse if 'cramer' in d.traders.lower()}
+ self.plot('Universe', 'Raw', len(alt))
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
+
+ def _rebalance(self) -> None:
+ if not self._universe.selected:
+ return
+ weight = min(1 / len(self._universe.selected), 0.1)
+ targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
+ self.set_holdings(targets, True)
diff --git a/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/08 Chain ETF and Alternative Data.html b/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/08 Chain ETF and Alternative Data.html
index 0db2580561..85d50261b6 100644
--- a/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/08 Chain ETF and Alternative Data.html
+++ b/03 Writing Algorithms/12 Universes/03 Equity/04 Chained Universes/08 Chain ETF and Alternative Data.html
@@ -7,90 +7,98 @@
QuiverCNBCsUniverse alternative universe
- . It first selects all constituents of SPY and then filters them down to those mentioned by CNBC commentator/trader Jim Cramer. The output of the alternative universe selection method is the output of the chained universe.
+ . It stores every SPY constituent, intersects them with the names CNBC commentator Jim Cramer mentions, and trades the 100 heaviest-weighted intersection members each morning. Names CNBC mentions but that aren't in SPY are dropped.
public class ChainedUniverseAlgorithm : QCAlgorithm
{
- private List<Symbol> _etf = new();
+ private List<ETFConstituentUniverse> _etf = [];
+ private Universe _universe;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(100000);
- UniverseSettings.Asynchronous = true;
-
- // Save all SPY constituents for the next filtering.
+ Settings.SeedInitialPrices = true;
+ UniverseSettings.Resolution = Resolution.Minute;
+ // First universe: store all SPY constituents; emits Universe.Unchanged.
AddUniverse(Universe.ETF("SPY", Market.USA, UniverseSettings, constituents =>
{
- _etf = constituents.Select(c => c.Symbol).ToList();
+ _etf = [..constituents];
return Universe.Unchanged;
}));
- // Filter the equities being commented on by CNBC analyst Cramer, then select the ones in SPY constituents.
- AddUniverse<QuiverCNBCsUniverse>(altCoarse =>
+ // Second universe: equities mentioned by Cramer that are in SPY, ranked by ETF weight.
+ _universe = AddUniverse<QuiverCNBCsUniverse>(altCoarse =>
{
- var followers = from d in altCoarse.OfType<QuiverCNBCsUniverse>()
- where d.Traders.ToLower().Contains("cramer")
- select d.Symbol;
- return _etf.Intersect(followers);
+ var alt = altCoarse.OfType<QuiverCNBCsUniverse>()
+ .Where(d => d.Traders.ToLower().Contains("cramer"))
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ // Names not in SPY cannot be traded, so intersect with the ETF list.
+ return _etf
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.Weight)
+ .Select(c => c.Symbol)
+ .Take(100);
});
+ // Rebalance before market open to trade today's intersection.
+ Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance);
}
- public override void OnSecuritiesChanged(SecurityChanges changes)
- {
- // Request CNBC data for the selected stocks.
- foreach (var added in changes.AddedSecurities)
- {
- AddData<QuiverCNBCs>(added.Symbol);
- }
- }
-
- public override void OnData(Slice data)
+ private void Rebalance()
{
- foreach (var dataPoint in data.Get<QuiverCNBCs>().SelectMany(x=> x.Value.OfType<QuiverCNBC>()))
+ if (_universe.Selected.Count == 0)
{
- Debug($"{dataPoint.Symbol} traders at {data.Time}: {dataPoint.Traders}");
+ return;
}
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
+ var targets = _universe.Selected
+ .Select(symbol => new PortfolioTarget(symbol, weight))
+ .ToList();
+ SetHoldings(targets, true);
}
}
from AlgorithmImports import *
+
class ChainedUniverseAlgorithm(QCAlgorithm):
- _etf = []
+ _etf: List[ETFConstituentUniverse] = []
- def initialize(self):
+ def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100000)
- self.universe_settings.asynchronous = True
- # Save all SPY constituents for the next filtering.
- self.add_universe(self.universe.etf("SPY", Market.USA, self.universe_settings, self._etf_constituents_filter))
- # Next filtering based on CNBC data.
- self.add_universe(QuiverCNBCsUniverse, self._mad_money_selection)
+ self.settings.seed_initial_prices = True
+ self.universe_settings.resolution = Resolution.MINUTE
+ # First universe: store all SPY constituents; emits Universe.UNCHANGED.
+ self.add_universe(self.universe.etf("SPY", Market.USA, self.universe_settings, self._etf_filter))
+ # Second universe: equities mentioned by Cramer that are in SPY, ranked by ETF weight.
+ self._universe = self.add_universe(QuiverCNBCsUniverse, self._select_assets)
+ # Rebalance before market open to trade today's intersection.
+ self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(9, 0, 0), self._rebalance)
- def _etf_constituents_filter(self, fundamental: List[Fundamental]) -> List[Symbol]:
- # Save all SPY constituents for the next filtering.
- self._etf = [c.symbol for c in constituents]
+ def _etf_filter(self, constituents: List[ETFConstituentUniverse]) -> Universe.UnchangedUniverse:
+ self._etf = constituents
return Universe.UNCHANGED
- def _mad_money_selection(self, alt_coarse: List[QuiverCNBCsUniverse]) -> List[Symbol]:
- # Filter the equities being commented on by CNBC analyst Cramer, then select the ones in SPY constituents.
- madmoney = [d.symbol for d in alt_coarse if 'Cramer' in d.traders]
- return list(set(self._etf) & set(madmoney))
-
- def on_securities_changed(self, changes):
- # Request CNBC data for the selected stocks.
- for added in changes.added_securities:
- self.add_data(QuiverCNBCs, added.symbol)
+ def _select_assets(self, alt_coarse: List[QuiverCNBCsUniverse]) -> List[Symbol]:
+ # Keep symbols mentioned by Cramer.
+ alt = {d.symbol for d in alt_coarse if 'cramer' in d.traders.lower()}
+ self.plot('Universe', 'Raw', len(alt))
+ # Names not in SPY cannot be traded, so intersect with the ETF list.
+ return [c.symbol for c in sorted(
+ [c for c in self._etf if c.symbol in alt],
+ key=lambda c: c.weight, reverse=True
+ )[:100]]
- def on_data(self, data):
- # Prices in the slice from the universe selection
- # Alternative data in a slice from OnSecuritiesChanged Addition
- # for ticker,bar in data.bars.items():
- # pass
- for dataset_symbol, data_points in data.get(QuiverCNBCs).items():
- for data_point in data_points:
- self.debug(f"{dataset_symbol} traders at {data.time}: {data_point.traders}")
+ def _rebalance(self) -> None:
+ if not self._universe.selected:
+ return
+ weight = min(1 / len(self._universe.selected), 0.1)
+ targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
+ self.set_holdings(targets, True)
+
diff --git a/project-templates/csharp/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/Main.cs b/project-templates/csharp/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/Main.cs
index 9fc8ef096b..d5308057ca 100644
--- a/project-templates/csharp/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class BrainCompanyFilingLanguageMetricsChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = [];
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -19,23 +19,28 @@ public override void Initialize()
SetCash(100000);
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: positive sentiment in latest SEC filings, intersected with the fundamental list.
+ // Second universe: positive sentiment in latest SEC filings, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Keep names with positive sentiment in both the report and MD&A sections.
- var alt = from d in altCoarse.OfType()
- where d.ReportSentiment.Sentiment > 0m
- && d.ManagementDiscussionAnalyasisOfFinancialConditionAndResultsOfOperations.Sentiment > 0m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .Where(d => d.ReportSentiment != null && d.ReportSentiment.Sentiment > 0m
+ && d.ManagementDiscussionAnalyasisOfFinancialConditionAndResultsOfOperations != null
+ && d.ManagementDiscussionAnalyasisOfFinancialConditionAndResultsOfOperations.Sentiment > 0m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance);
@@ -43,11 +48,11 @@ where d.ReportSentiment.Sentiment > 0m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-brainsentimentindicatoruniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-brainsentimentindicatoruniverse/Main.cs
index b2fc06a8c5..d34df220d9 100644
--- a/project-templates/csharp/alternative-data-chain-universe-brainsentimentindicatoruniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-brainsentimentindicatoruniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class BrainSentimentIndicatorChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = [];
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -19,22 +19,26 @@ public override void Initialize()
SetCash(100000);
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: positive 7-day media sentiment with active mention coverage, intersected with the fundamental list.
+ // Second universe: positive 7-day Brain sentiment, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
- // Keep names with both active mention coverage and positive 7-day sentiment.
- var alt = from d in altCoarse.OfType()
- where d.TotalArticleMentions7Days > 0m && d.Sentiment7Days > 0m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ // Keep names with both active 7-day mention coverage and positive 7-day sentiment.
+ var alt = altCoarse.OfType()
+ .Where(d => d.TotalArticleMentions7Days > 0m && d.Sentiment7Days > 0m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance);
@@ -42,11 +46,11 @@ where d.TotalArticleMentions7Days > 0m && d.Sentiment7Days > 0m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-brainstockrankinguniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-brainstockrankinguniverse/Main.cs
index db9bb753c1..f06348b50d 100644
--- a/project-templates/csharp/alternative-data-chain-universe-brainstockrankinguniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-brainstockrankinguniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class BrainStockRankingChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = [];
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -19,22 +19,26 @@ public override void Initialize()
SetCash(100000);
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe selects top 100 US Equities by dollar volume.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe filters for positive Brain ML rankings across all horizons.
+ // Second universe: positive Brain ML rankings across 2-, 3-, and 5-day horizons, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
- // Keep symbols with positive rankings across 2-day, 3-day, and 5-day horizons.
- var alt = from d in altCoarse.OfType()
- where d.Rank2Days > 0m && d.Rank3Days > 0m && d.Rank5Days > 0m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ // Keep names with consistent positive momentum across all three horizons.
+ var alt = altCoarse.OfType()
+ .Where(d => d.Rank2Days > 0m && d.Rank3Days > 0m && d.Rank5Days > 0m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance);
@@ -42,11 +46,11 @@ where d.Rank2Days > 0m && d.Rank3Days > 0m && d.Rank5Days > 0m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingdividends/Main.cs b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingdividends/Main.cs
index 1c11533f6b..7a6bc2767e 100644
--- a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingdividends/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingdividends/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class EODHDUpcomingDividendsChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = [];
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -19,22 +19,26 @@ public override void Initialize()
SetCash(100000);
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: ex-dividend in the next day with a $0.05+ payout, intersected with the fundamental list.
+ // Second universe: ex-dividend in the next day with a $0.05+ payout, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
- // Filter symbols with dividends over $0.05 paying within one day.
- var alt = from d in altCoarse.OfType()
- where d.DividendDate <= Time.AddDays(1) && d.Dividend > 0.05m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ // Keep names with a dividend over $0.05 paying within one day.
+ var alt = altCoarse.OfType()
+ .Where(d => d.DividendDate <= Time.AddDays(1) && d.Dividend > 0.05m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance);
@@ -42,11 +46,11 @@ orderby c.DollarVolume descending
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingearnings/Main.cs b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingearnings/Main.cs
index dec76e6e88..a2e2e08461 100644
--- a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingearnings/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingearnings/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class EODHDUpcomingEarningsChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,22 +20,26 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: earnings in the next 3 days with a positive estimate, intersected with the fundamental list.
+ // Second universe: upcoming earnings with positive estimates, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Keep names with a positive analyst estimate ahead of the report.
- var alt = from d in altCoarse.OfType()
- where d.ReportDate <= Time.AddDays(3) && d.Estimate > 0m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .Where(d => d.ReportDate <= Time.AddDays(3) && d.Estimate > 0m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -44,12 +48,12 @@ orderby c.DollarVolume descending
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingipos/Main.cs b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingipos/Main.cs
index c736826028..3a451fd669 100644
--- a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingipos/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingipos/Main.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Algorithm.Framework.Portfolio;
@@ -11,7 +12,10 @@ public class EODHDUpcomingIPOsChainedUniverseAlgorithm : QCAlgorithm
{
private static readonly HashSet _dealTypesWanted = new() { EODHD.DealType.Expected, EODHD.DealType.Priced };
- private List _fundamental = new();
+ private List _fundamental = [];
+ // Map of IPO symbol -> IPO date, captured while the event is upcoming so we can
+ // trade the name once Morningstar has a few days of fundamentals on it.
+ private Dictionary _ipoDates = new();
private Universe _universe;
public override void Initialize()
@@ -22,25 +26,47 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: confirmed non-penny upcoming IPOs, intersected with the fundamental list.
+ // Second universe: trade IPOs one week after listing so fundamentals are populated.
_universe = AddUniverse(altCoarse =>
{
- // Keep expected/priced IPOs with a confirmed date and an above-$1 price band.
- var alt = from d in altCoarse.OfType()
- where _dealTypesWanted.Contains(d.DealType)
- && d.IpoDate.HasValue
- && (new[] { d.LowestPrice, d.HighestPrice, d.OfferPrice }
- .Where(x => x.HasValue).Min() ?? 0m) > 1m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ // Capture expected/priced IPOs with a confirmed date and a >$1 minimum price band.
+ foreach (var d in altCoarse.OfType())
+ {
+ if (!_dealTypesWanted.Contains(d.DealType) || !d.IpoDate.HasValue)
+ {
+ continue;
+ }
+ var prices = new[] { d.LowestPrice, d.HighestPrice, d.OfferPrice }
+ .Where(x => x.HasValue)
+ .Select(x => x.Value)
+ .ToList();
+ if (prices.Count == 0 || prices.Min() <= 1m)
+ {
+ continue;
+ }
+ _ipoDates[d.Symbol] = d.IpoDate.Value;
+ }
+ // Drop entries whose IPO was more than 30 days ago to keep the dict bounded.
+ _ipoDates = _ipoDates
+ .Where(kv => kv.Value > Time.AddDays(-30))
+ .ToDictionary(kv => kv.Key, kv => kv.Value);
+ // Trade IPOs that listed at least 7 days ago, ranked by dollar volume.
+ var alt = _ipoDates
+ .Where(kv => kv.Value <= Time.AddDays(-7))
+ .Select(kv => kv.Key)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -49,7 +75,7 @@ where _dealTypesWanted.Contains(d.DealType)
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
diff --git a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingsplits/Main.cs b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingsplits/Main.cs
index 37756bd368..4f6ee36c18 100644
--- a/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingsplits/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-eodhdupcomingsplits/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class EODHDUpcomingSplitsChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,22 +20,26 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: forward stock split in the next 3 days, intersected with the fundamental list.
+ // Second universe: forward stock split in the next 3 days, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Keep names with a forward split (factor > 1) within 3 days.
- var alt = from d in altCoarse.OfType()
- where d.SplitDate <= Time.AddDays(3) && d.SplitFactor > 1m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .Where(d => d.SplitDate <= Time.AddDays(3) && d.SplitFactor > 1m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -44,12 +48,12 @@ orderby c.DollarVolume descending
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-quivercnbcsuniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-quivercnbcsuniverse/Main.cs
index 1af7eaeadf..0284efd98f 100644
--- a/project-templates/csharp/alternative-data-chain-universe-quivercnbcsuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-quivercnbcsuniverse/Main.cs
@@ -10,7 +10,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class QuiverCNBCsChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -24,19 +24,24 @@ public override void Initialize()
// First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
// Second universe: 3+ BUY CNBC opinions, intersected with the fundamental list.
_universe = AddUniverse(altCoarse =>
{
- // Group raw CNBC opinions by ticker and keep names with 3+ BUY recommendations.
- var alt = from g in altCoarse.OfType().GroupBy(x => x.Symbol)
- where g.Count(x => x.Direction == OrderDirection.Buy) >= 3
- select g.Key;
- return _fundamental.Intersect(alt);
+ // Group raw CNBC opinions by ticker and keep names with 2+ BUY recommendations.
+ var alt = altCoarse.OfType()
+ .GroupBy(x => x.Symbol)
+ .Where(g => g.Count(x => x.Direction == OrderDirection.Buy) >= 2)
+ .Select(g => g.Key)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -45,12 +50,12 @@ where g.Count(x => x.Direction == OrderDirection.Buy) >= 3
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-quivergovernmentcontractuniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-quivergovernmentcontractuniverse/Main.cs
index 97f349f94f..f85c7600c3 100644
--- a/project-templates/csharp/alternative-data-chain-universe-quivergovernmentcontractuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-quivergovernmentcontractuniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class QuiverGovernmentContractChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,22 +20,27 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: 3+ government contracts totalling over $50K, intersected with the fundamental list.
+ // Second universe: 3+ government contracts totalling over $50K, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Group by ticker and keep names with 3+ contracts totalling over $50K.
- var alt = from g in altCoarse.OfType().GroupBy(x => x.Symbol)
- where g.Count() >= 3 && g.Sum(x => x.Amount) > 50000m
- select g.Key;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .GroupBy(x => x.Symbol)
+ .Where(g => g.Count() >= 3 && g.Sum(x => x.Amount) > 50000m)
+ .Select(g => g.Key)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -44,7 +49,7 @@ where g.Count() >= 3 && g.Sum(x => x.Amount) > 50000m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
diff --git a/project-templates/csharp/alternative-data-chain-universe-quiverinsidertradinguniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-quiverinsidertradinguniverse/Main.cs
index a0e2657f52..e639871dd1 100644
--- a/project-templates/csharp/alternative-data-chain-universe-quiverinsidertradinguniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-quiverinsidertradinguniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class QuiverInsiderTradingChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,36 +20,30 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: 10 largest insider-trading dollar volumes, intersected with the fundamental list.
+ // Second universe: 10 largest insider-trading dollar volumes, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Aggregate insider dollar volume per ticker and keep the 10 largest.
- var dollarVolume = new Dictionary();
- foreach (var d in altCoarse.OfType())
- {
- if (d.PricePerShare == null || d.PricePerShare == 0m)
- {
- continue;
- }
- if (!dollarVolume.ContainsKey(d.Symbol))
- {
- dollarVolume[d.Symbol] = 0m;
- }
- dollarVolume[d.Symbol] += (d.Shares ?? 0m) * d.PricePerShare.Value;
- }
- var alt = dollarVolume
- .OrderByDescending(kvp => kvp.Value)
+ var alt = altCoarse.OfType()
+ .Where(d => d.PricePerShare.HasValue && d.PricePerShare.Value != 0m)
+ .GroupBy(d => d.Symbol)
+ .Select(g => new { Symbol = g.Key, DollarVolume = g.Sum(d => (d.Shares ?? 0m) * d.PricePerShare.Value) })
+ .OrderByDescending(x => x.DollarVolume)
.Take(10)
- .Select(kvp => kvp.Key);
- return _fundamental.Intersect(alt);
+ .Select(x => x.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -58,7 +52,7 @@ orderby c.DollarVolume descending
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
diff --git a/project-templates/csharp/alternative-data-chain-universe-quiverlobbyinguniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-quiverlobbyinguniverse/Main.cs
index 900b7dd171..bdfb2f6431 100644
--- a/project-templates/csharp/alternative-data-chain-universe-quiverlobbyinguniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-quiverlobbyinguniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class QuiverLobbyingChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,22 +20,27 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: $100K+ corporate lobbying spend, intersected with the fundamental list.
+ // Second universe: $100K+ corporate lobbying spend, ranked by dollar volume.
_universe = AddUniverse("QuiverLobbyingUniverse", Resolution.Daily, altCoarse =>
{
// Aggregate lobbying spend per ticker and keep names spending $100K+.
- var alt = from g in altCoarse.OfType().GroupBy(x => x.Symbol)
- where g.Sum(x => x.Amount) >= 100000m
- select g.Key;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .GroupBy(x => x.Symbol)
+ .Where(g => g.Sum(x => x.Amount) >= 100000m)
+ .Select(g => g.Key)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -44,12 +49,12 @@ where g.Sum(x => x.Amount) >= 100000m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-quiverquantcongressuniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-quiverquantcongressuniverse/Main.cs
index 50ca06d58f..113f922e9c 100644
--- a/project-templates/csharp/alternative-data-chain-universe-quiverquantcongressuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-quiverquantcongressuniverse/Main.cs
@@ -10,7 +10,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class QuiverQuantCongressChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -21,22 +21,26 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: US Congress BUY disclosures over $200K, intersected with the fundamental list.
+ // Second universe: US Congress BUY disclosures over $200K, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Keep buy disclosures over $200K to filter out small reports.
- var alt = from d in altCoarse.OfType()
- where d.Amount > 200000m && d.Transaction == OrderDirection.Buy
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .Where(d => d.Amount > 200000m && d.Transaction == OrderDirection.Buy)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -45,7 +49,7 @@ orderby c.DollarVolume descending
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
diff --git a/project-templates/csharp/alternative-data-chain-universe-smartinsiderintentionuniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-smartinsiderintentionuniverse/Main.cs
index fb8eb2e6f7..c84e57f745 100644
--- a/project-templates/csharp/alternative-data-chain-universe-smartinsiderintentionuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-smartinsiderintentionuniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class SmartInsiderIntentionChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,22 +20,28 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: $100M+ market-cap buyback intentions over 0.5%, intersected with the fundamental list.
+ // Second universe: $100M+ market-cap buyback intentions over 0.5%, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Keep $100M+ market-cap names announcing a buyback over 0.5% of shares.
- var alt = from d in altCoarse.OfType()
- where d.Percentage > 0.005m && d.USDMarketCap > 100000000m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ // Keep names announcing a buyback over 0.5% of shares. (USDMarketCap is not
+ // populated for intention records, unlike SmartInsiderTransactionUniverse.)
+ var alt = altCoarse.OfType()
+ .Where(d => d.Percentage > 0.005m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -44,12 +50,12 @@ where d.Percentage > 0.005m && d.USDMarketCap > 100000000m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-chain-universe-smartinsidertransactionuniverse/Main.cs b/project-templates/csharp/alternative-data-chain-universe-smartinsidertransactionuniverse/Main.cs
index c2ed324ccd..fc29d70c57 100644
--- a/project-templates/csharp/alternative-data-chain-universe-smartinsidertransactionuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-chain-universe-smartinsidertransactionuniverse/Main.cs
@@ -9,7 +9,7 @@ namespace QuantConnect.Algorithm.CSharp
{
public class SmartInsiderTransactionChainedUniverseAlgorithm : QCAlgorithm
{
- private List _fundamental = new();
+ private List _fundamental = [];
private Universe _universe;
public override void Initialize()
@@ -20,22 +20,26 @@ public override void Initialize()
Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Minute;
- // First universe: top 100 US Equities by dollar volume; emits Universe.Unchanged.
+ // First universe: store all US Equity fundamentals; emits Universe.Unchanged.
AddUniverse(fundamental =>
{
- _fundamental = (from c in fundamental
- orderby c.DollarVolume descending
- select c.Symbol).Take(100).ToList();
+ _fundamental = [..fundamental];
return Universe.Unchanged;
});
- // Second universe: $100M+ market-cap buybacks over 0.5%, intersected with the fundamental list.
+ // Second universe: $100M+ market-cap buybacks over 0.5%, ranked by dollar volume.
_universe = AddUniverse(altCoarse =>
{
// Keep $100M+ market-cap names buying back over 0.5% of shares.
- var alt = from d in altCoarse.OfType()
- where d.BuybackPercentage > 0.005m && d.USDMarketCap > 100000000m
- select d.Symbol;
- return _fundamental.Intersect(alt);
+ var alt = altCoarse.OfType()
+ .Where(d => d.BuybackPercentage > 0.005m && d.USDMarketCap > 100000000m)
+ .Select(d => d.Symbol)
+ .ToHashSet();
+ Plot("Universe", "Raw", alt.Count);
+ return _fundamental
+ .Where(c => alt.Contains(c.Symbol))
+ .OrderByDescending(c => c.DollarVolume)
+ .Select(c => c.Symbol)
+ .Take(100);
});
// Rebalance before market open to trade today's intersection.
@@ -44,12 +48,12 @@ where d.BuybackPercentage > 0.005m && d.USDMarketCap > 100000000m
private void Rebalance()
{
- if (_universe.Selected == null || _universe.Selected.Count == 0)
+ if (_universe.Selected.Count == 0)
{
return;
}
- var weight = 1m / _universe.Selected.Count;
+ var weight = _universe.Selected.Count >= 10 ? 1m / _universe.Selected.Count : 0.1m;
var targets = _universe.Selected
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-universe-eodhdupcomingipos/Main.cs b/project-templates/csharp/alternative-data-universe-eodhdupcomingipos/Main.cs
index 502076b611..59906874e1 100644
--- a/project-templates/csharp/alternative-data-universe-eodhdupcomingipos/Main.cs
+++ b/project-templates/csharp/alternative-data-universe-eodhdupcomingipos/Main.cs
@@ -24,11 +24,14 @@ public override void Initialize()
{
// Keep expected/priced IPOs with a confirmed date and an above-$1 price band.
return from d in data.OfType()
+ let prices = new[] { d.LowestPrice, d.HighestPrice, d.OfferPrice }
+ .Where(x => x.HasValue)
+ .Select(x => x.Value)
+ .ToList()
where _dealTypesWanted.Contains(d.DealType)
&& d.IpoDate.HasValue
- && new[] { d.LowestPrice, d.HighestPrice, d.OfferPrice }
- .Where(x => x.HasValue)
- .Min().Value > 1m
+ && prices.Count > 0
+ && prices.Min() > 1m
select d.Symbol;
});
diff --git a/project-templates/csharp/alternative-data-universe-quivercnbcsuniverse/Main.cs b/project-templates/csharp/alternative-data-universe-quivercnbcsuniverse/Main.cs
index e489b1fbf8..0a256ee141 100644
--- a/project-templates/csharp/alternative-data-universe-quivercnbcsuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-universe-quivercnbcsuniverse/Main.cs
@@ -15,6 +15,7 @@ public override void Initialize()
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(100000);
+ Settings.SeedInitialPrices = true;
// Trade daily on CNBC opinion updates.
UniverseSettings.Resolution = Resolution.Daily;
@@ -39,9 +40,13 @@ private void Rebalance()
{
return;
}
-
- var weight = 1m / _universe.Selected.Count;
- var targets = _universe.Selected
+ var securities = _universe.Selected.Where(s => Securities[s].Price > 0).ToList();
+ if (securities.Count == 0)
+ {
+ return;
+ }
+ var weight = securities.Count >= 10 ? 1m / securities.Count : 0.1m;
+ var targets = securities
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-universe-quiverquantcongressuniverse/Main.cs b/project-templates/csharp/alternative-data-universe-quiverquantcongressuniverse/Main.cs
index 3792ef252b..cb96403f29 100644
--- a/project-templates/csharp/alternative-data-universe-quiverquantcongressuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-universe-quiverquantcongressuniverse/Main.cs
@@ -15,6 +15,7 @@ public override void Initialize()
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(100000);
+ Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Daily;
// Universe of US Equities recently bought by US Congress members in trades over $200K.
diff --git a/project-templates/csharp/alternative-data-universe-smartinsiderintentionuniverse/Main.cs b/project-templates/csharp/alternative-data-universe-smartinsiderintentionuniverse/Main.cs
index c5959cbb69..6edd6caeb1 100644
--- a/project-templates/csharp/alternative-data-universe-smartinsiderintentionuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-universe-smartinsiderintentionuniverse/Main.cs
@@ -14,15 +14,17 @@ public override void Initialize()
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(100000);
+ Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Daily;
- // Universe of large-cap US Equities announcing meaningful buyback intentions.
+ // Universe of US Equities announcing meaningful buyback intentions.
_universe = AddUniverse(data =>
{
- // Keep $100M+ market-cap names announcing a buyback over 0.5% of shares.
- return from d in data.OfType()
- where d.Percentage > 0.005m && d.USDMarketCap > 100000000m
- select d.Symbol;
+ // Keep names announcing a buyback over 0.5% of shares. (USDMarketCap is not
+ // populated for intention records, unlike SmartInsiderTransactionUniverse.)
+ return data.OfType()
+ .Where(d => d.Percentage > 0.005m)
+ .Select(d => d.Symbol);
});
// Rebalance shortly after the open so today's universe is locked in.
@@ -35,9 +37,13 @@ private void Rebalance()
{
return;
}
-
- var weight = 1m / _universe.Selected.Count;
- var targets = _universe.Selected
+ var securities = _universe.Selected.Where(s => Securities[s].Price > 0).ToList();
+ if (securities.Count == 0)
+ {
+ return;
+ }
+ var weight = securities.Count >= 10 ? 1m / securities.Count : 0.1m;
+ var targets = securities
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/csharp/alternative-data-universe-smartinsidertransactionuniverse/Main.cs b/project-templates/csharp/alternative-data-universe-smartinsidertransactionuniverse/Main.cs
index a29e1337f7..a743dffdb7 100644
--- a/project-templates/csharp/alternative-data-universe-smartinsidertransactionuniverse/Main.cs
+++ b/project-templates/csharp/alternative-data-universe-smartinsidertransactionuniverse/Main.cs
@@ -14,6 +14,7 @@ public override void Initialize()
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(100000);
+ Settings.SeedInitialPrices = true;
UniverseSettings.Resolution = Resolution.Daily;
// Universe of large-cap US Equities executing meaningful share buybacks.
@@ -35,9 +36,13 @@ private void Rebalance()
{
return;
}
-
- var weight = 1m / _universe.Selected.Count;
- var targets = _universe.Selected
+ var securities = _universe.Selected.Where(s => Securities[s].Price > 0).ToList();
+ if (securities.Count == 0)
+ {
+ return;
+ }
+ var weight = securities.Count >= 10 ? 1m / securities.Count : 0.1m;
+ var targets = securities
.Select(symbol => new PortfolioTarget(symbol, weight))
.ToList();
diff --git a/project-templates/python/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/main.py b/project-templates/python/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/main.py
index 5e7299e160..1758ae1e84 100644
--- a/project-templates/python/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/main.py
+++ b/project-templates/python/alternative-data-chain-universe-braincompanyfilinglanguagemetricsuniverseall/main.py
@@ -4,7 +4,8 @@
class BrainCompanyFilingLanguageMetricsChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -12,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: positive sentiment in latest SEC filings, intersected with the fundamental list.
+ # Second universe: positive sentiment in latest SEC filings, ranked by dollar volume.
self._universe = self.add_universe(BrainCompanyFilingLanguageMetricsUniverseAll, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -24,22 +25,25 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[BrainCompanyFilingLanguageMetricsUniverseAll]) -> List[Symbol]:
# Keep names with positive sentiment in both the report and MD&A sections.
- alt = [d.symbol for d in alt_coarse
- if d.report_sentiment and d.report_sentiment.sentiment and d.report_sentiment.sentiment > 0 and
- d.management_discussion_analyasis_of_financial_condition_and_results_of_operations and
- d.management_discussion_analyasis_of_financial_condition_and_results_of_operations.sentiment and
- d.management_discussion_analyasis_of_financial_condition_and_results_of_operations.sentiment > 0]
- return [s for s in self._fundamental if s in alt]
+ alt = {d.symbol for d in alt_coarse
+ if d.report_sentiment and d.report_sentiment.sentiment and d.report_sentiment.sentiment > 0
+ and d.management_discussion_analyasis_of_financial_condition_and_results_of_operations
+ and d.management_discussion_analyasis_of_financial_condition_and_results_of_operations.sentiment
+ and d.management_discussion_analyasis_of_financial_condition_and_results_of_operations.sentiment > 0}
+ self.plot('Universe', 'Raw', len(alt))
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-brainsentimentindicatoruniverse/main.py b/project-templates/python/alternative-data-chain-universe-brainsentimentindicatoruniverse/main.py
index 0e1d188e7d..e9fdb230eb 100644
--- a/project-templates/python/alternative-data-chain-universe-brainsentimentindicatoruniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-brainsentimentindicatoruniverse/main.py
@@ -4,7 +4,8 @@
class BrainSentimentIndicatorChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -12,11 +13,11 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # Add a fundamental universe to track the most liquid US Equities by dollar volume.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Add a Brain Sentiment universe, restricted to high-sentiment names within the fundamental list.
+ # Second universe: positive 7-day Brain sentiment, ranked by dollar volume.
self._universe = self.add_universe(BrainSentimentIndicatorUniverse, self._select_assets)
- # Rebalance before market open.
+ # Rebalance before market open to trade today's intersection.
self.schedule.on(
self.date_rules.every_day("SPY"),
self.time_rules.at(9, 0),
@@ -24,22 +25,23 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- self._fundamental = [c.symbol for c in sorted(fundamental, key=lambda x: x.dollar_volume)[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[BrainSentimentIndicatorUniverse]) -> List[Symbol]:
- # Keep only names with active mention coverage and positive sentiment.
- alt = [d.symbol for d in alt_coarse
- if d.total_article_mentions_7_days and
- d.total_article_mentions_7_days > 0 and
- d.sentiment_7_days and
- d.sentiment_7_days > 0]
- return [s for s in self._fundamental if s in alt]
+ # Keep names with both active 7-day mention coverage and positive 7-day sentiment.
+ alt = {d.symbol for d in alt_coarse
+ if d.total_article_mentions_7_days and d.total_article_mentions_7_days > 0
+ and d.sentiment_7_days and d.sentiment_7_days > 0}
+ self.plot('Universe', 'Raw', len(alt))
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- # Enter the universe equally weighted across all selected assets.
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-brainstockrankinguniverse/main.py b/project-templates/python/alternative-data-chain-universe-brainstockrankinguniverse/main.py
index afc7c1982a..ef47895a53 100644
--- a/project-templates/python/alternative-data-chain-universe-brainstockrankinguniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-brainstockrankinguniverse/main.py
@@ -5,7 +5,7 @@
class BrainStockRankingChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: positive Brain ML rankings across 2-, 3-, and 5-day horizons, intersected with the fundamental list.
+ # Second universe: positive Brain ML rankings across 2-, 3-, and 5-day horizons, ranked by dollar volume.
self._universe = self.add_universe(BrainStockRankingUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,21 +25,24 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[BrainStockRankingUniverse]) -> List[Symbol]:
# Keep names with consistent positive momentum across all three horizons.
- alt = [d.symbol for d in alt_coarse
- if d.rank_2_days and d.rank_2_days > 0 and
- d.rank_3_days and d.rank_3_days > 0 and
- d.rank_5_days and d.rank_5_days > 0]
- return [s for s in self._fundamental if s in alt]
+ alt = {d.symbol for d in alt_coarse
+ if d.rank_2_days and d.rank_2_days > 0
+ and d.rank_3_days and d.rank_3_days > 0
+ and d.rank_5_days and d.rank_5_days > 0}
+ self.plot('Universe', 'Raw', len(alt))
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-eodhdupcomingdividends/main.py b/project-templates/python/alternative-data-chain-universe-eodhdupcomingdividends/main.py
index 218fb5a1a8..dfc173e3d2 100644
--- a/project-templates/python/alternative-data-chain-universe-eodhdupcomingdividends/main.py
+++ b/project-templates/python/alternative-data-chain-universe-eodhdupcomingdividends/main.py
@@ -5,7 +5,7 @@
class EODHDUpcomingDividendsChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: ex-dividend in the next day with a $0.05+ payout, intersected with the fundamental list.
+ # Second universe: ex-dividend in the next day with a $0.05+ payout, ranked by dollar volume.
self._universe = self.add_universe(EODHDUpcomingDividends, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,20 +25,23 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[EODHDUpcomingDividends]) -> List[Symbol]:
# Keep names with a dividend over $0.05 paying within one day.
- alt = [d.symbol for d in alt_coarse
- if d.dividend_date and d.dividend and
- d.dividend_date <= self.time + timedelta(1) and d.dividend > 0.05]
- return [s for s in self._fundamental if s in alt]
+ alt = {d.symbol for d in alt_coarse
+ if d.dividend_date and d.dividend
+ and d.dividend_date <= self.time + timedelta(1) and d.dividend > 0.05}
+ self.plot('Universe', 'Raw', len(alt))
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-eodhdupcomingearnings/main.py b/project-templates/python/alternative-data-chain-universe-eodhdupcomingearnings/main.py
index fead4fc361..87502a4689 100644
--- a/project-templates/python/alternative-data-chain-universe-eodhdupcomingearnings/main.py
+++ b/project-templates/python/alternative-data-chain-universe-eodhdupcomingearnings/main.py
@@ -5,7 +5,7 @@
class EODHDUpcomingEarningsChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: earnings in the next 3 days with a positive estimate, intersected with the fundamental list.
+ # Second universe: upcoming earnings with positive estimates, ranked by dollar volume.
self._universe = self.add_universe(EODHDUpcomingEarnings, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,20 +25,24 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[EODHDUpcomingEarnings]) -> List[Symbol]:
# Keep names with a positive analyst estimate ahead of the report.
- alt = [d.symbol for d in alt_coarse
+ alt = {d.symbol for d in alt_coarse
if d.report_date and d.estimate and
- d.report_date <= self.time + timedelta(3) and d.estimate > 0]
- return [s for s in self._fundamental if s in alt]
+ d.report_date <= self.time + timedelta(3) and d.estimate > 0}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-eodhdupcomingipos/main.py b/project-templates/python/alternative-data-chain-universe-eodhdupcomingipos/main.py
index c12d8e58e4..439f3e43be 100644
--- a/project-templates/python/alternative-data-chain-universe-eodhdupcomingipos/main.py
+++ b/project-templates/python/alternative-data-chain-universe-eodhdupcomingipos/main.py
@@ -5,7 +5,10 @@
class EODHDUpcomingIPOsChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
+ # Map of IPO symbol -> IPO date, captured while the event is upcoming so we can
+ # trade the name once Morningstar has a few days of fundamentals on it.
+ _ipo_dates: Dict[Symbol, datetime] = {}
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +16,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: confirmed non-penny upcoming IPOs, intersected with the fundamental list.
+ # Second universe: trade IPOs one week after listing so fundamentals are populated.
self._universe = self.add_universe(EODHDUpcomingIPOs, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,17 +28,27 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[EODHDUpcomingIPOs]) -> List[Symbol]:
- # Keep expected/priced IPOs with a confirmed date and a >$1 minimum across the price band.
- alt = [d.symbol for d in alt_coarse
- if d.ipo_date and d.deal_type in [EODHD.DealType.EXPECTED, EODHD.DealType.PRICED] and
- (prices := [x for x in [d.lowest_price, d.highest_price, d.offer_price] if x]) and
- min(prices) > 1]
- return [s for s in self._fundamental if s in alt]
+ # Capture expected/priced IPOs with a confirmed date and a >$1 minimum price band.
+ for d in alt_coarse:
+ if (d.ipo_date and d.deal_type in [EODHD.DealType.EXPECTED, EODHD.DealType.PRICED] and
+ (prices := [x for x in [d.lowest_price, d.highest_price, d.offer_price] if x]) and
+ min(prices) > 1):
+ self._ipo_dates[d.symbol] = d.ipo_date
+ # Drop entries whose IPO was more than 30 days ago to keep the dict bounded.
+ self._ipo_dates = {s: d for s, d in self._ipo_dates.items()
+ if d > self.time - timedelta(30)}
+ # Trade IPOs that listed at least 7 days ago, ranked by dollar volume.
+ alt = {s for s, d in self._ipo_dates.items()
+ if d <= self.time - timedelta(7)}
+ self.plot('Universe', 'Raw', len(alt))
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
diff --git a/project-templates/python/alternative-data-chain-universe-eodhdupcomingsplits/main.py b/project-templates/python/alternative-data-chain-universe-eodhdupcomingsplits/main.py
index 38050f38a3..f3cc18ed58 100644
--- a/project-templates/python/alternative-data-chain-universe-eodhdupcomingsplits/main.py
+++ b/project-templates/python/alternative-data-chain-universe-eodhdupcomingsplits/main.py
@@ -5,7 +5,7 @@
class EODHDUpcomingSplitsChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: forward stock split in the next 3 days, intersected with the fundamental list.
+ # Second universe: forward stock split in the next 3 days, ranked by dollar volume.
self._universe = self.add_universe(EODHDUpcomingSplits, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,20 +25,24 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[EODHDUpcomingSplits]) -> List[Symbol]:
# Keep names with a forward split (factor > 1) within 3 days.
- alt = [d.symbol for d in alt_coarse
+ alt = {d.symbol for d in alt_coarse
if d.split_date and d.split_factor and
- d.split_date <= self.time + timedelta(3) and d.split_factor > 1]
- return [s for s in self._fundamental if s in alt]
+ d.split_date <= self.time + timedelta(3) and d.split_factor > 1}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-quivercnbcsuniverse/main.py b/project-templates/python/alternative-data-chain-universe-quivercnbcsuniverse/main.py
index e5cc991dd2..e38c9de9f0 100644
--- a/project-templates/python/alternative-data-chain-universe-quivercnbcsuniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-quivercnbcsuniverse/main.py
@@ -5,7 +5,7 @@
class QuiverCNBCsChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: 3+ BUY CNBC opinions, intersected with the fundamental list.
+ # Second universe: CNBC opinions intersected with fundamentals, ranked by dollar volume.
self._universe = self.add_universe(QuiverCNBCsUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,22 +25,26 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[QuiverCNBCsUniverse]) -> List[Symbol]:
- # Group raw CNBC opinions by ticker and keep names with 3+ BUY recommendations.
+ # Group raw CNBC opinions by ticker and keep names with 2+ BUY recommendations.
cnbc_by_symbol: dict[Symbol, list[QuiverCNBCsUniverse]] = {}
for d in alt_coarse:
cnbc_by_symbol.setdefault(d.symbol, []).append(d)
- alt = [s for s, ds in cnbc_by_symbol.items()
- if sum(1 for d in ds if d.direction == OrderDirection.BUY) >= 3]
- return [s for s in self._fundamental if s in alt]
+ alt = {s for s, ds in cnbc_by_symbol.items()
+ if sum(1 for d in ds if d.direction == OrderDirection.BUY) >= 2}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-quivergovernmentcontractuniverse/main.py b/project-templates/python/alternative-data-chain-universe-quivergovernmentcontractuniverse/main.py
index 67ea29bbdd..5c9ef63e59 100644
--- a/project-templates/python/alternative-data-chain-universe-quivergovernmentcontractuniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-quivergovernmentcontractuniverse/main.py
@@ -5,7 +5,7 @@
class QuiverGovernmentContractChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: 3+ government contracts totalling over $50K, intersected with the fundamental list.
+ # Second universe: 3+ government contracts totalling over $50K, ranked by dollar volume.
self._universe = self.add_universe(QuiverGovernmentContractUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,8 +25,7 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[QuiverGovernmentContractUniverse]) -> List[Symbol]:
@@ -34,9 +33,14 @@ def _select_assets(self, alt_coarse: List[QuiverGovernmentContractUniverse]) ->
contracts_by_symbol: dict[Symbol, list[QuiverGovernmentContractUniverse]] = {}
for d in alt_coarse:
contracts_by_symbol.setdefault(d.symbol, []).append(d)
- alt = [s for s, ds in contracts_by_symbol.items()
- if len(ds) >= 3 and sum(x.amount or 0 for x in ds) > 50000]
- return [s for s in self._fundamental if s in alt]
+ alt = {s for s, ds in contracts_by_symbol.items()
+ if len(ds) >= 3 and sum(x.amount or 0 for x in ds) > 50000}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
diff --git a/project-templates/python/alternative-data-chain-universe-quiverinsidertradinguniverse/main.py b/project-templates/python/alternative-data-chain-universe-quiverinsidertradinguniverse/main.py
index 165e71f012..bdcc7c453c 100644
--- a/project-templates/python/alternative-data-chain-universe-quiverinsidertradinguniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-quiverinsidertradinguniverse/main.py
@@ -5,7 +5,7 @@
class QuiverInsiderTradingChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: 10 largest insider-trading dollar volumes, intersected with the fundamental list.
+ # Second universe: 10 largest insider-trading dollar volumes, ranked by dollar volume.
self._universe = self.add_universe(QuiverInsiderTradingUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,8 +25,7 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[QuiverInsiderTradingUniverse]) -> List[Symbol]:
@@ -36,8 +35,13 @@ def _select_assets(self, alt_coarse: List[QuiverInsiderTradingUniverse]) -> List
if not d.price_per_share:
continue
dollar_volume[d.symbol] = dollar_volume.get(d.symbol, 0) + (d.shares or 0) * d.price_per_share
- alt = [s for s, _ in sorted(dollar_volume.items(), key=lambda kv: kv[1])[-10:]]
- return [s for s in self._fundamental if s in alt]
+ alt = {s for s, _ in sorted(dollar_volume.items(), key=lambda kv: kv[1])[-10:]}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
diff --git a/project-templates/python/alternative-data-chain-universe-quiverlobbyinguniverse/main.py b/project-templates/python/alternative-data-chain-universe-quiverlobbyinguniverse/main.py
index c441c99aa9..9c6291ccd3 100644
--- a/project-templates/python/alternative-data-chain-universe-quiverlobbyinguniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-quiverlobbyinguniverse/main.py
@@ -5,7 +5,7 @@
class QuiverLobbyingChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: $100K+ corporate lobbying spend, intersected with the fundamental list.
+ # Second universe: $100K+ corporate lobbying spend, ranked by dollar volume.
self._universe = self.add_universe(QuiverLobbyingUniverse, "QuiverLobbyingUniverse",
Resolution.DAILY, self._select_assets)
# Rebalance before market open to trade today's intersection.
@@ -26,8 +26,7 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[QuiverLobbyingUniverse]) -> List[Symbol]:
@@ -35,12 +34,17 @@ def _select_assets(self, alt_coarse: List[QuiverLobbyingUniverse]) -> List[Symbo
spend_by_symbol: dict[Symbol, float] = {}
for d in alt_coarse:
spend_by_symbol[d.symbol] = spend_by_symbol.get(d.symbol, 0) + (d.amount or 0)
- alt = [s for s, v in spend_by_symbol.items() if v >= 100000]
- return [s for s in self._fundamental if s in alt]
+ alt = {s for s, v in spend_by_symbol.items() if v >= 100000}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-quiverquantcongressuniverse/main.py b/project-templates/python/alternative-data-chain-universe-quiverquantcongressuniverse/main.py
index ab8f41b25f..95f00b6678 100644
--- a/project-templates/python/alternative-data-chain-universe-quiverquantcongressuniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-quiverquantcongressuniverse/main.py
@@ -5,7 +5,7 @@
class QuiverQuantCongressChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: US Congress BUY disclosures over $200K, intersected with the fundamental list.
+ # Second universe: US Congress BUY disclosures over $200K, ranked by dollar volume.
self._universe = self.add_universe(QuiverQuantCongressUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,16 +25,20 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[QuiverQuantCongressUniverse]) -> List[Symbol]:
# Keep buy disclosures over $200K to filter out small reports.
- alt = [d.symbol for d in alt_coarse
+ alt = {d.symbol for d in alt_coarse
if d.amount and d.amount > 200000 and
- d.transaction == OrderDirection.BUY]
- return [s for s in self._fundamental if s in alt]
+ d.transaction == OrderDirection.BUY}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
diff --git a/project-templates/python/alternative-data-chain-universe-smartinsiderintentionuniverse/main.py b/project-templates/python/alternative-data-chain-universe-smartinsiderintentionuniverse/main.py
index d2dbfb13ae..f981041b68 100644
--- a/project-templates/python/alternative-data-chain-universe-smartinsiderintentionuniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-smartinsiderintentionuniverse/main.py
@@ -5,7 +5,7 @@
class SmartInsiderIntentionChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: $100M+ market-cap buyback intentions over 0.5%, intersected with the fundamental list.
+ # Second universe: $100M+ market-cap buyback intentions over 0.5%, ranked by dollar volume.
self._universe = self.add_universe(SmartInsiderIntentionUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,20 +25,24 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[SmartInsiderIntentionUniverse]) -> List[Symbol]:
- # Keep $100M+ market-cap names announcing a buyback over 0.5% of shares.
- alt = [d.symbol for d in alt_coarse
- if d.percentage and d.usd_market_cap and
- d.percentage > 0.005 and d.usd_market_cap > 100000000]
- return [s for s in self._fundamental if s in alt]
+ # Keep names announcing a buyback over 0.5% of shares. (USDMarketCap is not
+ # populated for intention records, unlike SmartInsiderTransactionUniverse.)
+ alt = {d.symbol for d in alt_coarse
+ if d.percentage and d.percentage > 0.005}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-chain-universe-smartinsidertransactionuniverse/main.py b/project-templates/python/alternative-data-chain-universe-smartinsidertransactionuniverse/main.py
index 8c70626968..e2575d9623 100644
--- a/project-templates/python/alternative-data-chain-universe-smartinsidertransactionuniverse/main.py
+++ b/project-templates/python/alternative-data-chain-universe-smartinsidertransactionuniverse/main.py
@@ -5,7 +5,7 @@
class SmartInsiderTransactionChainedUniverseAlgorithm(QCAlgorithm):
- _fundamental: list[Symbol] = []
+ _fundamental: List[Fundamental] = []
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
@@ -13,9 +13,9 @@ def initialize(self) -> None:
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.MINUTE
- # First universe: top 100 US Equities by dollar volume; emits Universe.UNCHANGED.
+ # First universe: store all US Equity fundamentals; emits Universe.UNCHANGED.
self.add_universe(self._fundamental_filter)
- # Second universe: $100M+ market-cap buybacks over 0.5%, intersected with the fundamental list.
+ # Second universe: $100M+ market-cap buybacks over 0.5%, ranked by dollar volume.
self._universe = self.add_universe(SmartInsiderTransactionUniverse, self._select_assets)
# Rebalance before market open to trade today's intersection.
self.schedule.on(
@@ -25,20 +25,24 @@ def initialize(self) -> None:
)
def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse:
- sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume)
- self._fundamental = [c.symbol for c in sorted_by_dollar_volume[-100:]]
+ self._fundamental = fundamental
return Universe.UNCHANGED
def _select_assets(self, alt_coarse: List[SmartInsiderTransactionUniverse]) -> List[Symbol]:
# Keep $100M+ market-cap names buying back over 0.5% of shares.
- alt = [d.symbol for d in alt_coarse
+ alt = {d.symbol for d in alt_coarse
if d.buyback_percentage and d.usd_market_cap and
- d.buyback_percentage > 0.005 and d.usd_market_cap > 100000000]
- return [s for s in self._fundamental if s in alt]
+ d.buyback_percentage > 0.005 and d.usd_market_cap > 100000000}
+ self.plot('Universe', 'Raw', len(alt))
+ # Among the matches, keep the 100 most liquid by dollar volume.
+ return [c.symbol for c in sorted(
+ [c for c in self._fundamental if c.symbol in alt],
+ key=lambda c: c.dollar_volume, reverse=True
+ )[:100]]
def _rebalance(self) -> None:
if not self._universe.selected:
return
- weight = 1 / len(self._universe.selected)
+ weight = min(1 / len(self._universe.selected), 0.1)
targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
self.set_holdings(targets, True)
diff --git a/project-templates/python/alternative-data-universe-eodhdupcomingipos/main.py b/project-templates/python/alternative-data-universe-eodhdupcomingipos/main.py
index 51613dd290..38bf9a8061 100644
--- a/project-templates/python/alternative-data-universe-eodhdupcomingipos/main.py
+++ b/project-templates/python/alternative-data-universe-eodhdupcomingipos/main.py
@@ -1,6 +1,5 @@
# region imports
from AlgorithmImports import *
-from QuantConnect.DataSource.EODHD import DealType
# endregion
class EODHDUpcomingIPOsUniverseAlgorithm(QCAlgorithm):
@@ -20,7 +19,7 @@ def initialize(self) -> None:
def _select_assets(self, data: List[EODHDUpcomingIPOs]) -> List[Symbol]:
# Keep expected/priced IPOs with a confirmed date and a >$1 minimum across the price band.
return [d.symbol for d in data
- if d.ipo_date and d.deal_type in [DealType.EXPECTED, DealType.PRICED]
+ if d.ipo_date and d.deal_type in [EODHD.DealType.EXPECTED, EODHD.DealType.PRICED]
and (prices := [x for x in [d.lowest_price, d.highest_price, d.offer_price] if x])
and min(prices) > 1]
diff --git a/project-templates/python/alternative-data-universe-quivercnbcsuniverse/main.py b/project-templates/python/alternative-data-universe-quivercnbcsuniverse/main.py
index a3dadebadd..eb5f8d1a43 100644
--- a/project-templates/python/alternative-data-universe-quivercnbcsuniverse/main.py
+++ b/project-templates/python/alternative-data-universe-quivercnbcsuniverse/main.py
@@ -8,6 +8,7 @@ def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100000)
+ self.settings.seed_initial_prices = True
# Trade daily on CNBC opinion updates.
self.universe_settings.resolution = Resolution.DAILY
@@ -29,8 +30,10 @@ def _select_assets(self, data: List[QuiverCNBCsUniverse]) -> List[Symbol]:
def _rebalance(self) -> None:
if not self._universe.selected:
return
-
- weight = 1 / len(self._universe.selected)
- targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
+ securities = [s for s in self._universe.selected if self.securities[s].price]
+ if not securities:
+ return
+ weight = min(1 / len(securities), 0.1)
+ targets = [PortfolioTarget(symbol, weight) for symbol in securities]
self.set_holdings(targets, liquidate_existing_holdings=True)
diff --git a/project-templates/python/alternative-data-universe-quiverquantcongressuniverse/main.py b/project-templates/python/alternative-data-universe-quiverquantcongressuniverse/main.py
index 90109f0be1..9bd9142150 100644
--- a/project-templates/python/alternative-data-universe-quiverquantcongressuniverse/main.py
+++ b/project-templates/python/alternative-data-universe-quiverquantcongressuniverse/main.py
@@ -8,6 +8,7 @@ def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100000)
+ self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.DAILY
# Universe of US Equities recently bought by US Congress members in trades over $200K.
diff --git a/project-templates/python/alternative-data-universe-smartinsiderintentionuniverse/main.py b/project-templates/python/alternative-data-universe-smartinsiderintentionuniverse/main.py
index 0a8a4c585f..ca23551ca1 100644
--- a/project-templates/python/alternative-data-universe-smartinsiderintentionuniverse/main.py
+++ b/project-templates/python/alternative-data-universe-smartinsiderintentionuniverse/main.py
@@ -8,6 +8,7 @@ def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100000)
+ self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.DAILY
# Universe of large-cap US Equities announcing meaningful buyback intentions.
@@ -17,16 +18,18 @@ def initialize(self) -> None:
self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(9, 0, 0), self._rebalance)
def _select_assets(self, data: List[SmartInsiderIntentionUniverse]) -> List[Symbol]:
- # Keep $100M+ market-cap names announcing a buyback over 0.5% of shares.
+ # Keep names announcing a buyback over 0.5% of shares. (USDMarketCap is not
+ # populated for intention records, unlike SmartInsiderTransactionUniverse.)
return [d.symbol for d in data
- if d.percentage and d.usd_market_cap
- and d.percentage > 0.005 and d.usd_market_cap > 100000000]
+ if d.percentage and d.percentage > 0.005]
def _rebalance(self) -> None:
if not self._universe.selected:
return
-
- weight = 1 / len(self._universe.selected)
- targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
+ securities = [s for s in self._universe.selected if self.securities[s].price]
+ if not securities:
+ return
+ weight = min(1 / len(securities), 0.1)
+ targets = [PortfolioTarget(symbol, weight) for symbol in securities]
self.set_holdings(targets, liquidate_existing_holdings=True)
diff --git a/project-templates/python/alternative-data-universe-smartinsidertransactionuniverse/main.py b/project-templates/python/alternative-data-universe-smartinsidertransactionuniverse/main.py
index 62b73f2383..d1e82a4a33 100644
--- a/project-templates/python/alternative-data-universe-smartinsidertransactionuniverse/main.py
+++ b/project-templates/python/alternative-data-universe-smartinsidertransactionuniverse/main.py
@@ -8,6 +8,7 @@ def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100000)
+ self.settings.seed_initial_prices = True
self.universe_settings.resolution = Resolution.DAILY
# Universe of large-cap US Equities executing meaningful share buybacks.
@@ -25,8 +26,10 @@ def _select_assets(self, data: List[SmartInsiderTransactionUniverse]) -> List[Sy
def _rebalance(self) -> None:
if not self._universe.selected:
return
-
- weight = 1 / len(self._universe.selected)
- targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
+ securities = [s for s in self._universe.selected if self.securities[s].price]
+ if not securities:
+ return
+ weight = min(1 / len(securities), 0.1)
+ targets = [PortfolioTarget(symbol, weight) for symbol in securities]
self.set_holdings(targets, liquidate_existing_holdings=True)
diff --git a/project-templates/python/custom-indicator/main.py b/project-templates/python/custom-indicator/main.py
index fac808ba2f..140da03788 100644
--- a/project-templates/python/custom-indicator/main.py
+++ b/project-templates/python/custom-indicator/main.py
@@ -9,7 +9,7 @@ def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
# Request daily SPY data to feed the indicators to generate trade signals and trade.
- self._spy = self.add_equity("SPY")
+ self._spy = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.RAW)
# Create a custom money flow index to generate a trade signal.
self._custom_mfi = CustomMoneyFlowIndex(20)
# Warm up for immediate usage of indicators.