Options#
This section contains 16 examples for Options 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__'
Options Greeks#
Retrieves end-of-day options data for AAPL contracts from the US Options EOD sample.
Includes Greeks (delta, gamma, theta, vega), implied volatility, open interest, volume,
bid/ask close prices, and underlying price for a single trading day.
import onetick.py as otp
# Retrieve the end-of-day (DAY) records for all AAPL option contracts.
# Symbols are selected with a pattern against the US_OPTIONS_EOD_SAMPLE database.
options_day = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='DAY')
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[options_day],
symbols=otp.Symbols('US_OPTIONS_EOD_SAMPLE', pattern='AAPL%')
)
# Return first 1000 rows
merged = merged.limit(1000)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3),
end=otp.dt(2025, 1, 4),
timezone='America/New_York'
)
result
| Time | ASK_CLOSE | BID_CLOSE | DELTA | GAMMA | IMP_VOLATILITY | OMDSEQ | OPEN_INT | THETA | UNDERLYING_PRICE | VEGA | VOLUME | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-03 16:00:00 | 144.35 | 142.55 | 1.0000 | 0.0000 | 0.3000 | 3782 | 10.0 | 0.0000 | 243.36 | 0.0000 | 0 |
| 1 | 2025-01-03 16:00:00 | 0.01 | NaN | 0.0000 | 0.0000 | 0.3000 | 3783 | 80.0 | 0.0000 | 243.36 | 0.0000 | 10 |
| 2 | 2025-01-03 16:00:00 | 139.55 | 137.90 | 1.0000 | 0.0000 | 0.3000 | 3784 | 0.0 | 0.0000 | 243.36 | 0.0000 | 0 |
| 3 | 2025-01-03 16:00:00 | 0.01 | NaN | 0.0000 | 0.0000 | 0.3000 | 3785 | 0.0 | 0.0000 | 243.36 | 0.0000 | 0 |
| 4 | 2025-01-03 16:00:00 | 134.45 | 132.45 | 1.0000 | 0.0000 | 0.3000 | 3786 | 0.0 | 0.0000 | 243.36 | 0.0000 | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 995 | 2025-01-03 16:00:00 | 12.55 | 12.00 | -0.5370 | 0.0155 | 0.2301 | 4777 | 11541.0 | -0.0448 | 243.36 | 0.4420 | 424 |
| 996 | 2025-01-03 16:00:00 | 5.65 | 5.50 | 0.3719 | 0.0165 | 0.2055 | 4778 | 4593.0 | -0.0695 | 243.36 | 0.4209 | 1006 |
| 997 | 2025-01-03 16:00:00 | 15.55 | 15.00 | -0.6113 | 0.0150 | 0.2291 | 4779 | 2039.0 | -0.0390 | 243.36 | 0.4265 | 312 |
| 998 | 2025-01-03 16:00:00 | 4.05 | 3.90 | 0.2937 | 0.0153 | 0.2025 | 4780 | 23432.0 | -0.0610 | 243.36 | 0.3832 | 887 |
| 999 | 2025-01-03 16:00:00 | 19.10 | 18.50 | -0.6770 | 0.0139 | 0.2327 | 4781 | 1259.0 | -0.0330 | 243.36 | 0.3995 | 24 |
1000 rows × 12 columns
Options Trades#
Retrieves options trade data for a specific AAPL contract from the US Options sample feed.
The symbol encodes the underlying, expiry, call/put indicator and strike price.
import onetick.py as otp
# Define the trade data source for a single option contract.
data = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='TRD')
# Return first 1000 rows
data = data.limit(1000)
result = otp.run(
data,
start=otp.dt(2025, 1, 2),
end=otp.dt(2025, 1, 4, 16),
timezone='UTC',
symbols='AAPL 250103C00155000' # Symbol has Underlying, Expiry, Call/Put and Strike
)
result
Time |
PRICE |
SIZE |
EXCHANGE |
TRADE_TYPE |
TRADE_TYPE_EXT |
TRADE_ID |
OMDSEQ |
DELETED_TIME |
TICK_STATUS |
|
|---|---|---|---|---|---|---|---|---|---|---|
0 |
2025-01-03 16:09:05.053000 |
87.91 |
6 |
S |
f |
MLET |
003988253e |
147 |
1970-01-01 00:00:00 |
0 |
1 |
2025-01-03 16:09:05.153000 |
87.92 |
7 |
E |
f |
MLET |
00beb5253e |
89 |
1970-01-01 00:00:00 |
0 |
2 |
2025-01-03 16:09:05.153000 |
87.95 |
3 |
X |
f |
MLET |
00c3b5253e |
90 |
1970-01-01 00:00:00 |
0 |
3 |
2025-01-03 16:09:05.153000 |
87.92 |
7 |
W |
f |
MLET |
00c4b5253e |
164 |
1970-01-01 00:00:00 |
0 |
4 |
2025-01-03 16:09:05.286000 |
87.93 |
12 |
J |
g |
MLAT |
000bdb253e |
60 |
1970-01-01 00:00:00 |
0 |
5 |
2025-01-03 19:09:30.778000 |
87.84 |
2 |
C |
g |
MLAT |
0001936f7d |
33 |
1970-01-01 00:00:00 |
0 |
OPRA Call and Put Volume & Open Interest Summary by Strike Price#
OPRA Daily data is retrieved from the US_OPTIONS_EOD database.
Here the sample database US_OPTIONS_EOD_SAMPLE is used.
Daily Volume and Open Interest are split by Calls and Puts and grouped by Strike Price for a specified underlying.
The daily DAY records are joined by time to the static STAT records to obtain the Expiration Date,
Strike Price and Call/Put Indicator.
A lookback of up to 1 day (86400s) is used on the static data so the
prevailing static record is picked up.
Volume and Open Interest are divided into Call and Put buckets,
then summed across the day, grouped by Underlying Symbol and Strike Price.
import onetick.py as otp
# Daily options data for all AAPL contracts.
day = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='DAY')
day = day[['VOLUME', 'OPEN_INT']]
# Static (reference) data for the same contracts, looking back up to 1 day for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Join each daily tick to the prevailing static record (asof join).
joined = otp.join_by_time([day, stat])
# Split Volume and Open Interest into Call and Put buckets based on the Call/Put Indicator.
joined['CALL_VOLUME'] = joined.apply(lambda t: t['VOLUME'] if t['CALL_PUT_IND'] == 'C' else 0)
joined['PUT_VOLUME'] = joined.apply(lambda t: t['VOLUME'] if t['CALL_PUT_IND'] == 'P' else 0)
joined['CALL_OPEN_INT'] = joined.apply(lambda t: t['OPEN_INT'] if t['CALL_PUT_IND'] == 'C' else 0)
joined['PUT_OPEN_INT'] = joined.apply(lambda t: t['OPEN_INT'] if t['CALL_PUT_IND'] == 'P' else 0)
# Sum across the day, grouped by Underlying Symbol and Strike Price.
summary = joined.agg(
{
'CONTRACT_COUNT': otp.agg.count(),
'CALL_VOLUME': otp.agg.sum('CALL_VOLUME'),
'PUT_VOLUME': otp.agg.sum('PUT_VOLUME'),
'VOLUME': otp.agg.sum('VOLUME'),
'CALL_OPEN_INT': otp.agg.sum('CALL_OPEN_INT'),
'PUT_OPEN_INT': otp.agg.sum('PUT_OPEN_INT'),
'OPEN_INT': otp.agg.sum('OPEN_INT'),
},
group_by=['UNDERLYING_SYMBOL', 'STRIKE_PRICE']
)
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[summary],
symbols=otp.Symbols('US_OPTIONS_EOD_SAMPLE', pattern='AAPL %')
)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3),
end=otp.dt(2025, 1, 4),
timezone='America/New_York'
)
result
| Time | UNDERLYING_SYMBOL | STRIKE_PRICE | CONTRACT_COUNT | CALL_VOLUME | PUT_VOLUME | VOLUME | CALL_OPEN_INT | PUT_OPEN_INT | OPEN_INT | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-04 | AAPL | 100.0 | 1 | 0 | 0 | 0 | 10.0 | 0.0 | 10.0 |
| 1 | 2025-01-04 | AAPL | 105.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2 | 2025-01-04 | AAPL | 110.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 3 | 2025-01-04 | AAPL | 115.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 4 | 2025-01-04 | AAPL | 120.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2257 | 2025-01-04 | AAPL | 410.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2258 | 2025-01-04 | AAPL | 420.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2259 | 2025-01-04 | AAPL | 430.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2260 | 2025-01-04 | AAPL | 440.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2261 | 2025-01-04 | AAPL | 450.0 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
2262 rows × 10 columns
OPRA Call and Put Volume & Open Interest Summary by Expiration#
OPRA Daily data is retrieved from the US_OPTIONS_EOD database.
Here the sample database US_OPTIONS_EOD_SAMPLE is used.
Daily Volume and Open Interest are split by Calls and Puts and grouped by Expiration Date for a specified underlying.
The daily DAY records are joined by time to the static STAT records to obtain the Expiration Date,
Strike Price and Call/Put Indicator.
A lookback of up to 1 day (86400s) is used on the static data so the
prevailing static record is picked up.
Volume and Open Interest are divided into Call and Put buckets,
then summed across the day, grouped by Underlying Symbol and Expiration Date.
import onetick.py as otp
# Daily options data for all AAPL contracts.
day = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='DAY')
day = day[['VOLUME', 'OPEN_INT']]
# Static (reference) data for the same contracts, looking back up to 1 day for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Join each daily tick to the prevailing static record (asof join).
joined = otp.join_by_time([day, stat])
# Split Volume and Open Interest into Call and Put buckets based on the Call/Put Indicator.
joined['CALL_VOLUME'] = joined.apply(lambda t: t['VOLUME'] if t['CALL_PUT_IND'] == 'C' else 0)
joined['PUT_VOLUME'] = joined.apply(lambda t: t['VOLUME'] if t['CALL_PUT_IND'] == 'P' else 0)
joined['CALL_OPEN_INT'] = joined.apply(lambda t: t['OPEN_INT'] if t['CALL_PUT_IND'] == 'C' else 0)
joined['PUT_OPEN_INT'] = joined.apply(lambda t: t['OPEN_INT'] if t['CALL_PUT_IND'] == 'P' else 0)
# Sum across the day, grouped by Underlying Symbol and Expiration Date.
summary = joined.agg(
{
'CONTRACT_COUNT': otp.agg.count(),
'CALL_VOLUME': otp.agg.sum('CALL_VOLUME'),
'PUT_VOLUME': otp.agg.sum('PUT_VOLUME'),
'VOLUME': otp.agg.sum('VOLUME'),
'CALL_OPEN_INT': otp.agg.sum('CALL_OPEN_INT'),
'PUT_OPEN_INT': otp.agg.sum('PUT_OPEN_INT'),
'OPEN_INT': otp.agg.sum('OPEN_INT'),
},
group_by=['UNDERLYING_SYMBOL', 'EXPIRATION_DATE']
)
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[summary],
symbols=otp.Symbols('US_OPTIONS_EOD_SAMPLE', pattern='AAPL %')
)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3),
end=otp.dt(2025, 1, 4),
timezone='America/New_York'
)
result
| Time | UNDERLYING_SYMBOL | EXPIRATION_DATE | CONTRACT_COUNT | CALL_VOLUME | PUT_VOLUME | VOLUME | CALL_OPEN_INT | PUT_OPEN_INT | OPEN_INT | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-04 | AAPL | 20250103 | 1 | 0 | 0 | 0 | 10.0 | 0.0 | 10.0 |
| 1 | 2025-01-04 | AAPL | 20250103 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2 | 2025-01-04 | AAPL | 20250103 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 3 | 2025-01-04 | AAPL | 20250103 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 4 | 2025-01-04 | AAPL | 20250103 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2257 | 2025-01-04 | AAPL | 20270115 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2258 | 2025-01-04 | AAPL | 20270115 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2259 | 2025-01-04 | AAPL | 20270115 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2260 | 2025-01-04 | AAPL | 20270115 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
| 2261 | 2025-01-04 | AAPL | 20270115 | 1 | 0 | 0 | 0 | 0.0 | 0.0 | 0.0 |
2262 rows × 10 columns
OPRA Call and Put Volume across an intra-day time range by Expiry#
OPRA Trade data is retrieved from the US_OPTIONS database.
Here the sample database US_OPTIONS_SAMPLE is used.
Period Volume is split by Calls and Puts and grouped by Expiration Date for a specified underlying.
Trades are joined by time to the static STAT records to obtain the Expiration Date, Strike Price and
Call/Put Indicator.
A lookback of up to 1 day (86400s) is used on the static data so the prevailing
static record is picked up.
Volume is aggregated from Trade Size and divided into Call and Put buckets,
then summed across the period, grouped by Underlying Symbol and Expiration Date.
import onetick.py as otp
# Intraday options trades for all AAPL contracts.
trd = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='TRD')
trd = trd[['SIZE']]
# Static (reference) data for the same contracts, looking back up to 1 day for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Join each trade to the prevailing static record (asof join).
joined = otp.join_by_time([trd, stat])
# Trade Size is the traded volume; split it into Call and Put buckets.
joined['VOLUME'] = joined['SIZE']
joined['CALL_VOLUME'] = joined.apply(lambda t: t['SIZE'] if t['CALL_PUT_IND'] == 'C' else 0)
joined['PUT_VOLUME'] = joined.apply(lambda t: t['SIZE'] if t['CALL_PUT_IND'] == 'P' else 0)
# Sum across the period, grouped by Underlying Symbol and Expiration Date.
summary = joined.agg(
{
'CONTRACT_COUNT': otp.agg.count(),
'CALL_VOLUME': otp.agg.sum('CALL_VOLUME'),
'PUT_VOLUME': otp.agg.sum('PUT_VOLUME'),
'VOLUME': otp.agg.sum('VOLUME'),
},
group_by=['UNDERLYING_SYMBOL', 'EXPIRATION_DATE']
)
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[summary],
symbols=otp.Symbols('US_OPTIONS_SAMPLE', pattern='AAPL %')
)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3, 10),
end=otp.dt(2025, 1, 3, 12),
timezone='America/New_York'
)
result
Time |
UNDERLYING_SYMBOL |
EXPIRATION_DATE |
CONTRACT_COUNT |
CALL_VOLUME |
PUT_VOLUME |
VOLUME |
|
|---|---|---|---|---|---|---|---|
0 |
2025-01-03 12:00:00 |
AAPL |
20250103 |
1 |
2 |
0 |
2 |
1 |
2025-01-03 12:00:00 |
AAPL |
20250103 |
1 |
10 |
0 |
10 |
2 |
2025-01-03 12:00:00 |
AAPL |
20250103 |
5 |
35 |
0 |
35 |
3 |
2025-01-03 12:00:00 |
AAPL |
20250103 |
2 |
4 |
0 |
4 |
4 |
2025-01-03 12:00:00 |
AAPL |
20250103 |
1 |
1 |
0 |
1 |
… |
… |
… |
… |
… |
… |
… |
… |
811 |
2025-01-03 12:00:00 |
AAPL |
20270115 |
1 |
0 |
3 |
3 |
812 |
2025-01-03 12:00:00 |
AAPL |
20270115 |
49 |
0 |
528 |
528 |
813 |
2025-01-03 12:00:00 |
AAPL |
20270115 |
3 |
0 |
7 |
7 |
814 |
2025-01-03 12:00:00 |
AAPL |
20270115 |
2 |
0 |
2 |
2 |
815 |
2025-01-03 12:00:00 |
AAPL |
20270115 |
1 |
0 |
6 |
6 |
816 rows x 7 columns
OPRA Call and Put Volume across an intra-day time range by Strike Price#
OPRA Trade data is retrieved from the US_OPTIONS database.
Here the sample database US_OPTIONS_SAMPLE is used.
Period Volume is split by Calls and Puts and grouped by Strike Price for a specified underlying.
Trades are joined by time to the static STAT records to obtain the Expiration Date, Strike Price and
Call/Put Indicator.
A lookback of up to 1 day (86400s) is used on the static data so the prevailing
static record is picked up.
Volume is aggregated from Trade Size and divided into Call and Put buckets,
then summed across the period, grouped by Underlying Symbol and Strike Price.
import onetick.py as otp
# Intraday options trades for all AAPL contracts.
trd = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='TRD')
trd = trd[['SIZE']]
# Static (reference) data for the same contracts, looking back up to 1 day for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Join each trade to the prevailing static record (asof join).
joined = otp.join_by_time([trd, stat])
# Trade Size is the traded volume; split it into Call and Put buckets.
joined['VOLUME'] = joined['SIZE']
joined['CALL_VOLUME'] = joined.apply(lambda t: t['SIZE'] if t['CALL_PUT_IND'] == 'C' else 0)
joined['PUT_VOLUME'] = joined.apply(lambda t: t['SIZE'] if t['CALL_PUT_IND'] == 'P' else 0)
# Sum across the period, grouped by Underlying Symbol and Strike Price.
summary = joined.agg(
{
'CONTRACT_COUNT': otp.agg.count(),
'CALL_VOLUME': otp.agg.sum('CALL_VOLUME'),
'PUT_VOLUME': otp.agg.sum('PUT_VOLUME'),
'VOLUME': otp.agg.sum('VOLUME'),
},
group_by=['UNDERLYING_SYMBOL', 'STRIKE_PRICE']
)
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[summary],
symbols=otp.Symbols('US_OPTIONS_SAMPLE', pattern='AAPL %')
)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3, 10),
end=otp.dt(2025, 1, 3, 12),
timezone='America/New_York'
)
result
Time |
UNDERLYING_SYMBOL |
STRIKE_PRICE |
CONTRACT_COUNT |
CALL_VOLUME |
PUT_VOLUME |
VOLUME |
|
|---|---|---|---|---|---|---|---|
0 |
2025-01-03 12:00:00 |
AAPL |
140.0 |
1 |
2 |
0 |
2 |
1 |
2025-01-03 12:00:00 |
AAPL |
150.0 |
1 |
10 |
0 |
10 |
2 |
2025-01-03 12:00:00 |
AAPL |
155.0 |
5 |
35 |
0 |
35 |
3 |
2025-01-03 12:00:00 |
AAPL |
160.0 |
2 |
4 |
0 |
4 |
4 |
2025-01-03 12:00:00 |
AAPL |
170.0 |
1 |
1 |
0 |
1 |
… |
… |
… |
… |
… |
… |
… |
… |
811 |
2025-01-03 12:00:00 |
AAPL |
185.0 |
1 |
0 |
3 |
3 |
812 |
2025-01-03 12:00:00 |
AAPL |
200.0 |
49 |
0 |
528 |
528 |
813 |
2025-01-03 12:00:00 |
AAPL |
210.0 |
3 |
0 |
7 |
7 |
814 |
2025-01-03 12:00:00 |
AAPL |
240.0 |
2 |
0 |
2 |
2 |
815 |
2025-01-03 12:00:00 |
AAPL |
250.0 |
1 |
0 |
6 |
6 |
816 rows x 7 columns
OPRA Daily Volume, Open Interest and Greeks for Selected Underlying and Expiry#
OPRA Daily data is retrieved from the US_OPTIONS_EOD database.
Here the sample database US_OPTIONS_EOD_SAMPLE is used.
Retrieves end-of-day pricing, Volume, Open Interest and Greeks (Implied Volatility, Delta, Gamma, Theta and Vega),
together with static data including Underlying Symbol, Strike Price, Expiration Date and Call/Put Indicator.
Filtered for the AAPL underlying and expiration date 20270115.
The daily DAY records are joined by time to the static STAT records.
Because the static data may have been
published at a different time to the daily data, a lookback of up to 1 day (86400s) is used so the prevailing
static record is identified.
import onetick.py as otp
# Daily options data for all AAPL contracts.
day = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='DAY')
day = day[['VOLUME', 'OPEN_INT', 'UNDERLYING_PRICE', 'BID_CLOSE', 'ASK_CLOSE',
'IMP_VOLATILITY', 'DELTA', 'GAMMA', 'THETA', 'VEGA']]
# Static (reference) data for the same contracts, looking back up to 1 day for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Restrict the static records to the selected expiration.
stat = stat.where(stat['EXPIRATION_DATE'] == '20270115')
# Join each daily tick to the prevailing static record (asof join).
joined = otp.join_by_time([day, stat])
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[joined],
symbols=otp.Symbols('US_OPTIONS_EOD_SAMPLE', pattern='AAPL %')
)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3),
end=otp.dt(2025, 1, 4),
timezone='America/New_York'
)
result
| Time | VOLUME | OPEN_INT | UNDERLYING_PRICE | BID_CLOSE | ASK_CLOSE | IMP_VOLATILITY | DELTA | GAMMA | THETA | VEGA | UNDERLYING_SYMBOL | EXPIRATION_DATE | STRIKE_PRICE | CALL_PUT_IND | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-03 16:00:00 | 0 | 10.0 | 243.36 | 142.55 | 144.35 | 0.3000 | 1.0000 | 0.0000 | 0.0000 | 0.0000 | NaN | |||
| 1 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 137.90 | 139.55 | 0.3000 | 1.0000 | 0.0000 | 0.0000 | 0.0000 | NaN | |||
| 2 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 132.45 | 134.45 | 0.3000 | 1.0000 | 0.0000 | 0.0000 | 0.0000 | NaN | |||
| 3 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 127.65 | 128.80 | 0.3000 | 1.0000 | 0.0000 | 0.0000 | 0.0000 | NaN | |||
| 4 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 122.45 | 123.80 | 0.3000 | 1.0000 | 0.0000 | 0.0000 | 0.0000 | NaN | |||
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2257 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 164.55 | 168.50 | 0.5541 | -0.5489 | 0.0021 | -0.0057 | 1.3732 | AAPL | 20270115 | 410.0 | P |
| 2258 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 174.60 | 178.55 | 0.5541 | -0.5610 | 0.0021 | -0.0039 | 1.3674 | AAPL | 20270115 | 420.0 | P |
| 2259 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 184.60 | 188.55 | 0.5541 | -0.5727 | 0.0020 | -0.0021 | 1.3605 | AAPL | 20270115 | 430.0 | P |
| 2260 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 194.60 | 198.55 | 0.5541 | -0.5841 | 0.0020 | -0.0002 | 1.3527 | AAPL | 20270115 | 440.0 | P |
| 2261 | 2025-01-03 16:00:00 | 0 | 0.0 | 243.36 | 204.60 | 208.55 | 0.5541 | -0.5952 | 0.0020 | 0.0016 | 1.3440 | AAPL | 20270115 | 450.0 | P |
2262 rows × 15 columns
OPRA Daily Volume, Open Interest and Greeks for Selected Underlying and Expiry returned as a straddle configuration#
OPRA Daily Volume, Open Interest and Greeks for Selected Underlying and Expiry returned as a straddle configuration.
OPRA Daily data is retrieved from the US_OPTIONS_EOD database.
Here the sample database US_OPTIONS_EOD_SAMPLE is used.
Retrieves end-of-day pricing, Volume, Open Interest and Greeks (Implied Volatility, Delta, Gamma, Theta and Vega),
together with static data including Underlying Symbol, Strike Price, Expiration Date and Call/Put Indicator.
Filtered for the AAPL underlying and expiration date 20270115.
Data is displayed grouped by strike price, with Call and Put metrics associated with each strike.
The daily DAY records are joined by time to the static STAT records with a lookback of up to 1 day (86400s).
Call and Put metrics are created by testing CALL_PUT_IND (‘P’ for Put, ‘C’ for Call), using NaN for the
other side so that averaging by strike leaves a single row per strike carrying both the Call and Put values.
import onetick.py as otp
# Daily options data for all AAPL contracts.
day = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='DAY')
day = day[['VOLUME', 'OPEN_INT', 'BID_CLOSE', 'ASK_CLOSE',
'IMP_VOLATILITY', 'DELTA', 'GAMMA', 'THETA', 'VEGA']]
# Static (reference) data for the same contracts, looking back up to 1 day for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_EOD_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Restrict the static records to the selected expiration.
stat = stat.where(stat['EXPIRATION_DATE'] == '20270115')
# Join each daily tick to the prevailing static record (asof join).
joined = otp.join_by_time([day, stat])
# Build Call ('C') and Put ('P') columns per metric; the opposite side is NaN so it is ignored by the average.
# (per-tick apply takes a single-argument lambda referencing the tick's fields)
joined['C_VOLUME'] = joined.apply(lambda t: t['VOLUME'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_VOLUME'] = joined.apply(lambda t: t['VOLUME'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_OPEN_INT'] = joined.apply(lambda t: t['OPEN_INT'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_OPEN_INT'] = joined.apply(lambda t: t['OPEN_INT'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_BID'] = joined.apply(lambda t: t['BID_CLOSE'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_BID'] = joined.apply(lambda t: t['BID_CLOSE'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_ASK'] = joined.apply(lambda t: t['ASK_CLOSE'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_ASK'] = joined.apply(lambda t: t['ASK_CLOSE'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_IV'] = joined.apply(lambda t: t['IMP_VOLATILITY'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_IV'] = joined.apply(lambda t: t['IMP_VOLATILITY'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_DELTA'] = joined.apply(lambda t: t['DELTA'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_DELTA'] = joined.apply(lambda t: t['DELTA'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_GAMMA'] = joined.apply(lambda t: t['GAMMA'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_GAMMA'] = joined.apply(lambda t: t['GAMMA'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_THETA'] = joined.apply(lambda t: t['THETA'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_THETA'] = joined.apply(lambda t: t['THETA'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
joined['C_VEGA'] = joined.apply(lambda t: t['VEGA'] if t['CALL_PUT_IND'] == 'C' else otp.nan)
joined['P_VEGA'] = joined.apply(lambda t: t['VEGA'] if t['CALL_PUT_IND'] == 'P' else otp.nan)
# Average each Call and Put metric, grouped by Strike Price, to return a single straddle row per strike.
metrics = ['VOLUME', 'OPEN_INT', 'BID', 'ASK', 'IV', 'DELTA', 'GAMMA', 'THETA', 'VEGA']
agg_spec = {}
for m in metrics:
agg_spec['C_' + m] = otp.agg.average('C_' + m)
agg_spec['P_' + m] = otp.agg.average('P_' + m)
straddle = joined.agg(agg_spec, group_by=['STRIKE_PRICE'])
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[straddle],
symbols=otp.Symbols('US_OPTIONS_EOD_SAMPLE', pattern='AAPL %')
)
result = otp.run(
merged,
start=otp.dt(2025, 1, 3),
end=otp.dt(2025, 1, 4),
timezone='America/New_York'
)
result
| Time | STRIKE_PRICE | C_VOLUME | P_VOLUME | C_OPEN_INT | P_OPEN_INT | C_BID | P_BID | C_ASK | P_ASK | C_IV | P_IV | C_DELTA | P_DELTA | C_GAMMA | P_GAMMA | C_THETA | P_THETA | C_VEGA | P_VEGA | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-04 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 2025-01-04 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2 | 2025-01-04 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | 2025-01-04 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 4 | 2025-01-04 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2257 | 2025-01-04 | 410.0 | NaN | 0.0 | NaN | 0.0 | NaN | 164.55 | NaN | 168.50 | NaN | 0.5541 | NaN | -0.5489 | NaN | 0.0021 | NaN | -0.0057 | NaN | 1.3732 |
| 2258 | 2025-01-04 | 420.0 | NaN | 0.0 | NaN | 0.0 | NaN | 174.60 | NaN | 178.55 | NaN | 0.5541 | NaN | -0.5610 | NaN | 0.0021 | NaN | -0.0039 | NaN | 1.3674 |
| 2259 | 2025-01-04 | 430.0 | NaN | 0.0 | NaN | 0.0 | NaN | 184.60 | NaN | 188.55 | NaN | 0.5541 | NaN | -0.5727 | NaN | 0.0020 | NaN | -0.0021 | NaN | 1.3605 |
| 2260 | 2025-01-04 | 440.0 | NaN | 0.0 | NaN | 0.0 | NaN | 194.60 | NaN | 198.55 | NaN | 0.5541 | NaN | -0.5841 | NaN | 0.0020 | NaN | -0.0002 | NaN | 1.3527 |
| 2261 | 2025-01-04 | 450.0 | NaN | 0.0 | NaN | 0.0 | NaN | 204.60 | NaN | 208.55 | NaN | 0.5541 | NaN | -0.5952 | NaN | 0.0020 | NaN | 0.0016 | NaN | 1.3440 |
2262 rows × 20 columns
OPRA Prevailing Pricing or Snapshot for the Selected Time, Underlying and Expiry#
OPRA Trade data is retrieved from the US_OPTIONS database (sample database US_OPTIONS_SAMPLE), together with
static data including Underlying Symbol, Strike Price, Expiration Date and Call/Put Indicator.
Underlying equity pricing is retrieved from the US_COMP database (sample database US_COMP_SAMPLE).
Data is Filtered for the AAPL underlying (options via the AAPL % pattern, equity via SYMBOL_NAME AAPL)
and for the expiration date 20270115.
The option trades are joined by time to the static records and to the prevailing underlying equity trade.
Because the data may have been published at different times before the target time, lookbacks are defined so
the prevailing values are returned.
MONEYNESS is computed as Strike Price minus the underlying price.
import onetick.py as otp
# The snapshot time of interest.
snapshot_time = otp.dt(2025, 1, 3, 10)
# Prevailing options trades for all AAPL contracts, looking back up to 10 hours (36000s).
trd = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='TRD', back_to_first_tick=36000)
trd = trd[['PRICE', 'SIZE']]
# Static (reference) data for the same contracts, looking back up to 1 day (86400s) for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Restrict the static records to the selected expiration.
stat = stat.where(stat['EXPIRATION_DATE'] == '20270115')
# Join each prevailing option trade to the prevailing static record (asof join).
joined = otp.join_by_time([trd, stat])
# Keep only the last (prevailing) tick up to the snapshot time, per option contract.
joined = joined.last()
# Merge every matching AAPL option contract into a single stream.
options = otp.merge(
[joined],
symbols=otp.Symbols('US_OPTIONS_SAMPLE', pattern='AAPL %')
)
# Prevailing underlying equity trade for AAPL, looking back up to 10 hours (36000s).
underlying = otp.DataSource(db='US_COMP_SAMPLE', tick_type='TRD', back_to_first_tick=36000, symbols='AAPL')
underlying = underlying[['PRICE']]
underlying = underlying.rename({'PRICE': 'UNDERLYING_PRICE'})
underlying = underlying.last()
# Join the option snapshot to the prevailing underlying price (asof join).
result_src = otp.join_by_time([options, underlying])
# Moneyness is the strike price relative to the underlying price.
result_src['MONEYNESS'] = result_src['STRIKE_PRICE'] - result_src['UNDERLYING_PRICE']
# A zero-length window ending at the snapshot time returns the prevailing values as of that time.
result = otp.run(
result_src,
start=snapshot_time,
end=snapshot_time,
timezone='America/New_York'
)
result
OPRA Prevailing or Snapshot Options Prices at a specified time, for a specified underlying#
OPRA Trade data is retrieved from the US_OPTIONS database.
Here the sample database US_OPTIONS_SAMPLE is used.
Trades are joined by time to the static STAT records to obtain the Expiration Date, Strike Price and
Call/Put Indicator.
The query returns the prevailing trade at the specified time; lookbacks are defined for
both the Trades (up to 10 hours) and the Static Data (up to 1 day) so the prevailing values up to the
specified time are returned.
import onetick.py as otp
# The snapshot time of interest.
snapshot_time = otp.dt(2025, 1, 3, 10)
# Prevailing options trades for all AAPL contracts, looking back up to 10 hours (36000s).
trd = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='TRD', back_to_first_tick=36000)
trd = trd[['PRICE', 'SIZE']]
# Static (reference) data for the same contracts, looking back up to 1 day (86400s) for the prevailing record.
stat = otp.DataSource(db='US_OPTIONS_SAMPLE', tick_type='STAT', back_to_first_tick=86400)
stat = stat[['UNDERLYING_SYMBOL', 'EXPIRATION_DATE', 'STRIKE_PRICE', 'CALL_PUT_IND']]
# Join each prevailing trade to the prevailing static record (asof join).
joined = otp.join_by_time([trd, stat])
# Keep only the last (prevailing) tick up to the snapshot time.
joined = joined.last()
# Merge every matching AAPL contract into a single stream.
merged = otp.merge(
[joined],
symbols=otp.Symbols('US_OPTIONS_SAMPLE', pattern='AAPL %')
)
# A zero-length window ending at the snapshot time returns the prevailing values as of that time.
result = otp.run(
merged,
start=snapshot_time,
end=snapshot_time,
timezone='America/New_York'
)
result
Time |
PRICE |
SIZE |
UNDERLYING_SYMBOL |
EXPIRATION_DATE |
STRIKE_PRICE |
CALL_PUT_IND |
|
|---|---|---|---|---|---|---|---|
0 |
2025-01-03 10:00:00 |
68.35 |
10 |
AAPL |
20250103 |
175.0 |
C |
1 |
2025-01-03 10:00:00 |
63.71 |
20 |
AAPL |
20250103 |
180.0 |
C |
2 |
2025-01-03 10:00:00 |
38.76 |
1 |
AAPL |
20250103 |
205.0 |
C |
3 |
2025-01-03 10:00:00 |
32.40 |
1 |
AAPL |
20250103 |
210.0 |
C |
4 |
2025-01-03 10:00:00 |
30.65 |
1 |
AAPL |
20250103 |
212.5 |
C |
… |
… |
… |
… |
… |
… |
… |
… |
633 |
2025-01-03 10:00:00 |
9.60 |
15 |
AAPL |
20270115 |
190.0 |
P |
634 |
2025-01-03 10:00:00 |
11.73 |
2 |
AAPL |
20270115 |
200.0 |
P |
635 |
2025-01-03 10:00:00 |
24.45 |
1 |
AAPL |
20270115 |
240.0 |
P |
636 |
2025-01-03 10:00:00 |
28.65 |
50 |
AAPL |
20270115 |
250.0 |
P |
637 |
2025-01-03 10:00:00 |
34.00 |
1 |
AAPL |
20270115 |
260.0 |
P |
638 rows x 7 columns
OPRA Options Chain Symbol Universe Retrieval#
Return the Options Chain of contracts for an OPRA underlying from the Symbol Universe.
Filtering with US_OPTIONS Option selects the symbols that correspond to OPRA Options.
Additionally filtering on UNDERLYING_SYMBOL equal to AAPL returns the option contracts for AAPL.
import onetick.py as otp
# The Symbol Universe static records are stored in the SYMBOL_UNIVERSE database, STAT tick type.
# The SYMBOL_NAME 'US_OPTIONS Option' groups the OPRA option contracts.
data = otp.DataSource(db='SYMBOL_UNIVERSE', tick_type='STAT')
# Filter to the OPRA options universe for the AAPL underlying.
data = data.where(data['UNDERLYING_SYMBOL'] == 'AAPL')
# Select the descriptive fields of interest.
data = data[['DB_NAME', 'DB_SYMBOL', 'NAME', 'SEC_TYPE',
'UNDERLYING_SYMBOL', 'CALL_PUT_IND', 'STRIKE_PRICE', 'EXPIRATION_DATE']]
# Return first 1000 rows
data = data.limit(1000)
result = otp.run(
data,
start=otp.dt(2026, 6, 11),
end=otp.dt(2026, 6, 12),
timezone='UTC',
symbols='US_OPTIONS Option'
)
result
| Time | DB_NAME | DB_SYMBOL | NAME | SEC_TYPE | UNDERLYING_SYMBOL | CALL_PUT_IND | STRIKE_PRICE | EXPIRATION_DATE | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610C00250000 | Option | AAPL | C | 250.0 | 20260610 | |
| 1 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610P00250000 | Option | AAPL | P | 250.0 | 20260610 | |
| 2 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610C00255000 | Option | AAPL | C | 255.0 | 20260610 | |
| 3 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610P00255000 | Option | AAPL | P | 255.0 | 20260610 | |
| 4 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610C00260000 | Option | AAPL | C | 260.0 | 20260610 | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 995 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702P00170000 | Option | AAPL | P | 170.0 | 20260702 | |
| 996 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702C00175000 | Option | AAPL | C | 175.0 | 20260702 | |
| 997 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702P00175000 | Option | AAPL | P | 175.0 | 20260702 | |
| 998 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702C00180000 | Option | AAPL | C | 180.0 | 20260702 | |
| 999 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702P00180000 | Option | AAPL | P | 180.0 | 20260702 |
1000 rows × 9 columns
OPRA Options Chain Symbol Universe Summary Retrieval#
Return the Options Chain of contracts for an OPRA underlying from the Symbol Universe.
Filtering with US_OPTIONS Option selects the symbols that correspond to OPRA Options.
Additionally filtering on UNDERLYING_SYMBOL equal to AAPL returns the option contracts for AAPL.
import onetick.py as otp
# The Symbol Universe static records are stored in the SYMBOL_UNIVERSE database, STAT tick type.
# The SYMBOL_NAME 'US_OPTIONS Option' groups the OPRA option contracts.
data = otp.DataSource(db='SYMBOL_UNIVERSE', tick_type='STAT')
# Filter to the OPRA options universe for the AAPL underlying.
data = data.where(data['UNDERLYING_SYMBOL'] == 'AAPL')
# Select the descriptive fields of interest.
data = data[['DB_NAME', 'DB_SYMBOL', 'NAME', 'SEC_TYPE',
'UNDERLYING_SYMBOL', 'CALL_PUT_IND', 'STRIKE_PRICE', 'EXPIRATION_DATE']]
# Return first 1000 rows
data = data.limit(1000)
result = otp.run(
data,
start=otp.dt(2026, 6, 11),
end=otp.dt(2026, 6, 12),
timezone='UTC',
symbols='US_OPTIONS Option'
)
result
| Time | DB_NAME | DB_SYMBOL | NAME | SEC_TYPE | UNDERLYING_SYMBOL | CALL_PUT_IND | STRIKE_PRICE | EXPIRATION_DATE | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610C00250000 | Option | AAPL | C | 250.0 | 20260610 | |
| 1 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610P00250000 | Option | AAPL | P | 250.0 | 20260610 | |
| 2 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610C00255000 | Option | AAPL | C | 255.0 | 20260610 | |
| 3 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610P00255000 | Option | AAPL | P | 255.0 | 20260610 | |
| 4 | 2026-06-11 00:00:00 | US_OPTIONS | AAPL 260610C00260000 | Option | AAPL | C | 260.0 | 20260610 | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 995 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702P00170000 | Option | AAPL | P | 170.0 | 20260702 | |
| 996 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702C00175000 | Option | AAPL | C | 175.0 | 20260702 | |
| 997 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702P00175000 | Option | AAPL | P | 175.0 | 20260702 | |
| 998 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702C00180000 | Option | AAPL | C | 180.0 | 20260702 | |
| 999 | 2026-06-11 20:00:00 | US_OPTIONS | AAPL 260702P00180000 | Option | AAPL | P | 180.0 | 20260702 |
1000 rows × 9 columns
CME Options Symbol Universe Retrieval#
Return the number of Options contracts for CME from the Symbol Universe.
Filtering with CME Option selects the symbols that correspond to CME Options.
CME populates UNDERLYING_SEC_TYPE, allowing Products to be grouped.
import onetick.py as otp
# The Symbol Universe static records are stored in the SYMBOL_UNIVERSE database, STAT tick type.
# The SYMBOL_NAME 'CME Option' groups the CME option contracts.
data = otp.DataSource(db='SYMBOL_UNIVERSE', tick_type='STAT')
# Count the contracts, grouped by database, security type, underlying security type and product code.
summary = data.agg(
{'CONTRACT_COUNT': otp.agg.count()},
group_by=['DB_NAME', 'SEC_TYPE', 'UNDERLYING_SEC_TYPE', 'PRODUCT_CODE']
)
# Return first 1000 rows
summary = summary.limit(1000)
result = otp.run(
summary,
start=otp.dt(2026, 6, 11),
end=otp.dt(2026, 6, 12),
timezone='UTC',
symbols='CME Option'
)
result
| Time | DB_NAME | SEC_TYPE | UNDERLYING_SEC_TYPE | PRODUCT_CODE | CONTRACT_COUNT | |
|---|---|---|---|---|---|---|
| 0 | 2026-06-12 | CME | Option | Agriculture | 0HO | 64 |
| 1 | 2026-06-12 | CME | Option | Agriculture | 0OC | 710 |
| 2 | 2026-06-12 | CME | Option | Agriculture | 12C | 56 |
| 3 | 2026-06-12 | CME | Option | Agriculture | 12K | 60 |
| 4 | 2026-06-12 | CME | Option | Agriculture | 12S | 66 |
| ... | ... | ... | ... | ... | ... | ... |
| 883 | 2026-06-12 | CME | Option | Metal | W2S | 672 |
| 884 | 2026-06-12 | CME | Option | Metal | W3S | 370 |
| 885 | 2026-06-12 | CME | Option | Metal | W4S | 148 |
| 886 | 2026-06-12 | CME | Option | Other | 0CA | 492 |
| 887 | 2026-06-12 | CME | Option | Other | ECO | 404 |
888 rows × 6 columns
CME Treasury Options Symbol Universe Retrieval#
Return Interest Rate Options contracts for CME from the Symbol Universe.
Filtering with CME Option selects the symbols that correspond to CME Options.
Filtering with UNDERLYING_SEC_TYPE set to Interest Rate restricts the results to Treasury Options.
import onetick.py as otp
# The Symbol Universe static records are stored in the SYMBOL_UNIVERSE database, STAT tick type.
# The SYMBOL_NAME 'CME Option' groups the CME option contracts.
data = otp.DataSource(db='SYMBOL_UNIVERSE', tick_type='STAT')
# Filter to Interest Rate (Treasury) options.
data = data.where(data['UNDERLYING_SEC_TYPE'] == 'Interest Rate')
# Select the descriptive fields of interest.
data = data[['DB_NAME', 'DB_SYMBOL', 'NAME', 'SEC_TYPE', 'UNDERLYING_SEC_TYPE',
'PRODUCT_CODE', 'CALL_PUT_IND', 'STRIKE_PRICE', 'EXPIRATION_DATE']]
# Return first 1000 rows
data = data.limit(1000)
result = otp.run(
data,
start=otp.dt(2026, 6, 11),
end=otp.dt(2026, 6, 12),
timezone='UTC',
symbols='CME Option'
)
result
| Time | DB_NAME | DB_SYMBOL | NAME | SEC_TYPE | UNDERLYING_SEC_TYPE | PRODUCT_CODE | CALL_PUT_IND | STRIKE_PRICE | EXPIRATION_DATE | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2026-06-11 00:00:00.000 | CME | GB2\F26\108 | US Treasury Bond Tuesday Week 2 Jun26 108 Call | Option | Interest Rate | GB2 | C | 108.000 | 20260609 |
| 1 | 2026-06-11 00:00:00.000 | CME | GB2\F26\118 | US Treasury Bond Tuesday Week 2 Jun26 118 Call | Option | Interest Rate | GB2 | C | 118.000 | 20260609 |
| 2 | 2026-06-11 00:00:00.000 | CME | GB2\F26\127 | US Treasury Bond Tuesday Week 2 Jun26 127 Call | Option | Interest Rate | GB2 | C | 127.000 | 20260609 |
| 3 | 2026-06-11 00:00:00.000 | CME | GB2\F26\128.5 | US Treasury Bond Tuesday Week 2 Jun26 128.5 Call | Option | Interest Rate | GB2 | C | 128.500 | 20260609 |
| 4 | 2026-06-11 00:00:00.000 | CME | GB2\F26\97.5 | US Treasury Bond Tuesday Week 2 Jun26 97.5 Call | Option | Interest Rate | GB2 | C | 97.500 | 20260609 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 995 | 2026-06-11 21:00:00.934 | CME | VT3\F26\102.125 | 2-Year T-Note Monday Week 3 Jun26 102.125 Call | Option | Interest Rate | VT3 | C | 102.125 | 20260615 |
| 996 | 2026-06-11 21:00:00.934 | CME | VF4\F26\108.75 | 5-Year T-Note Monday Week 4 Jun26 108.75 Call | Option | Interest Rate | VF4 | C | 108.750 | 20260622 |
| 997 | 2026-06-11 21:00:00.934 | CME | VF4\R26\104.75 | 5-Year T-Note Monday Week 4 Jun26 104.75 Put | Option | Interest Rate | VF4 | P | 104.750 | 20260622 |
| 998 | 2026-06-11 21:00:00.934 | CME | VF4\F26\109.25 | 5-Year T-Note Monday Week 4 Jun26 109.25 Call | Option | Interest Rate | VF4 | C | 109.250 | 20260622 |
| 999 | 2026-06-11 21:00:00.934 | CME | VF4\F26\109.75 | 5-Year T-Note Monday Week 4 Jun26 109.75 Call | Option | Interest Rate | VF4 | C | 109.750 | 20260622 |
1000 rows × 10 columns
CME Options Chain Symbol Universe Retrieval#
Return the Options Chain of contracts for a CME Product from the Symbol Universe.
Filtering with CME Option selects the symbols that correspond to CME Options.
Additionally filtering on PRODUCT_CODE equal to LO, the CME Product Code for Crude Oil.
import onetick.py as otp
# The Symbol Universe static records are stored in the SYMBOL_UNIVERSE database, STAT tick type.
# The SYMBOL_NAME 'CME Option' groups the CME option contracts.
data = otp.DataSource(db='SYMBOL_UNIVERSE', tick_type='STAT')
# Filter to the CME Crude Oil product (PRODUCT_CODE 'LO').
data = data.where(data['PRODUCT_CODE'] == 'LO')
# Select the descriptive fields of interest.
data = data[['DB_NAME', 'DB_SYMBOL', 'NAME', 'SEC_TYPE', 'UNDERLYING_SEC_TYPE',
'PRODUCT_CODE', 'CALL_PUT_IND', 'STRIKE_PRICE', 'EXPIRATION_DATE']]
# Return first 1000 rows
data = data.limit(1000)
result = otp.run(
data,
start=otp.dt(2026, 6, 11),
end=otp.dt(2026, 6, 12),
timezone='UTC',
symbols='CME Option'
)
result
| Time | DB_NAME | DB_SYMBOL | NAME | SEC_TYPE | UNDERLYING_SEC_TYPE | PRODUCT_CODE | CALL_PUT_IND | STRIKE_PRICE | EXPIRATION_DATE | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2026-06-11 21:00:00.809 | CME | LO\X29\113.5 | Crude Oil Dec29 113.5 Put | Option | Energy | LO | P | 113.5 | 20291114 |
| 1 | 2026-06-11 21:00:00.809 | CME | LO\R29\75 | Crude Oil Jun29 75 Put | Option | Energy | LO | P | 75.0 | 20290517 |
| 2 | 2026-06-11 21:00:00.809 | CME | LO\L31\4 | Crude Oil Dec31 4 Call | Option | Energy | LO | C | 4.0 | 20311117 |
| 3 | 2026-06-11 21:00:00.809 | CME | LO\X27\19.5 | Crude Oil Dec27 19.5 Put | Option | Energy | LO | P | 19.5 | 20271116 |
| 4 | 2026-06-11 21:00:00.809 | CME | LO\L29\90.5 | Crude Oil Dec29 90.5 Call | Option | Energy | LO | C | 90.5 | 20291114 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 995 | 2026-06-11 21:00:01.109 | CME | LO\R28\152.5 | Crude Oil Jun28 152.5 Put | Option | Energy | LO | P | 152.5 | 20280517 |
| 996 | 2026-06-11 21:00:01.109 | CME | LO\F27\66.5 | Crude Oil Jun27 66.5 Call | Option | Energy | LO | C | 66.5 | 20270517 |
| 997 | 2026-06-11 21:00:01.109 | CME | LO\L29\105.5 | Crude Oil Dec29 105.5 Call | Option | Energy | LO | C | 105.5 | 20291114 |
| 998 | 2026-06-11 21:00:01.109 | CME | LO\R30\24 | Crude Oil Jun30 24 Put | Option | Energy | LO | P | 24.0 | 20300516 |
| 999 | 2026-06-11 21:00:01.109 | CME | LO\X32\127.5 | Crude Oil Dec32 127.5 Put | Option | Energy | LO | P | 127.5 | 20321116 |
1000 rows × 10 columns
Query Options Volume Open Interest And Greeks Analysis#
Options Volume, Open Interest, and Greeks Analysis by Expiration and Call/Put.
import onetick.py as otp
# Define the time range
start_time = otp.dt(2025, 1, 20)
end_time = otp.dt(2025, 1, 28)
# Create a DataSource for all AAPL option contracts
options_day = otp.DataSource(
db='US_OPTIONS_EOD_SAMPLE',
tick_type='DAY'
)
# Merge all AAPL option contracts into a single stream
merged_options = otp.merge(
[options_day],
symbols=otp.Symbols('US_OPTIONS_EOD_SAMPLE', pattern='AAPL%')
)
# Aggregate metrics across all contracts
agg_result = merged_options.agg(
{
'TOTAL_OPEN_INTEREST': otp.agg.sum('OPEN_INT'),
'TOTAL_VOLUME': otp.agg.sum('VOLUME'),
'AVG_UNDERLYING_PRICE': otp.agg.average('UNDERLYING_PRICE'),
'AVG_IMPLIED_VOL': otp.agg.average('IMP_VOLATILITY'),
'AVG_DELTA': otp.agg.average('DELTA'),
'AVG_GAMMA': otp.agg.average('GAMMA'),
'AVG_THETA': otp.agg.average('THETA'),
'AVG_VEGA': otp.agg.average('VEGA'),
'CONTRACT_COUNT': otp.agg.count()
}
)
# Run the query
df = otp.run(
agg_result,
start=start_time,
end=end_time,
timezone='UTC'
)
# The result is a single DataFrame with one row
df
| Time | TOTAL_OPEN_INTEREST | TOTAL_VOLUME | AVG_UNDERLYING_PRICE | AVG_IMPLIED_VOL | AVG_DELTA | AVG_GAMMA | AVG_THETA | AVG_VEGA | CONTRACT_COUNT | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2025-01-28 | 21880286.0 | 5846439 | 224.641871 | 0.400747 | 0.087597 | 0.00411 | -0.028074 | 0.260932 | 11460 |