About Upcoming Earnings
The Upcoming Earnings dataset, provided by EOD Historical Data (EODHD), is a daily universe of US Equities with an earnings report publication in the upcoming 7 days. The data starts in January 1998 and is delivered on a daily frequency.
About EOD Historical Data
EOD Historical Data (EODHD) is a financial data provider based in France, and founded in April 2015. They focus on providing clean financial data, including stock prices, splits, dividends, fundamentals, macroeconomic indicators, technical indicators, and alternative data sources, through 24/7 API seamlessly. For more information about EODHD, visit https://eodhd.com/.
About QuantConnect
QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month.
Algorithm Example
class UpcomingEarningsExampleAlgorithm(QCAlgorithm):
options_by_symbol = {}
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 10, 1)
self.set_cash(100000)
# Seed the last price as price since we need to use the underlying price for option contract filtering when it join the universe.
self.set_security_initializer(BrokerageModelSecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices)))
# Trade on daily basis based on daily upcoming earnings signals.
self.universe_settings.resolution = Resolution.DAILY
# Option trading requires raw price for strike price comparison.
self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
# Universe consists of equities with upcoming earnings events.
self.add_universe(EODHDUpcomingEarnings, self.selection)
def selection(self, earnings: List[EODHDUpcomingEarnings]) -> List[Symbol]:
# We do not want to lock our fund too early, so filter for stocks is in lower volatility but will go up.
# Assuming 5 days before the earnings report publish is less volatile.
# We do not want depository due to their low liquidity.
return [d.symbol for d in earnings
if d.report_date <= self.time + timedelta(5)]
def on_securities_changed(self, changes: SecurityChanges) -> None:
# Actions only based on the equity universe changes.
for added in [security for security in changes.added_securities if security.type == SecurityType.EQUITY]:
# Select the option contracts to construct a straddle to trade the volatility.
call, put = self.select_option_contracts(added.symbol)
if not call or not put:
continue
self.options_by_symbol[added.symbol] = (call, put)
# Request the option contract data for trading.
call = self.add_option_contract(call).symbol
put = self.add_option_contract(put).symbol
# Long a straddle by shorting the selected ATM call and put.
self.combo_market_order([
Leg.create(call, 1),
Leg.create(put, 1)
],
1
)
# Actions only based on the equity universe changes.
for removed in [security for security in changes.removed_securities if security.type == SecurityType.EQUITY]:
# Liquidate any assigned position.
self.liquidate(removed.symbol)
# Liquidate the option positions and capitalize the volatility 1-day after the earnings announcement.
contracts = self.options_by_symbol.pop(removed.symbol, None)
if contracts:
for contract in contracts:
self.remove_option_contract(contract)
def select_option_contracts(self, underlying: Symbol) -> Tuple[Symbol, Symbol]:
# Get all tradable option contracts for filtering.
option_contract_list = self.option_chain(underlying)
# Expiry at least 30 days later to have a smaller theta to reduce time decay loss.
# Yet also be ensure liquidity over the volatility fluctuation hence we take the closet expiry after that.
long_expiries = [x for x in option_contract_list if x.id.date >= self.time + timedelta(30)]
if len(long_expiries) < 2:
return None, None
expiry = min(x.id.date for x in long_expiries)
filtered_contracts = [x for x in option_contract_list if x.id.date == expiry]
# Select ATM call and put to form a straddle for trading the volatility.
strike = sorted(filtered_contracts,
key=lambda x: abs(x.id.strike_price - self.securities[underlying].price))[0].id.strike_price
atm_contracts = [x for x in filtered_contracts if x.id.strike_price == strike]
if len(atm_contracts) < 2:
return None, None
atm_call = next(filter(lambda x: x.id.option_right == OptionRight.CALL, atm_contracts))
atm_put = next(filter(lambda x: x.id.option_right == OptionRight.PUT, atm_contracts))
return atm_call, atm_put
Example Applications
The Upcoming Earnings dataset provides timely notifications about earnings announcements, allowing traders to make capitalize on potential price movements and manage risks effectively. Examples include the following strategies:
- Short Straddle to trade on heightened volatility during earnings report.
- Filter universe for the stocks with or without upcoming earnings report to trade or avoid volatility.
- Hold the stocks with upcoming earnings estimated to be positive.
Pricing
Cloud Access
Using Upcoming Earnings data in the QuantConnect Cloud for your backtesting and live trading purposes.
Explore Other Datasets
CFD Data
Dataset by QuantConnect
US Interest Rate
Dataset by Federal Reserve Bank of St Louis
VIX Central Contango
Dataset by VIX Central