diff --git a/project-templates/csharp/alternative-data-universe-brainsentimentindicatoruniverse/Main.cs b/project-templates/csharp/alternative-data-universe-brainsentimentindicatoruniverse/Main.cs index fbe6afce81..6a1ae2e8bf 100644 --- a/project-templates/csharp/alternative-data-universe-brainsentimentindicatoruniverse/Main.cs +++ b/project-templates/csharp/alternative-data-universe-brainsentimentindicatoruniverse/Main.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using QuantConnect.Algorithm.Framework.Portfolio; -using QuantConnect.Data.Fundamental; using QuantConnect.Data.UniverseSelection; using QuantConnect.DataSource; @@ -10,7 +9,6 @@ namespace QuantConnect.Algorithm.CSharp { public class BrainSentimentIndicatorChainedUniverseAlgorithm : QCAlgorithm { - private List _fundamental = []; private Universe _universe; public override void Initialize() @@ -20,24 +18,13 @@ public override void Initialize() SetCash(100000); Settings.SeedInitialPrices = true; UniverseSettings.Resolution = Resolution.Daily; - // Add a fundamental universe to track the most liquid US Equities by dollar volume. - AddUniverse(fundamental => - { - _fundamental = fundamental - .OrderBy(c => c.DollarVolume) - .TakeLast(100) - .Select(c => c.Symbol) - .ToList(); - return Universe.Unchanged; - }); - // Add a Brain Sentiment universe, restricted to high-sentiment names within the fundamental list. + // Add a Brain Sentiment universe, restricted to high-sentiment names with strong coverage. _universe = AddUniverse( - // Keep names with both active mention coverage and positive 7-day sentiment. + // Keep names with both active mention coverage 15+ articles and positive 7-day sentiment above 0.5. altCoarse => altCoarse .OfType() - .Where(d => d.TotalArticleMentions7Days > 0m && d.Sentiment7Days > 0m) + .Where(d => d.TotalArticleMentions7Days > 15m && d.Sentiment7Days > 0.5m) .Select(d => d.Symbol) - .Intersect(_fundamental) ); // Rebalance every day at 9am. Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance); diff --git a/project-templates/csharp/alternative-data-universe-brainstockrankinguniverse/Main.cs b/project-templates/csharp/alternative-data-universe-brainstockrankinguniverse/Main.cs index 87e3c90ec2..a2dcad0556 100644 --- a/project-templates/csharp/alternative-data-universe-brainstockrankinguniverse/Main.cs +++ b/project-templates/csharp/alternative-data-universe-brainstockrankinguniverse/Main.cs @@ -9,7 +9,6 @@ namespace QuantConnect.Algorithm.CSharp public class BrainStockRankingUniverseAlgorithm : QCAlgorithm { private Universe _universe; - private List _fundamental = []; public override void Initialize() { @@ -17,24 +16,13 @@ public override void Initialize() SetEndDate(2024, 12, 31); SetCash(100000); Settings.SeedInitialPrices = true; - // Add a fundamental universe to track the most liquid US equities by dollar volume. - AddUniverse(fundamental => - { - // Store the top 50 symbols by dollar volume for use in the alt-data universe. - _fundamental = fundamental - .OrderBy(f => f.DollarVolume) - .TakeLast(50) - .Select(f => f.Symbol) - .ToList(); - return Universe.Unchanged; - }); - // Add a Brain Stock Ranking universe, restricted to high-ranking names within the fundamental list. + // Add a Brain Stock Ranking universe, restricted to high-ranking names with strong multi-horizon signals. _universe = AddUniverse( + // Filter for stocks with positive rankings across 2-day, 3-day, and 5-day horizons. data => data .OfType() - .Where(d => d.Rank2Days > 0m && d.Rank3Days > 0m && d.Rank5Days > 0m) + .Where(d => d.Rank2Days > 0.05m && d.Rank3Days > 0.05m && d.Rank5Days > 0.05m) .Select(d => d.Symbol) - .Where(symbol => _fundamental.Contains(symbol)) ); // Schedule daily rebalancing at 9:00 AM before market open. Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0), Rebalance); diff --git a/project-templates/csharp/alternative-data-universe-eodhdupcomingdividends/Main.cs b/project-templates/csharp/alternative-data-universe-eodhdupcomingdividends/Main.cs index 078e84a504..c49100421a 100644 --- a/project-templates/csharp/alternative-data-universe-eodhdupcomingdividends/Main.cs +++ b/project-templates/csharp/alternative-data-universe-eodhdupcomingdividends/Main.cs @@ -14,14 +14,15 @@ public override void Initialize() SetStartDate(2024, 9, 1); SetEndDate(2024, 12, 31); SetCash(100000); + Settings.SeedInitialPrices = true; - UniverseSettings.Resolution = Resolution.Daily; + UniverseSettings.Resolution = Resolution.Hour; // Universe of US Equities going ex-dividend in the next day with a meaningful payout. _universe = AddUniverse(data => { - // Keep names with a dividend over $0.05 paying within one day. + // Keep names with a dividend over $0.75 paying within one day. return from d in data.OfType() - where d.DividendDate <= Time.AddDays(1) && d.Dividend > 0.05m + where d.DividendDate <= Time.AddDays(1) && d.Dividend > 0.75m select d.Symbol; }); @@ -36,8 +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 = 1m / securities.Count; + var targets = securities .Select(symbol => new PortfolioTarget(symbol, weight)) .ToList(); diff --git a/project-templates/csharp/alternative-data-universe-eodhdupcomingearnings/Main.cs b/project-templates/csharp/alternative-data-universe-eodhdupcomingearnings/Main.cs index 2737b1b01b..31d972b3ec 100644 --- a/project-templates/csharp/alternative-data-universe-eodhdupcomingearnings/Main.cs +++ b/project-templates/csharp/alternative-data-universe-eodhdupcomingearnings/Main.cs @@ -14,19 +14,20 @@ 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 reporting earnings in the next 3 days with a positive estimate. + UniverseSettings.Resolution = Resolution.Hour; + // Universe of US Equities reporting earnings in the next 3 days with estimate > 1.5. _universe = AddUniverse(data => { - // Keep names with a positive analyst estimate ahead of the report. + // Keep names with an analyst estimate over 1.5 ahead of the report. return from d in data.OfType() - where d.ReportDate <= Time.AddDays(3) && d.Estimate > 0m + where d.ReportDate <= Time.AddDays(3) && d.Estimate > 1.5m select d.Symbol; }); // Rebalance shortly after the open so today's universe is locked in. - Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 0, 0), Rebalance); + Schedule.On(DateRules.EveryDay("SPY"), TimeRules.At(9, 31, 0), Rebalance); } private void Rebalance() @@ -36,8 +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 = 1m / securities.Count; + var targets = securities .Select(symbol => new PortfolioTarget(symbol, weight)) .ToList(); diff --git a/project-templates/python/alternative-data-universe-brainsentimentindicatoruniverse/main.py b/project-templates/python/alternative-data-universe-brainsentimentindicatoruniverse/main.py index f983a888f8..d1da2ecbe2 100644 --- a/project-templates/python/alternative-data-universe-brainsentimentindicatoruniverse/main.py +++ b/project-templates/python/alternative-data-universe-brainsentimentindicatoruniverse/main.py @@ -4,7 +4,6 @@ class BrainSentimentIndicatorUniverseAlgorithm(QCAlgorithm): - _fundamental: list[Symbol] = [] def initialize(self) -> None: self.set_start_date(2024, 9, 1) @@ -12,9 +11,7 @@ def initialize(self) -> None: self.set_cash(100_000) self.settings.seed_initial_prices = True self.universe_settings.resolution = Resolution.DAILY - # Add a fundamental universe to track the most liquid US Equities by dollar volume. - self.add_universe(self._fundamental_filter) - # Add a Brain Sentiment universe, restricted to high-sentiment names within the fundamental list. + # Add a Brain Sentiment universe, restricted to high-sentiment names with strong coverage. self._universe = self.add_universe(BrainSentimentIndicatorUniverse, self._select_assets) # Rebalance every day at 9am. self.schedule.on( @@ -23,16 +20,11 @@ def initialize(self) -> None: self._rebalance ) - def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse: - self._fundamental = [f.symbol for f in sorted(fundamental, key=lambda f: f.dollar_volume)[-100:]] - return Universe.UNCHANGED - def _select_assets(self, data: List[BrainSentimentIndicatorUniverse]) -> List[Symbol]: - # Keep names with both active mention coverage and positive 7-day sentiment. - alt = [d.symbol for d in data - 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 mention coverage 15+ articles and positive 7-day sentiment above 0.5. + return [d.symbol for d in data + if d.total_article_mentions_7_days and d.total_article_mentions_7_days > 15 and + d.sentiment_7_days and d.sentiment_7_days > 0.5] def _rebalance(self) -> None: if not self._universe.selected: diff --git a/project-templates/python/alternative-data-universe-brainstockrankinguniverse/main.py b/project-templates/python/alternative-data-universe-brainstockrankinguniverse/main.py index 4ce77efc13..7d947320f9 100644 --- a/project-templates/python/alternative-data-universe-brainstockrankinguniverse/main.py +++ b/project-templates/python/alternative-data-universe-brainstockrankinguniverse/main.py @@ -4,16 +4,13 @@ class BrainStockRankingUniverseAlgorithm(QCAlgorithm): - _fundamental: list[Symbol] = [] def initialize(self) -> None: self.set_start_date(2024, 9, 1) self.set_end_date(2024, 12, 31) self.set_cash(100_000) self.settings.seed_initial_prices = True - # Add a fundamental universe to track the most liquid US equities by dollar volume. - self.add_universe(self._fundamental_filter) - # Add a Brain Stock Ranking universe, restricted to high-ranking names within the fundamental list. + # Add a Brain Stock Ranking universe, restricted to high-ranking names with strong multi-horizon signals. self._universe = self.add_universe(BrainStockRankingUniverse, self._select_assets) # Schedule daily rebalancing at 9:00 AM before market open. self.schedule.on( @@ -22,18 +19,12 @@ def initialize(self) -> None: self._rebalance ) - def _fundamental_filter(self, fundamental: List[Fundamental]) -> Universe.UnchangedUniverse: - # Store the top 50 symbols by dollar volume for use in the alt-data universe. - self._fundamental = [f.symbol for f in sorted(fundamental, key=lambda f: f.dollar_volume)[-50:]] - return Universe.UNCHANGED - def _select_assets(self, data: List[BrainStockRankingUniverse]) -> List[Symbol]: # Filter for stocks with positive rankings across 2-day, 3-day, and 5-day horizons. - alt = [d.symbol for d in data - 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] + return [d.symbol for d in data + if d.rank_2_days and d.rank_2_days > 0.05 and + d.rank_3_days and d.rank_3_days > 0.05 and + d.rank_5_days and d.rank_5_days > 0.05] def _rebalance(self) -> None: if not self._universe.selected: diff --git a/project-templates/python/alternative-data-universe-coingeckouniverse/main.py b/project-templates/python/alternative-data-universe-coingeckouniverse/main.py index 1b826772a8..df3ca58ceb 100644 --- a/project-templates/python/alternative-data-universe-coingeckouniverse/main.py +++ b/project-templates/python/alternative-data-universe-coingeckouniverse/main.py @@ -41,7 +41,7 @@ def _rebalance(self) -> None: if not self._universe.selected: return # Filter for securities with valid prices. - securities = [s for s in self._universe.selected if self.securities[s].price > 0] + securities = [s for s in self._universe.selected if self.securities[s].price] if not securities: return weight = 1 / len(securities) diff --git a/project-templates/python/alternative-data-universe-eodhdupcomingdividends/main.py b/project-templates/python/alternative-data-universe-eodhdupcomingdividends/main.py index ed2694dd19..af9dcec609 100644 --- a/project-templates/python/alternative-data-universe-eodhdupcomingdividends/main.py +++ b/project-templates/python/alternative-data-universe-eodhdupcomingdividends/main.py @@ -8,8 +8,8 @@ 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.resolution = Resolution.DAILY + self.settings.seed_initial_prices = True + self.universe_settings.resolution = Resolution.HOUR # Universe of US Equities going ex-dividend in the next day with a meaningful payout. self._universe = self.add_universe(EODHDUpcomingDividends, self._select_assets) @@ -17,16 +17,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[EODHDUpcomingDividends]) -> List[Symbol]: - # Keep names with a dividend over $0.05 paying within one day. + # Keep names with a dividend over $0.75 paying within one day. return [d.symbol for d in data if d.dividend_date and d.dividend - and d.dividend_date <= self.time + timedelta(1) and d.dividend > 0.05] + and d.dividend_date <= self.time + timedelta(1) and d.dividend > 0.75] 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 = 1 / len(securities) + 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-eodhdupcomingearnings/main.py b/project-templates/python/alternative-data-universe-eodhdupcomingearnings/main.py index 7e7597da05..be8e4b857e 100644 --- a/project-templates/python/alternative-data-universe-eodhdupcomingearnings/main.py +++ b/project-templates/python/alternative-data-universe-eodhdupcomingearnings/main.py @@ -8,25 +8,27 @@ 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.resolution = Resolution.DAILY - # Universe of US Equities reporting earnings in the next 3 days with a positive estimate. + self.settings.seed_initial_prices = True + self.universe_settings.resolution = Resolution.HOUR + # Universe of US Equities reporting earnings in the next 3 days with estimate > 1.5. self._universe = self.add_universe(EODHDUpcomingEarnings, self._select_assets) # Rebalance shortly after the open so today's universe is locked in. - self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(9, 0, 0), self._rebalance) + self.schedule.on(self.date_rules.every_day("SPY"), self.time_rules.at(9, 31, 0), self._rebalance) def _select_assets(self, data: List[EODHDUpcomingEarnings]) -> List[Symbol]: - # Keep names with a positive analyst estimate ahead of the report. + # Keep names with an analyst estimate over 1.5 ahead of the report. return [d.symbol for d in data - if d.report_date and d.estimate - and d.report_date <= self.time + timedelta(3) and d.estimate > 0] + if d.report_date and d.estimate and + d.report_date <= self.time + timedelta(3) and d.estimate > 1.5] 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 = 1 / len(securities) + targets = [PortfolioTarget(symbol, weight) for symbol in securities] self.set_holdings(targets, liquidate_existing_holdings=True)