# Earnings Events Analysis

This section contains 6 examples for Events using the `onetick-py`.<br />
\\\\
Each example is a self-contained script that can be run against the OneTick Cloud sample databases.

```default
# 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 dates
* `COMPANY_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.<br />
\\\\
This shows all historical earnings announcements for a company.

```ipython3
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
```

```myst-ansi
                 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`](https://docs.pip.distribution.sol.onetick.com/api/sources/symbols.html.md#onetick.py.Symbols), the equivalent of SQL's `SYMBOL_NAME LIKE '%'`.<br />
\\\\
This provides a comprehensive view of earnings announcements during a particular period.<br />
\\\\
`identify_input_ts` adds the `SYMBOL_NAME` of each tick to the output.

```ipython3
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
```

```myst-ansi
                  Time EVENT_CONDITION               EVENT_TYPE  OMDSEQ  \
0  2024-01-03 08:00:00                             EARNING_DATE       0   
1  2024-01-03 09:00:00                  COMPANY_CONFERENCE_CALL       0   
2  2024-01-03 16:05:00                             EARNING_DATE       0   
3  2024-01-03 16:05:00                             EARNING_DATE       1   
4  2024-01-03 16:06:00                             EARNING_DATE       0   
..                 ...             ...                      ...     ...   
17 2024-01-04 16:03:00                             EARNING_DATE       0   
18 2024-01-04 16:05:00                             EARNING_DATE       0   
19 2024-01-04 17:00:00                  COMPANY_CONFERENCE_CALL       0   
20 2024-01-04 17:00:00                  COMPANY_CONFERENCE_CALL       1   
21 2024-01-04 19:00:00                             EARNING_DATE       0   

   SYMBOL_NAME TICK_TYPE  
0          UNF     EVENT  
1          UNF     EVENT  
2          RGP     EVENT  
3         CALM     EVENT  
4          SLP     EVENT  
..         ...       ...  
17          FC     EVENT  
18        KRUS     EVENT  
19        KRUS     EVENT  
20          FC     EVENT  
21         STZ     EVENT  

[22 rows x 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.<br />
\\\\
Earnings events (excluding conference calls) are joined to the daily price/volume record
for the same symbol with [`otp.join`](https://docs.pip.distribution.sol.onetick.com/api/functions/join.html.md#onetick.py.join), keyed on the date.<br />
\\\\
As closing prices and events occur at different times of day,
both sides are truncated to the day with the
[`.dt.date_trunc`](https://docs.pip.distribution.sol.onetick.com/api/operation/dt/date_trunc.html.md#onetick.py.core.column_operations.accessors.dt_accessor._DtAccessor.date_trunc)
accessor before joining.<br />
\\\\
A left outer join keeps every daily record, with `EVENT_TYPE` populated only on event days.

```ipython3
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
```

```myst-ansi
                  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 x 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`](https://docs.pip.distribution.sol.onetick.com/api/functions/merge.html.md#onetick.py.merge).<br />
\\\\
This is useful for time series visualization and analysis spanning both continuous pricing and discrete events.<br />
\\\\
The output schema is standardized across both branches:
setting `CLOSE` as [`otp.nan`](https://docs.pip.distribution.sol.onetick.com/api/types/nan.html.md#onetick.py.nan) and `VOLUME` as 0 for the event rows,
and `EVENT_TYPE` as an empty [`otp.string[40]`](https://docs.pip.distribution.sol.onetick.com/api/types/string.html.md#onetick.py.string) for the daily pricing rows.

```ipython3
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
```

```myst-ansi
                  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 x 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`](https://docs.pip.distribution.sol.onetick.com/api/functions/merge.html.md#onetick.py.merge).<br />
\\\\
The output schema is standardized across both branches:
setting `LAST` as [`otp.nan`](https://docs.pip.distribution.sol.onetick.com/api/types/nan.html.md#onetick.py.nan) and `VOLUME` as 0 for the event rows,
and `EVENT_TYPE` as an empty [`otp.string[40]`](https://docs.pip.distribution.sol.onetick.com/api/types/string.html.md#onetick.py.string) for the bar rows.

```ipython3
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
```

```myst-ansi
                   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 x 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`](https://docs.pip.distribution.sol.onetick.com/api/functions/merge.html.md#onetick.py.merge).<br />
\\\\
The output schema is standardized across both branches:
setting `PRICE` as [`otp.nan`](https://docs.pip.distribution.sol.onetick.com/api/types/nan.html.md#onetick.py.nan) and `SIZE` as 0 for the event rows,
and `EVENT_TYPE` as an empty [`otp.string[40]`](https://docs.pip.distribution.sol.onetick.com/api/types/string.html.md#onetick.py.string) for the trade rows.

```ipython3
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
```

```myst-ansi
                             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 x 5 columns]
```
