Earnings Events Analysis#
This section contains 6 examples for Events using the onetick-py.
Each example is a self-contained script that can be run against the OneTick Cloud sample databases.
# onetick-py WebAPI configuration for OneTick Cloud
import os
os.environ['OTP_WEBAPI'] = '1'
os.environ['OTP_HTTP_ADDRESS'] = 'https://rest.cloud.onetick.com'
os.environ['OTP_ACCESS_TOKEN_URL'] = 'https://cloud-auth.parent.onetick.com/realms/OMD/protocol/openid-connect/token'
os.environ['OTP_CLIENT_ID'] = '__FILL_IN__'
os.environ['OTP_CLIENT_SECRET'] = '__FILL_IN__'
Earnings announcements are recorded in the EVENT tick type
and can be combined with market data to analyze market reactions and trading patterns around these events.
Event Data Sources#
Earnings announcement events are available in the daily market data databases:
US_COMP_DAILY/EVENT- US earnings events
Event Types#
The EVENT tick type records two primary event types, held in the EVENT_TYPE field:
EARNING_DATE- Earnings announcement datesCOMPANY_CONFERENCE_CALL- Scheduled conference call dates
These events are useful for analyzing market behavior around significant corporate announcements.
Earnings Event History for Specified Symbol#
Retrieve all earnings events recorded for a specific symbol within a time range.
This shows all historical earnings announcements for a company.
import onetick.py as otp
data = otp.DataSource(db='US_COMP_DAILY', tick_type='EVENT')
result = otp.run(data,
start=otp.dt(2026, 1, 1),
end=otp.dt(2026, 6, 12),
timezone='America/New_York',
symbols='CSCO')
result
| Time | EVENT_TYPE | EVENT_CONDITION | OMDSEQ | |
|---|---|---|---|---|
| 0 | 2026-02-11 16:05:00 | EARNING_DATE | 2 | |
| 1 | 2026-02-11 16:30:00 | COMPANY_CONFERENCE_CALL | 6 | |
| 2 | 2026-05-13 16:05:00 | EARNING_DATE | 4 | |
| 3 | 2026-05-13 16:30:00 | COMPANY_CONFERENCE_CALL | 11 |
Earnings Event History for all US Companies across a time range#
Retrieve all earnings events across every symbol in the database within a specified time range,
by merging across otp.Symbols, the equivalent of SQL’s SYMBOL_NAME LIKE '%'.
This provides a comprehensive view of earnings announcements during a particular period.
identify_input_ts adds the SYMBOL_NAME of each tick to the output.
import onetick.py as otp
data = otp.DataSource(db='US_COMP_DAILY', tick_type='EVENT')
# Merge the events for every symbol in the database into a single stream.
# identify_input_ts adds the SYMBOL_NAME of each tick to the output.
data = otp.merge([data],
symbols=otp.Symbols(db='US_COMP_DAILY', for_tick_type='EVENT'),
identify_input_ts=True)
result = otp.run(data,
start=otp.dt(2024, 1, 1),
end=otp.dt(2024, 1, 5),
timezone='America/New_York')
result
| Time | EVENT_CONDITION | EVENT_TYPE | OMDSEQ | SYMBOL_NAME | TICK_TYPE | |
|---|---|---|---|---|---|---|
| 0 | 2024-01-03 08:00:00 | EARNING_DATE | 0 | UNF | EVENT | |
| 1 | 2024-01-03 09:00:00 | COMPANY_CONFERENCE_CALL | 0 | UNF | EVENT | |
| 2 | 2024-01-03 16:05:00 | EARNING_DATE | 0 | RGP | EVENT | |
| 3 | 2024-01-03 16:05:00 | EARNING_DATE | 1 | CALM | EVENT | |
| 4 | 2024-01-03 16:06:00 | EARNING_DATE | 0 | SLP | EVENT | |
| ... | ... | ... | ... | ... | ... | ... |
| 17 | 2024-01-04 16:03:00 | EARNING_DATE | 0 | FC | EVENT | |
| 18 | 2024-01-04 16:05:00 | EARNING_DATE | 0 | KRUS | EVENT | |
| 19 | 2024-01-04 17:00:00 | COMPANY_CONFERENCE_CALL | 0 | KRUS | EVENT | |
| 20 | 2024-01-04 17:00:00 | COMPANY_CONFERENCE_CALL | 1 | FC | EVENT | |
| 21 | 2024-01-04 19:00:00 | EARNING_DATE | 0 | STZ | EVENT |
22 rows × 6 columns
Joining Daily Pricing to US Earning Events#
Correlate daily pricing data with earnings events to analyze closing prices and volume
on earnings announcement dates.
Earnings events (excluding conference calls) are joined to the daily price/volume record
for the same symbol with otp.join, keyed on the date.
As closing prices and events occur at different times of day,
both sides are truncated to the day with the
.dt.date_trunc
accessor before joining.
A left outer join keeps every daily record, with EVENT_TYPE populated only on event days.
import onetick.py as otp
# Daily pricing, filtered to the composite (empty EXCHANGE).
day = otp.DataSource(db='US_COMP_DAILY', tick_type='DAY')
day = day.where(day['EXCHANGE'] == '')
day = day[['CLOSE', 'VOLUME']]
# Earnings events only, excluding the conference calls.
event = otp.DataSource(db='US_COMP_DAILY', tick_type='EVENT',
schema_policy='manual', schema={'EVENT_TYPE': str})
event = event.where(event['EVENT_TYPE'] == 'EARNING_DATE')
event = event[['EVENT_TYPE']]
# Truncate both sides to the day so the differing intraday times still match.
day['DAY_KEY'] = day['TIMESTAMP'].dt.date_trunc('day')
event['DAY_KEY'] = event['TIMESTAMP'].dt.date_trunc('day')
# Left outer join keeps every daily record, with EVENT_TYPE populated only on event days.
data = otp.join(day, event, on=day['DAY_KEY'] == event['DAY_KEY'], how='left_outer')
data = data[['CLOSE', 'VOLUME', 'EVENT_TYPE']]
result = otp.run(data,
start=otp.dt(2024, 1, 1),
end=otp.dt(2024, 4, 1),
timezone='America/New_York',
symbols='CSCO')
result
| Time | CLOSE | VOLUME | EVENT_TYPE | |
|---|---|---|---|---|
| 0 | 2024-01-02 20:15:00 | 50.51 | 20242939 | |
| 1 | 2024-01-03 20:15:00 | 50.51 | 20303875 | |
| 2 | 2024-01-04 20:15:00 | 50.08 | 18134121 | |
| 3 | 2024-01-05 20:15:00 | 50.09 | 13989287 | |
| 4 | 2024-01-08 20:15:00 | 50.46 | 18070293 | |
| ... | ... | ... | ... | ... |
| 56 | 2024-03-22 20:15:00 | 49.78 | 15022861 | |
| 57 | 2024-03-25 20:15:00 | 49.68 | 16191164 | |
| 58 | 2024-03-26 20:15:00 | 49.55 | 13842923 | |
| 59 | 2024-03-27 20:15:00 | 49.77 | 17230958 | |
| 60 | 2024-03-28 20:15:00 | 49.91 | 18139735 |
61 rows × 4 columns
Combining or Unioning Daily Pricing and US Earnings Events#
Union daily price data with earnings events, creating a combined dataset that shows both daily price bars and
discrete event occurrences, using otp.merge.
This is useful for time series visualization and analysis spanning both continuous pricing and discrete events.
The output schema is standardized across both branches:
setting CLOSE as otp.nan and VOLUME as 0 for the event rows,
and EVENT_TYPE as an empty otp.string[40] for the daily pricing rows.
import onetick.py as otp
# Daily pricing, filtered to the composite (empty EXCHANGE).
day = otp.DataSource(db='US_COMP_DAILY', tick_type='DAY')
day = day.where(day['EXCHANGE'] == '')
day = day[['CLOSE', 'VOLUME']]
day['EVENT'] = 0
day['EVENT_TYPE'] = otp.string[40]('')
# Earnings events only, shaped to the same schema as the daily pricing.
event = otp.DataSource(db='US_COMP_DAILY', tick_type='EVENT',
schema_policy='manual', schema={'EVENT_TYPE': otp.string[40]})
event = event.where(event['EVENT_TYPE'] == 'EARNING_DATE')
event['CLOSE'] = otp.nan
event['VOLUME'] = 0
event['EVENT'] = 1
event = event[['CLOSE', 'VOLUME', 'EVENT', 'EVENT_TYPE']]
# Union the two streams.
data = otp.merge([day, event])
result = otp.run(data,
start=otp.dt(2024, 1, 1),
end=otp.dt(2024, 4, 1),
timezone='America/New_York',
symbols='CSCO')
result
| Time | CLOSE | VOLUME | EVENT | EVENT_TYPE | |
|---|---|---|---|---|---|
| 0 | 2024-01-02 20:15:00 | 50.51 | 20242939 | 0 | |
| 1 | 2024-01-03 20:15:00 | 50.51 | 20303875 | 0 | |
| 2 | 2024-01-04 20:15:00 | 50.08 | 18134121 | 0 | |
| 3 | 2024-01-05 20:15:00 | 50.09 | 13989287 | 0 | |
| 4 | 2024-01-08 20:15:00 | 50.46 | 18070293 | 0 | |
| ... | ... | ... | ... | ... | ... |
| 57 | 2024-03-22 20:15:00 | 49.78 | 15022861 | 0 | |
| 58 | 2024-03-25 20:15:00 | 49.68 | 16191164 | 0 | |
| 59 | 2024-03-26 20:15:00 | 49.55 | 13842923 | 0 | |
| 60 | 2024-03-27 20:15:00 | 49.77 | 17230958 | 0 | |
| 61 | 2024-03-28 20:15:00 | 49.91 | 18139735 | 0 |
62 rows × 5 columns
Combining or Unioning 1 Minute Trade Bars and US Earnings Events#
Merge pre-calculated 1 minute trade bar data with earnings events on the same day,
allowing analysis of intraday price movement patterns around earnings announcements,
using otp.merge.
The output schema is standardized across both branches:
setting LAST as otp.nan and VOLUME as 0 for the event rows,
and EVENT_TYPE as an empty otp.string[40] for the bar rows.
import onetick.py as otp
# Pre-calculated 1 minute trade bars.
bars = otp.DataSource(db='US_COMP_BARS', tick_type='TRD_1M')
bars = bars[['LAST', 'VOLUME']]
bars['EVENT'] = 0
bars['EVENT_TYPE'] = otp.string[40]('')
# Earnings events only, shaped to the same schema as the bars.
event = otp.DataSource(db='US_COMP_DAILY', tick_type='EVENT',
schema_policy='manual', schema={'EVENT_TYPE': otp.string[40]})
event = event.where(event['EVENT_TYPE'] == 'EARNING_DATE')
event['LAST'] = otp.nan
event['VOLUME'] = 0
event['EVENT'] = 1
event = event[['LAST', 'VOLUME', 'EVENT', 'EVENT_TYPE']]
# Union the two streams.
data = otp.merge([bars, event])
result = otp.run(data,
start=otp.dt(2024, 2, 14),
end=otp.dt(2024, 2, 15),
timezone='America/New_York',
symbols='CSCO')
result
| Time | LAST | VOLUME | EVENT | EVENT_TYPE | |
|---|---|---|---|---|---|
| 0 | 2024-02-14 05:08:00 | 49.74 | 400 | 0 | |
| 1 | 2024-02-14 05:09:00 | 49.74 | 0 | 0 | |
| 2 | 2024-02-14 05:10:00 | 49.74 | 0 | 0 | |
| 3 | 2024-02-14 05:11:00 | 49.74 | 0 | 0 | |
| 4 | 2024-02-14 05:12:00 | 49.74 | 0 | 0 | |
| ... | ... | ... | ... | ... | ... |
| 894 | 2024-02-14 20:01:00 | 47.63 | 0 | 0 | |
| 895 | 2024-02-14 20:02:00 | 47.63 | 0 | 0 | |
| 896 | 2024-02-14 20:03:00 | 47.63 | 0 | 0 | |
| 897 | 2024-02-14 20:04:00 | 47.63 | 0 | 0 | |
| 898 | 2024-02-14 20:05:00 | 47.63 | 0 | 0 |
899 rows × 5 columns
Combining or Unioning Trades and US Earnings Events#
Combine individual trade data with earnings events into a unified stream, creating a single data source that
captures both transaction-level activity and corporate announcements, using otp.merge.
The output schema is standardized across both branches:
setting PRICE as otp.nan and SIZE as 0 for the event rows,
and EVENT_TYPE as an empty otp.string[40] for the trade rows.
import onetick.py as otp
# Trades from the US Composite.
trd = otp.DataSource(db='US_COMP', tick_type='TRD')
trd = trd[['PRICE', 'SIZE']]
trd['EVENT'] = 0
trd['EVENT_TYPE'] = otp.string[40]('')
# Earnings events only, shaped to the same schema as the trades.
event = otp.DataSource(db='US_COMP_DAILY', tick_type='EVENT',
schema_policy='manual', schema={'EVENT_TYPE': otp.string[40]})
event = event.where(event['EVENT_TYPE'] == 'EARNING_DATE')
event['PRICE'] = otp.nan
event['SIZE'] = 0
event['EVENT'] = 1
event = event[['PRICE', 'SIZE', 'EVENT', 'EVENT_TYPE']]
# Union the two streams.
data = otp.merge([trd, event])
# get only first 1000 rows
data = data.limit(1000)
result = otp.run(data,
start=otp.dt(2024, 2, 14),
end=otp.dt(2024, 2, 15),
timezone='America/New_York',
symbols='CSCO')
result
| Time | PRICE | SIZE | EVENT | EVENT_TYPE | |
|---|---|---|---|---|---|
| 0 | 2024-02-14 04:00:00.036667885 | 49.80 | 80 | 0 | |
| 1 | 2024-02-14 04:00:01.123032110 | 49.80 | 78 | 0 | |
| 2 | 2024-02-14 04:00:01.123032235 | 49.70 | 20 | 0 | |
| 3 | 2024-02-14 04:00:01.124715858 | 49.70 | 2 | 0 | |
| 4 | 2024-02-14 04:00:02.068007001 | 49.68 | 2 | 0 | |
| ... | ... | ... | ... | ... | ... |
| 995 | 2024-02-14 09:30:01.429521692 | 49.60 | 100 | 0 | |
| 996 | 2024-02-14 09:30:01.429530498 | 49.60 | 10 | 0 | |
| 997 | 2024-02-14 09:30:01.429579520 | 49.60 | 50 | 0 | |
| 998 | 2024-02-14 09:30:01.429707081 | 49.60 | 100 | 0 | |
| 999 | 2024-02-14 09:30:01.429708760 | 49.60 | 17 | 0 |
1000 rows × 5 columns