Skip to main content

Market Calendars

Market calendars are an essential part of any analyst's daily rituals. Economic events and corporate actions provide near-term trading opportunities (or reasons to get out of the way) as expectations meet reality. The OpenBB Platform has a variety of calendars.

  • Economic
  • Earnings
  • Dividends
  • Splits
  • IPO/SPOs

Let's take a look at some use-cases.

note

Examples on this page will assume that the OpenBB Platform is installed, the Python environment is active, and the Python interface has been imported into the active session.

from openbb import obb
import pandas as pd

Economic Calendar

Details

The economic calendar aggregates global central bank and macroeconomic releases, it is located within the obb.economy module.

tip

Do not rely on the economic calendar for real-time updates. Times posted are scheduled by publishers and are estimates which do not reflect the actual time data is released to the public.

Timezone Considerations

There are subtle differences between providers, the main consideration will be the timestamp. FMP and TradingEconomics both return the calendar as UTC-0, while Nasdaq posts events in US/Eastern time. Of the three, only TradingEconomics provides a TZ-aware timestamp. The differences can be reconciled with a few lines of code.

To identify the issue, let's look at one event. First, from FMP:

fmp_df = obb.economy.calendar(provider="fmp", start_date="2023-11-19", end_date="2023-11-20").to_df()
fmp_df[fmp_df["event"].str.contains("20-Year Bond Auction")]
datecountryeventpreviousconsensusimportancecurrencychangechange_percent
2023-11-20 18:00:00US20-Year Bond Auction5.245nanLowUSDnan0

Then Nasdaq:

nasdaq_df = obb.economy.calendar(provider="nasdaq", start_date="2023-11-19", end_date="2023-11-20").to_df()
nasdaq_df[nasdaq_df["event"].str.contains("20-Year Bond Auction")]
datecountryeventactualpreviousconsensusdescription
2023-11-20 13:00:00United States20-Year Bond Auction-5.245%-The figures displayed in the calendar represent the yield on the Treasury Bond auctioned.

Now let's convert the FMP timestamp to US/Eastern time.

from datetime import time

fmp_df.index = fmp_df.index.map(
lambda dt: dt.tz_localize("UTC")
.tz_convert("America/New_York")
if dt.time() != time(0, 0, 0)
else dt.tz_localize("America/New_York")
)
fmp_df[fmp_df["event"].str.contains("20-Year Bond Auction")]
datecountryeventpreviousconsensusimportancecurrencychangechange_percent
2023-11-20 13:00:00-05:00US20-Year Bond Auction5.245nanLowUSDnan0

Timestamps can be a factor with start/end dates because the calendar day will roll over at midnight, moving the date. Converting the timestamp will overcome this, but be aware of when the time is 00:00:00, signifying an all-day event like a holiday.

An exception was added in the code above to maintain the time where applicable, instead of rolling it back five hours.

For these reasons, among others, it is important for users to know and understand their data intimately.

Filtering by Event

The providers do not have a pre-request filter for a specific event. TradingEconomics does have categories, like 'government', but that does not focus it on any particular release. To find something like PMI reports, search for it post-request.

FMP allows queries to this endpoint to be a maximum width of three months. To get the year-to-date events, requests will need to loop. The code below will do that, filter the results for ISM Manufacturing New Orders, and display the table of hits.

ISM New Orders


start_dates = ["2023-01-04", "2023-04-01", "2023-07-01", "2023-10-01"]
end_dates = ["2023-03-31", "2023-06-30", "2023-09-30", "2023-12-30"]
results = []

for i in range(0, len(start_dates)):
_data = (
obb.economy.calendar(provider="fmp", start_date=start_dates[i], end_date=end_dates[i])
.model_dump()["results"]
)
results.extend(_data)
events = pd.DataFrame.from_records(results).set_index("date").sort_index()

events[events["event"].str.contains("ISM Manufacturing New Orders")]
datecountryeventactualpreviousconsensusimportancecurrencychangechange_percent
2023-01-04 15:00:00USISM Manufacturing New Orders (Dec)45.247.2nanLowUSD-2-4.237
2023-02-01 15:00:00USISM Manufacturing New Orders (Jan)42.545.1nanLowUSD-2.6-5.765
2023-03-01 20:00:00USISM Manufacturing New Orders (Feb)4742.5nanLowUSD4.510.588
2023-04-03 18:00:00USISM Manufacturing New Orders (Mar)44.347nanLowUSD-2.7-5.745
2023-05-01 18:00:00USISM Manufacturing New Orders (Apr)45.744.3nanLowUSD1.43.16
2023-06-01 14:00:00USISM Manufacturing New Orders (May)42.645.7nanLowUSD-3.1-6.783
2023-07-03 18:00:00USISM Manufacturing New Orders (Jun)45.642.6nanLowUSD37.042
2023-08-01 18:00:00USISM Manufacturing New Orders (Jul)47.345.644LowUSD1.73.728
2023-09-01 14:00:00USISM Manufacturing New Orders (Aug)46.847.3nanLowUSD-0.5-1.057
2023-10-02 14:00:00USISM Manufacturing New Orders (Sep)49.246.8nanLowUSD2.45.128
2023-11-01 14:00:00USISM Manufacturing New Orders (Oct)45.549.2nanLowUSD-3.7-7.52
2023-12-01 15:00:00USISM Manufacturing New Orders (Nov)nan45.5nanLowUSDnan0

Earnings Calendar

Details

The earnings calendar works in a similar way. For companies outside of the US, try the openbb-fmp provider.

calendar = (
obb.equity.calendar.earnings(
provider="fmp",
start_date="2023-11-20",
end_date="2023-11-24"
).to_df()
)

This returned 1,234 results, but let's filter it down to those companies with analysts estimates, and display the top ten by EPS consensus.

(
calendar[calendar["eps_consensus"].notnull()
& calendar["revenue_consensus"].notnull()]
.sort_values(by="eps_consensus", ascending=False)
.head(10)
)
report_datesymboleps_consensusactual_epsactual_revenuerevenue_consensusperiod_endingreporting_timeupdated_date
2023-11-22CAP.SN279.3nannan6909550000002023-09-30bmo2023-11-19
2023-11-20ABDP.L56.4nannan1060000002023-09-29bmo2023-11-19
2023-11-234206.T56.3nannan622000002023-09-30bmo2023-11-19
2023-11-22DE7.58nannan129096000002023-10-29bmo2023-11-19
2023-11-21NVDA3.34nannan151946000002023-10-29amc2023-11-19
2023-11-21LOW3.1nannan210597000002023-11-03bmo2023-11-19
2023-11-20MOH.AT2.48nannan30304800002023-09-30bmo2023-11-19
2023-11-20SJM2.47nannan19478000002023-10-30bmo2023-11-19
2023-11-21BIDU2.45nannan47355800002023-09-30bmo2023-11-19
2023-11-21DKS2.42nannan29485700002023-10-28bmo2023-11-19
tip

EPS values are reported in the currency of the exchange listing price, direct comparisons are not viable across domiciles without a conversion factor.

Dividend Calendar

Details

The dividend calendar uses start/end dates that reflect the ex-dividend date - the date when it begins trading without dividend rights.

Aside from the notable dates, the information returned tells you only the amount paid. Calculating the yield requires more data.

note
  • Nasdaq provides a field for 'annualized_amount', which makes it easier to calculate a dividend yield.

  • The openbb-nasdaq provider has US-only data for this endpoint.

  • The same markets covered by FMP's earnings calendar are included in their dividend calendar.

Calculate Dividend Yield

The ten highest-payments going ex-div between November 20-24 are shown below.

With T+2 settlement, a purchase needs to occur two days prior to the record date for payment eligibility. The dividend yield is the current payment annualized as a percent of the asset's price.

dividends = (
obb.equity.calendar.dividend(
provider="nasdaq",
start_date="2023-11-20",
end_date="2023-11-24",
).to_df()
.drop_duplicates(subset="symbol")
.sort_values("amount", ascending=False)
.reset_index()
.set_index("symbol")
.head(10)
)

symbols = dividends.index.tolist()
prices = (
obb.equity.price.quote(symbols, provider="fmp").to_df()
.reset_index()
.set_index("symbol")["price"]
)
dividends["price"] = prices

dividends["yield"] = (
round((dividends["annualized_amount"]/dividends["price"])*100, 4)
)

(
dividends[["record_date", "payment_date", "amount", "annualized_amount", "price", "yield"]]
.sort_values("yield", ascending=False)
)
symbolrecord_datepayment_dateamountannualized_amountpriceyield
USOI2023-11-212023-11-271.858816.13475.7321.3046
ATCD2023-11-212023-12-2660.1460.1412354.8696
GLDI2023-11-212023-11-271.51534.8216141.83.4003
CHTM2023-11-212023-12-2659.6259.621856.953.2106
CMI2023-11-242023-12-071.686.72225.52.98
KLIB2023-11-242023-12-152.14.21442.9167
SNA2023-11-212023-12-111.867.44277.762.6786
NOC2023-11-272023-12-131.877.48464.171.6115
CBCYB2023-11-242023-12-013.7586471.2365
CBCY2023-11-242023-12-013.7586601.2121

IPO Calendar

Details

The IPO calendar shows events based on their status - ["upcoming", "priced", "withdrawn"] - and Intrinio provides a filter for the min/max dollar amount offered.

note

The data from both Intrinio and Nasdaq is US-only, both relying on the SEC for filing information.

Use the status parameter to find announcements in different stages of the cycle.

Upcoming

The initial public offerings that are confirmed to be coming to market are categorized as 'upcoming'. The number of companies going public at any given time will depend on market cycles.

obb.equity.calendar.ipo(provider="nasdaq", status="upcoming").to_df()
symbolnameoffer_amountshare_countexpected_price_dateidexchangeshare_price
DOCODocola, Inc.823500410608702023-11-21995278-107909NASDAQ Capital5.75-6.75

Withdrawn

A withdrawn status might be the result of a SPAC unwinding after failing to merge with a company.

obb.equity.calendar.ipo(provider="nasdaq", status="withdrawn").to_df().tail(3)
withdraw_datenameoffer_amountshare_countfiled_dateid
2023-11-09Arago Acquisition Corp.86250000.075000002022-05-061214792-102968
2023-11-13CW Petroleum Corp17249995.531578942022-06-021055531-103241
2023-11-13Tiga Acquisition Corp. II230000000.0200000002021-02-261148285-96307

SPO

SPOs, secondary public offerings, are shares being sold by investors after an IPO. The money does not go to the company, but directly to the investor selling shares into the market. The openbb-nasdaq provider has an additional boolean parameter, is_spo. By default, year-to-date data is returned.

obb.equity.calendar.ipo(provider="nasdaq", is_spo=True).to_df().tail(1)
symbolipo_datenameoffer_amountshare_countdeal_statusidexchangeshare_price
SKWD2023-11-16Skyward Specialty Insurance Group, Inc.152500000.05000000Priced854131-108262NASDAQ Global Select30.5