# Options

This section contains 16 examples for Options 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__'
```

## Options Greeks

Retrieves end-of-day options data for `AAPL` contracts from the US Options EOD sample.<br />
\\\\
Includes Greeks (delta, gamma, theta, vega), implied volatility, open interest, volume,
bid/ask close prices, and underlying price for a single trading day.

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

```myst-ansi
                   Time  ASK_CLOSE  BID_CLOSE   DELTA   GAMMA  IMP_VOLATILITY  \
0   2025-01-03 16:00:00     144.35     142.55  1.0000  0.0000          0.3000   
1   2025-01-03 16:00:00       0.01        NaN  0.0000  0.0000          0.3000   
2   2025-01-03 16:00:00     139.55     137.90  1.0000  0.0000          0.3000   
3   2025-01-03 16:00:00       0.01        NaN  0.0000  0.0000          0.3000   
4   2025-01-03 16:00:00     134.45     132.45  1.0000  0.0000          0.3000   
..                  ...        ...        ...     ...     ...             ...   
995 2025-01-03 16:00:00      12.55      12.00 -0.5370  0.0155          0.2301   
996 2025-01-03 16:00:00       5.65       5.50  0.3719  0.0165          0.2055   
997 2025-01-03 16:00:00      15.55      15.00 -0.6113  0.0150          0.2291   
998 2025-01-03 16:00:00       4.05       3.90  0.2937  0.0153          0.2025   
999 2025-01-03 16:00:00      19.10      18.50 -0.6770  0.0139          0.2327   

     OMDSEQ  OPEN_INT   THETA  UNDERLYING_PRICE    VEGA  VOLUME  
0      3782      10.0  0.0000            243.36  0.0000       0  
1      3783      80.0  0.0000            243.36  0.0000      10  
2      3784       0.0  0.0000            243.36  0.0000       0  
3      3785       0.0  0.0000            243.36  0.0000       0  
4      3786       0.0  0.0000            243.36  0.0000       0  
..      ...       ...     ...               ...     ...     ...  
995    4777   11541.0 -0.0448            243.36  0.4420     424  
996    4778    4593.0 -0.0695            243.36  0.4209    1006  
997    4779    2039.0 -0.0390            243.36  0.4265     312  
998    4780   23432.0 -0.0610            243.36  0.3832     887  
999    4781    1259.0 -0.0330            243.36  0.3995      24  

[1000 rows x 12 columns]
```

## Options Trades

Retrieves options trade data for a specific `AAPL` contract from the US Options sample feed.<br />
\\\\
The symbol encodes the underlying, expiry, call/put indicator and strike price.

```python
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.<br />
\\\\
Here the sample database `US_OPTIONS_EOD_SAMPLE` is used.<br />
\\\\
Daily Volume and Open Interest are split by Calls and Puts and grouped by Strike Price for a specified underlying.<br />
\\\\
The daily `DAY` records are joined by time to the static `STAT` records to obtain the Expiration Date,
Strike Price and Call/Put Indicator.<br />
\\\\
A lookback of up to 1 day (86400s) is used on the static data so the
prevailing static record is picked up.<br />
\\\\
Volume and Open Interest are divided into Call and Put buckets,
then summed across the day, grouped by Underlying Symbol and Strike Price.

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

```myst-ansi
           Time UNDERLYING_SYMBOL  STRIKE_PRICE  CONTRACT_COUNT  CALL_VOLUME  \
0    2025-01-04              AAPL         100.0               1            0   
1    2025-01-04              AAPL         105.0               1            0   
2    2025-01-04              AAPL         110.0               1            0   
3    2025-01-04              AAPL         115.0               1            0   
4    2025-01-04              AAPL         120.0               1            0   
...         ...               ...           ...             ...          ...   
2257 2025-01-04              AAPL         410.0               1            0   
2258 2025-01-04              AAPL         420.0               1            0   
2259 2025-01-04              AAPL         430.0               1            0   
2260 2025-01-04              AAPL         440.0               1            0   
2261 2025-01-04              AAPL         450.0               1            0   

      PUT_VOLUME  VOLUME  CALL_OPEN_INT  PUT_OPEN_INT  OPEN_INT  
0              0       0           10.0           0.0      10.0  
1              0       0            0.0           0.0       0.0  
2              0       0            0.0           0.0       0.0  
3              0       0            0.0           0.0       0.0  
4              0       0            0.0           0.0       0.0  
...          ...     ...            ...           ...       ...  
2257           0       0            0.0           0.0       0.0  
2258           0       0            0.0           0.0       0.0  
2259           0       0            0.0           0.0       0.0  
2260           0       0            0.0           0.0       0.0  
2261           0       0            0.0           0.0       0.0  

[2262 rows x 10 columns]
```

## OPRA Call and Put Volume & Open Interest Summary by Expiration

OPRA Daily data is retrieved from the `US_OPTIONS_EOD` database.<br />
\\\\
Here the sample database `US_OPTIONS_EOD_SAMPLE` is used.<br />
\\\\
Daily Volume and Open Interest are split by Calls and Puts and grouped by Expiration Date for a specified underlying.<br />
\\\\
The daily `DAY` records are joined by time to the static `STAT` records to obtain the Expiration Date,
Strike Price and Call/Put Indicator.<br />
\\\\
A lookback of up to 1 day (86400s) is used on the static data so the
prevailing static record is picked up.<br />
\\\\
Volume and Open Interest are divided into Call and Put buckets,
then summed across the day, grouped by Underlying Symbol and Expiration Date.

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

```myst-ansi
           Time UNDERLYING_SYMBOL EXPIRATION_DATE  CONTRACT_COUNT  \
0    2025-01-04              AAPL        20250103               1   
1    2025-01-04              AAPL        20250103               1   
2    2025-01-04              AAPL        20250103               1   
3    2025-01-04              AAPL        20250103               1   
4    2025-01-04              AAPL        20250103               1   
...         ...               ...             ...             ...   
2257 2025-01-04              AAPL        20270115               1   
2258 2025-01-04              AAPL        20270115               1   
2259 2025-01-04              AAPL        20270115               1   
2260 2025-01-04              AAPL        20270115               1   
2261 2025-01-04              AAPL        20270115               1   

      CALL_VOLUME  PUT_VOLUME  VOLUME  CALL_OPEN_INT  PUT_OPEN_INT  OPEN_INT  
0               0           0       0           10.0           0.0      10.0  
1               0           0       0            0.0           0.0       0.0  
2               0           0       0            0.0           0.0       0.0  
3               0           0       0            0.0           0.0       0.0  
4               0           0       0            0.0           0.0       0.0  
...           ...         ...     ...            ...           ...       ...  
2257            0           0       0            0.0           0.0       0.0  
2258            0           0       0            0.0           0.0       0.0  
2259            0           0       0            0.0           0.0       0.0  
2260            0           0       0            0.0           0.0       0.0  
2261            0           0       0            0.0           0.0       0.0  

[2262 rows x 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.<br />
\\\\
Here the sample database `US_OPTIONS_SAMPLE` is used.<br />
\\\\
Period Volume is split by Calls and Puts and grouped by Expiration Date for a specified underlying.<br />
\\\\
Trades are joined by time to the static `STAT` records to obtain the Expiration Date, Strike Price and
Call/Put Indicator.<br />
\\\\
A lookback of up to 1 day (86400s) is used on the static data so the prevailing
static record is picked up.<br />
\\\\
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.

```python
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.<br />
\\\\
Here the sample database `US_OPTIONS_SAMPLE` is used.<br />
\\\\
Period Volume is split by Calls and Puts and grouped by Strike Price for a specified underlying.<br />
\\\\
Trades are joined by time to the static `STAT` records to obtain the Expiration Date, Strike Price and
Call/Put Indicator.<br />
\\\\
A lookback of up to 1 day (86400s) is used on the static data so the prevailing
static record is picked up.<br />
\\\\
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.

```python
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.<br />
\\\\
Here the sample database `US_OPTIONS_EOD_SAMPLE` is used.<br />
\\\\
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.<br />
\\\\
Filtered for the `AAPL` underlying and expiration date 20270115.<br />
\\\\
The daily `DAY` records are joined by time to the static `STAT` records.<br />
\\\\
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.

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

```myst-ansi
                    Time  VOLUME  OPEN_INT  UNDERLYING_PRICE  BID_CLOSE  \
0    2025-01-03 16:00:00       0      10.0            243.36     142.55   
1    2025-01-03 16:00:00       0       0.0            243.36     137.90   
2    2025-01-03 16:00:00       0       0.0            243.36     132.45   
3    2025-01-03 16:00:00       0       0.0            243.36     127.65   
4    2025-01-03 16:00:00       0       0.0            243.36     122.45   
...                  ...     ...       ...               ...        ...   
2257 2025-01-03 16:00:00       0       0.0            243.36     164.55   
2258 2025-01-03 16:00:00       0       0.0            243.36     174.60   
2259 2025-01-03 16:00:00       0       0.0            243.36     184.60   
2260 2025-01-03 16:00:00       0       0.0            243.36     194.60   
2261 2025-01-03 16:00:00       0       0.0            243.36     204.60   

      ASK_CLOSE  IMP_VOLATILITY   DELTA   GAMMA   THETA    VEGA  \
0        144.35          0.3000  1.0000  0.0000  0.0000  0.0000   
1        139.55          0.3000  1.0000  0.0000  0.0000  0.0000   
2        134.45          0.3000  1.0000  0.0000  0.0000  0.0000   
3        128.80          0.3000  1.0000  0.0000  0.0000  0.0000   
4        123.80          0.3000  1.0000  0.0000  0.0000  0.0000   
...         ...             ...     ...     ...     ...     ...   
2257     168.50          0.5541 -0.5489  0.0021 -0.0057  1.3732   
2258     178.55          0.5541 -0.5610  0.0021 -0.0039  1.3674   
2259     188.55          0.5541 -0.5727  0.0020 -0.0021  1.3605   
2260     198.55          0.5541 -0.5841  0.0020 -0.0002  1.3527   
2261     208.55          0.5541 -0.5952  0.0020  0.0016  1.3440   

     UNDERLYING_SYMBOL EXPIRATION_DATE  STRIKE_PRICE CALL_PUT_IND  
0                                                NaN               
1                                                NaN               
2                                                NaN               
3                                                NaN               
4                                                NaN               
...                ...             ...           ...          ...  
2257              AAPL        20270115         410.0            P  
2258              AAPL        20270115         420.0            P  
2259              AAPL        20270115         430.0            P  
2260              AAPL        20270115         440.0            P  
2261              AAPL        20270115         450.0            P  

[2262 rows x 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.<br />
\\\\
OPRA Daily data is retrieved from the `US_OPTIONS_EOD` database.<br />
\\\\
Here the sample database `US_OPTIONS_EOD_SAMPLE` is used.<br />
\\\\
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.<br />
\\\\
Filtered for the `AAPL` underlying and expiration date 20270115.<br />
\\\\
Data is displayed grouped by strike price, with Call and Put metrics associated with each strike.<br />
\\\\
The daily `DAY` records are joined by time to the static `STAT` records with a lookback of up to 1 day (86400s).<br />
\\\\
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.

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

```myst-ansi
           Time  STRIKE_PRICE  C_VOLUME  P_VOLUME  C_OPEN_INT  P_OPEN_INT  \
0    2025-01-04           NaN       NaN       NaN         NaN         NaN   
1    2025-01-04           NaN       NaN       NaN         NaN         NaN   
2    2025-01-04           NaN       NaN       NaN         NaN         NaN   
3    2025-01-04           NaN       NaN       NaN         NaN         NaN   
4    2025-01-04           NaN       NaN       NaN         NaN         NaN   
...         ...           ...       ...       ...         ...         ...   
2257 2025-01-04         410.0       NaN       0.0         NaN         0.0   
2258 2025-01-04         420.0       NaN       0.0         NaN         0.0   
2259 2025-01-04         430.0       NaN       0.0         NaN         0.0   
2260 2025-01-04         440.0       NaN       0.0         NaN         0.0   
2261 2025-01-04         450.0       NaN       0.0         NaN         0.0   

      C_BID   P_BID  C_ASK   P_ASK  C_IV    P_IV  C_DELTA  P_DELTA  C_GAMMA  \
0       NaN     NaN    NaN     NaN   NaN     NaN      NaN      NaN      NaN   
1       NaN     NaN    NaN     NaN   NaN     NaN      NaN      NaN      NaN   
2       NaN     NaN    NaN     NaN   NaN     NaN      NaN      NaN      NaN   
3       NaN     NaN    NaN     NaN   NaN     NaN      NaN      NaN      NaN   
4       NaN     NaN    NaN     NaN   NaN     NaN      NaN      NaN      NaN   
...     ...     ...    ...     ...   ...     ...      ...      ...      ...   
2257    NaN  164.55    NaN  168.50   NaN  0.5541      NaN  -0.5489      NaN   
2258    NaN  174.60    NaN  178.55   NaN  0.5541      NaN  -0.5610      NaN   
2259    NaN  184.60    NaN  188.55   NaN  0.5541      NaN  -0.5727      NaN   
2260    NaN  194.60    NaN  198.55   NaN  0.5541      NaN  -0.5841      NaN   
2261    NaN  204.60    NaN  208.55   NaN  0.5541      NaN  -0.5952      NaN   

      P_GAMMA  C_THETA  P_THETA  C_VEGA  P_VEGA  
0         NaN      NaN      NaN     NaN     NaN  
1         NaN      NaN      NaN     NaN     NaN  
2         NaN      NaN      NaN     NaN     NaN  
3         NaN      NaN      NaN     NaN     NaN  
4         NaN      NaN      NaN     NaN     NaN  
...       ...      ...      ...     ...     ...  
2257   0.0021      NaN  -0.0057     NaN  1.3732  
2258   0.0021      NaN  -0.0039     NaN  1.3674  
2259   0.0020      NaN  -0.0021     NaN  1.3605  
2260   0.0020      NaN  -0.0002     NaN  1.3527  
2261   0.0020      NaN   0.0016     NaN  1.3440  

[2262 rows x 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.<br />
\\\\
Underlying equity pricing is retrieved from the US_COMP database (sample database `US_COMP_SAMPLE`).<br />
\\\\
Data is Filtered for the `AAPL` underlying (options via the `AAPL %` pattern, equity via SYMBOL_NAME `AAPL`)
and for the expiration date 20270115.<br />
\\\\
The option trades are joined by time to the static records and to the prevailing underlying equity trade.<br />
\\\\
Because the data may have been published at different times before the target time, lookbacks are defined so
the prevailing values are returned.<br />
\\\\
`MONEYNESS` is computed as Strike Price minus the underlying price.

```python
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.<br />
\\\\
Here the sample database `US_OPTIONS_SAMPLE` is used.<br />
\\\\
Trades are joined by time to the static `STAT` records to obtain the Expiration Date, Strike Price and
Call/Put Indicator.<br />
\\\\
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.

```python
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.<br />
\\\\
Filtering with `US_OPTIONS Option` selects the symbols that correspond to OPRA Options.<br />
\\\\
Additionally filtering on `UNDERLYING_SYMBOL` equal to `AAPL` returns the option contracts for `AAPL`.

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

```myst-ansi
                   Time     DB_NAME              DB_SYMBOL NAME SEC_TYPE  \
0   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610C00250000        Option   
1   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610P00250000        Option   
2   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610C00255000        Option   
3   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610P00255000        Option   
4   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610C00260000        Option   
..                  ...         ...                    ...  ...      ...   
995 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702P00170000        Option   
996 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702C00175000        Option   
997 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702P00175000        Option   
998 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702C00180000        Option   
999 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702P00180000        Option   

    UNDERLYING_SYMBOL CALL_PUT_IND  STRIKE_PRICE EXPIRATION_DATE  
0                AAPL            C         250.0        20260610  
1                AAPL            P         250.0        20260610  
2                AAPL            C         255.0        20260610  
3                AAPL            P         255.0        20260610  
4                AAPL            C         260.0        20260610  
..                ...          ...           ...             ...  
995              AAPL            P         170.0        20260702  
996              AAPL            C         175.0        20260702  
997              AAPL            P         175.0        20260702  
998              AAPL            C         180.0        20260702  
999              AAPL            P         180.0        20260702  

[1000 rows x 9 columns]
```

## OPRA Options Chain Symbol Universe Summary Retrieval

Return the Options Chain of contracts for an OPRA underlying from the Symbol Universe.<br />
\\\\
Filtering with `US_OPTIONS Option` selects the symbols that correspond to OPRA Options.<br />
\\\\
Additionally filtering on `UNDERLYING_SYMBOL` equal to `AAPL` returns the option contracts for `AAPL`.

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

```myst-ansi
                   Time     DB_NAME              DB_SYMBOL NAME SEC_TYPE  \
0   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610C00250000        Option   
1   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610P00250000        Option   
2   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610C00255000        Option   
3   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610P00255000        Option   
4   2026-06-11 00:00:00  US_OPTIONS  AAPL  260610C00260000        Option   
..                  ...         ...                    ...  ...      ...   
995 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702P00170000        Option   
996 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702C00175000        Option   
997 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702P00175000        Option   
998 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702C00180000        Option   
999 2026-06-11 20:00:00  US_OPTIONS  AAPL  260702P00180000        Option   

    UNDERLYING_SYMBOL CALL_PUT_IND  STRIKE_PRICE EXPIRATION_DATE  
0                AAPL            C         250.0        20260610  
1                AAPL            P         250.0        20260610  
2                AAPL            C         255.0        20260610  
3                AAPL            P         255.0        20260610  
4                AAPL            C         260.0        20260610  
..                ...          ...           ...             ...  
995              AAPL            P         170.0        20260702  
996              AAPL            C         175.0        20260702  
997              AAPL            P         175.0        20260702  
998              AAPL            C         180.0        20260702  
999              AAPL            P         180.0        20260702  

[1000 rows x 9 columns]
```

## CME Options Symbol Universe Retrieval

Return the number of Options contracts for `CME` from the Symbol Universe.<br />
\\\\
Filtering with `CME Option` selects the symbols that correspond to CME Options.<br />
\\\\
`CME` populates `UNDERLYING_SEC_TYPE`, allowing Products to be grouped.

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

```myst-ansi
          Time DB_NAME SEC_TYPE UNDERLYING_SEC_TYPE PRODUCT_CODE  \
0   2026-06-12     CME   Option         Agriculture          0HO   
1   2026-06-12     CME   Option         Agriculture          0OC   
2   2026-06-12     CME   Option         Agriculture          12C   
3   2026-06-12     CME   Option         Agriculture          12K   
4   2026-06-12     CME   Option         Agriculture          12S   
..         ...     ...      ...                 ...          ...   
883 2026-06-12     CME   Option               Metal          W2S   
884 2026-06-12     CME   Option               Metal          W3S   
885 2026-06-12     CME   Option               Metal          W4S   
886 2026-06-12     CME   Option               Other          0CA   
887 2026-06-12     CME   Option               Other          ECO   

     CONTRACT_COUNT  
0                64  
1               710  
2                56  
3                60  
4                66  
..              ...  
883             672  
884             370  
885             148  
886             492  
887             404  

[888 rows x 6 columns]
```

## CME Treasury Options Symbol Universe Retrieval

Return Interest Rate Options contracts for `CME` from the Symbol Universe.<br />
\\\\
Filtering with `CME Option` selects the symbols that correspond to CME Options.<br />
\\\\
Filtering with `UNDERLYING_SEC_TYPE` set to `Interest Rate` restricts the results to Treasury Options.

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

```myst-ansi
                       Time DB_NAME        DB_SYMBOL  \
0   2026-06-11 00:00:00.000     CME      GB2\F26\108   
1   2026-06-11 00:00:00.000     CME      GB2\F26\118   
2   2026-06-11 00:00:00.000     CME      GB2\F26\127   
3   2026-06-11 00:00:00.000     CME    GB2\F26\128.5   
4   2026-06-11 00:00:00.000     CME     GB2\F26\97.5   
..                      ...     ...              ...   
995 2026-06-11 21:00:00.934     CME  VT3\F26\102.125   
996 2026-06-11 21:00:00.934     CME   VF4\F26\108.75   
997 2026-06-11 21:00:00.934     CME   VF4\R26\104.75   
998 2026-06-11 21:00:00.934     CME   VF4\F26\109.25   
999 2026-06-11 21:00:00.934     CME   VF4\F26\109.75   

                                                 NAME SEC_TYPE  \
0      US Treasury Bond Tuesday Week 2 Jun26 108 Call   Option   
1      US Treasury Bond Tuesday Week 2 Jun26 118 Call   Option   
2      US Treasury Bond Tuesday Week 2 Jun26 127 Call   Option   
3    US Treasury Bond Tuesday Week 2 Jun26 128.5 Call   Option   
4     US Treasury Bond Tuesday Week 2 Jun26 97.5 Call   Option   
..                                                ...      ...   
995    2-Year T-Note Monday Week 3 Jun26 102.125 Call   Option   
996     5-Year T-Note Monday Week 4 Jun26 108.75 Call   Option   
997      5-Year T-Note Monday Week 4 Jun26 104.75 Put   Option   
998     5-Year T-Note Monday Week 4 Jun26 109.25 Call   Option   
999     5-Year T-Note Monday Week 4 Jun26 109.75 Call   Option   

    UNDERLYING_SEC_TYPE PRODUCT_CODE CALL_PUT_IND  STRIKE_PRICE  \
0         Interest Rate          GB2            C       108.000   
1         Interest Rate          GB2            C       118.000   
2         Interest Rate          GB2            C       127.000   
3         Interest Rate          GB2            C       128.500   
4         Interest Rate          GB2            C        97.500   
..                  ...          ...          ...           ...   
995       Interest Rate          VT3            C       102.125   
996       Interest Rate          VF4            C       108.750   
997       Interest Rate          VF4            P       104.750   
998       Interest Rate          VF4            C       109.250   
999       Interest Rate          VF4            C       109.750   

    EXPIRATION_DATE  
0          20260609  
1          20260609  
2          20260609  
3          20260609  
4          20260609  
..              ...  
995        20260615  
996        20260622  
997        20260622  
998        20260622  
999        20260622  

[1000 rows x 10 columns]
```

## CME Options Chain Symbol Universe Retrieval

Return the Options Chain of contracts for a CME Product from the Symbol Universe.<br />
\\\\
Filtering with `CME Option` selects the symbols that correspond to CME Options.<br />
\\\\
Additionally filtering on `PRODUCT_CODE` equal to `LO`, the CME Product Code for Crude Oil.

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

```myst-ansi
                       Time DB_NAME     DB_SYMBOL                        NAME  \
0   2026-06-11 21:00:00.809     CME  LO\X29\113.5   Crude Oil Dec29 113.5 Put   
1   2026-06-11 21:00:00.809     CME     LO\R29\75      Crude Oil Jun29 75 Put   
2   2026-06-11 21:00:00.809     CME      LO\L31\4      Crude Oil Dec31 4 Call   
3   2026-06-11 21:00:00.809     CME   LO\X27\19.5    Crude Oil Dec27 19.5 Put   
4   2026-06-11 21:00:00.809     CME   LO\L29\90.5   Crude Oil Dec29 90.5 Call   
..                      ...     ...           ...                         ...   
995 2026-06-11 21:00:01.109     CME  LO\R28\152.5   Crude Oil Jun28 152.5 Put   
996 2026-06-11 21:00:01.109     CME   LO\F27\66.5   Crude Oil Jun27 66.5 Call   
997 2026-06-11 21:00:01.109     CME  LO\L29\105.5  Crude Oil Dec29 105.5 Call   
998 2026-06-11 21:00:01.109     CME     LO\R30\24      Crude Oil Jun30 24 Put   
999 2026-06-11 21:00:01.109     CME  LO\X32\127.5   Crude Oil Dec32 127.5 Put   

    SEC_TYPE UNDERLYING_SEC_TYPE PRODUCT_CODE CALL_PUT_IND  STRIKE_PRICE  \
0     Option              Energy           LO            P         113.5   
1     Option              Energy           LO            P          75.0   
2     Option              Energy           LO            C           4.0   
3     Option              Energy           LO            P          19.5   
4     Option              Energy           LO            C          90.5   
..       ...                 ...          ...          ...           ...   
995   Option              Energy           LO            P         152.5   
996   Option              Energy           LO            C          66.5   
997   Option              Energy           LO            C         105.5   
998   Option              Energy           LO            P          24.0   
999   Option              Energy           LO            P         127.5   

    EXPIRATION_DATE  
0          20291114  
1          20290517  
2          20311117  
3          20271116  
4          20291114  
..              ...  
995        20280517  
996        20270517  
997        20291114  
998        20300516  
999        20321116  

[1000 rows x 10 columns]
```

## Query Options Volume Open Interest And Greeks Analysis

Options Volume, Open Interest, and Greeks Analysis by Expiration and Call/Put.

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

```myst-ansi
        Time  TOTAL_OPEN_INTEREST  TOTAL_VOLUME  AVG_UNDERLYING_PRICE  \
0 2025-01-28           21880286.0       5846439            224.641871   

   AVG_IMPLIED_VOL  AVG_DELTA  AVG_GAMMA  AVG_THETA  AVG_VEGA  CONTRACT_COUNT  
0         0.400747   0.087597    0.00411  -0.028074  0.260932           11460  
```
