from AlgorithmImports import *
import pandas as pd
from datetime import datetime, timedelta
class ContinuousCompaniesQC500Algorithm(QCAlgorithm):
def Initialize(self) -> None:
self.SetStartDate(2006, 1, 1)
self.SetEndDate(2024, 12, 31)
self.SetCash(100000)
# Use QC500 universe
self.UniverseSettings.Resolution = Resolution.Daily
self._universe = self.AddUniverseSelection(QC500UniverseSelectionModel())
# Dictionary to track company existence
self.company_tracker = {}
# Check dates for continuous listing
self.check_dates = [
datetime(2006, 1, 1),
datetime(2007, 1, 1),
datetime(2008, 1, 1),
datetime(2009, 1, 1),
datetime(2010, 1, 1),
datetime(2011, 1, 1),
datetime(2012, 1, 1),
datetime(2013, 1, 1),
datetime(2014, 1, 1),
datetime(2015, 1, 1),
datetime(2016, 1, 1),
datetime(2017, 1, 1),
datetime(2018, 1, 1),
datetime(2019, 1, 1),
datetime(2020, 1, 1),
datetime(2021, 1, 1),
datetime(2022, 1, 1),
datetime(2023, 1, 1),
datetime(2024, 1, 1),
datetime(2025, 1, 1)
]
# Optimization: Prepare history request for all dates
self.history_cache = {}
def OnSecuritiesChanged(self, changes: SecurityChanges) -> None:
# Track when companies first appear in the universe
for security in changes.AddedSecurities:
if security.Symbol not in self.company_tracker:
self.company_tracker[security.Symbol] = {
'first_seen': self.Time,
'checked_dates': {}
}
def PrepareDateHistory(self):
# Optimization: Bulk history request for all check dates
symbols_to_check = list(self.company_tracker.keys())
for check_date in self.check_dates:
try:
# Request history for a single day around the check date
history = self.History(
symbols_to_check,
check_date,
check_date + timedelta(days=5), # Allow some buffer for non-trading days
Resolution.Daily
)
# Cache the history results
if not history.empty:
for symbol in symbols_to_check:
symbol_history = history.loc[history.index.get_level_values('symbol') == symbol]
if not symbol_history.empty:
if symbol not in self.history_cache:
self.history_cache[symbol] = {}
self.history_cache[symbol][check_date] = symbol_history
except Exception as e:
self.Debug(f"Error preparing history for {check_date}: {e}")
def OnEndOfAlgorithm(self):
# Prepare history cache first
self.PrepareDateHistory()
continuous_companies = []
for symbol, data in self.company_tracker.items():
exists_at_all_dates = True
for check_date in self.check_dates:
# Check if symbol has history for this date
if (symbol not in self.history_cache or
check_date not in self.history_cache[symbol]):
exists_at_all_dates = False
break
# Optional: Add additional filtering criteria
# For example, check if price is above a certain threshold
price_data = self.history_cache[symbol][check_date]
if price_data['close'].values[0] < 1: # Optional price filter
exists_at_all_dates = False
break
if exists_at_all_dates:
continuous_companies.append({
'Symbol': symbol.Value,
'FirstSeen': data['first_seen']
})
# Convert to DataFrame and save
if continuous_companies:
df = pd.DataFrame(continuous_companies)
filename = "continuous_companies_qc500_2006_2024.csv"
df.to_csv(filename, index=False)
self.Debug(f"Found {len(df)} companies continuously in QC500-like universe")
self.Debug(f"Companies: {[company['Symbol'] for company in continuous_companies]}")
else:
self.Debug("No companies found continuous throughout all check dates")from AlgorithmImports import *
from QuantConnect.DataSource import *
class TiingoNewsDataAlgorithm(QCAlgorithm):
current_holdings = 0
target_holdings = 0
word_scores = {'good': 1, 'great': 1, 'best': 1, 'growth': 1,
'bad': -1, 'terrible': -1, 'worst': -1, 'loss': -1}
def initialize(self) -> None:
self.set_start_date(2021, 1, 1)
self.set_end_date(2021, 6, 1)
self.set_cash(100000)
# Requesting data
self.aapl = self.add_equity("AAPL", Resolution.MINUTE).symbol
self.tiingo_symbol = self.add_data(TiingoNews, self.aapl).symbol
# Historical data
history = self.history(self.tiingo_symbol, 14, Resolution.DAILY)
self.debug(f"We got {len(history)} items from our history request")
def on_data(self, slice: Slice) -> None:
if slice.contains_key(self.tiingo_symbol):
# Assign a sentiment score to the news article
title_words = slice[self.tiingo_symbol].description.lower()
score = 0
for word, word_score in self.word_scores.items():
if word in title_words:
score += word_score
if score > 0:
self.target_holdings = 1
elif score < 0:
self.target_holdings = -1
# Buy or short sell if the sentiment has changed from our current holdings
if slice.contains_key(self.aapl) and self.current_holdings != self.target_holdings:
self.set_holdings(self.aapl, self.target_holdings)
self.current_holdings = self.target_holdings