Skip to main content

Generate probability distributions on the future price of publicly traded securities using options data

Project description

OIPD logo

PyPI - Python Version Open In Colab Chat on Discord PyPI Downloads

Overview

OIPD (Options-implied Probability Distribution) provides 2 capabilities:

1. Compute market-implied probability distributions of future asset prices.

  • While markets don't predict the future with certainty, under the efficient market view, these market expectations represent the best available estimate of what might happen.

example

2. Fit arbitrage-free volatility smiles and surfaces for pricing and risk analysis.

  • Fitting a vol surface well is a complex and expensive process, with the leading software provider costing $50k USD/month/seat. OIPD open-sources the entire pipeline fairly rigorously, with further improvements in the roadmap.
vol curve vol surface

See the full documentation site for details.

Quick start

1. Installation

pip install oipd

2. Mental model for using OIPD

[!TIP] For non-technical users, you can safely skip this section and jump to Section 3 to compute future market-implied probabilities.


OIPD has four core objects.

A simple way to understand the package is by use case: fitting at a single future date vs over time, and working in implied volatility vs probabilities.

Scope Volatility Layer Probability Layer
Single future date VolCurve ProbCurve
Future time horizon VolSurface ProbSurface

You can think about the lifecycle in three steps:

  1. Initialize the estimator object with configuration.
  2. Call .fit(chain, market) to calibrate.
  3. Query/plot the fitted object, or convert from vol to probability via .implied_distribution().

If you're familiar with scikit-learn, this is the same mental model: configure an estimator, call fit, then inspect outputs.

Conceptual flow:

Step 1: Fit volatility
  Initialize VolCurve / VolSurface object
      + options chain + market inputs
      -> .fit(...)
      -> fitted VolCurve / VolSurface object (inspect IV, prices, greeks, etc.)

Step 2: Convert fitted volatility to probability
  Use fitted VolCurve / VolSurface
      -> .implied_distribution()
      -> ProbCurve / ProbSurface object (inspect PDF, CDF, quantiles, moments, etc.)

3. Quickstart tutorial in computing market-implied probability distributions

This quickstart will cover the functionality in (1) computing market-implied probabilities. See the included jupyter notebook for a full example on using the automated yfinance connection to download options data and compute market-implied probabilities for Palantir.

For a more technical tutorial including the functionality of (2) volatility fitting, see the additional jupyter notebooks in the examples directory, as well as the full documentation.

3A. Usage for computing a probability distribution on a specific future date

import matplotlib.pyplot as plt

from oipd import MarketInputs, ProbCurve, sources

# 1. we download data using the built-in yfinance connection
ticker = "PLTR"                               # specify the stock ticker
expiries = sources.list_expiry_dates(ticker)  # see all expiry dates
single_expiry = expiries[1]                   # select one of the expiry dates you're interested in 

chain, snapshot = sources.fetch_chain(ticker, expiries=single_expiry) # download the options chain data, and a snapshot at the time of download

# 2. fill in the parameters 
market = MarketInputs(
    valuation_date=snapshot.date,               # date on which the options data was downloaded
    underlying_price=snapshot.underlying_price, # the price of the underlying stock at the time when the options data was downloaded 
    risk_free_rate=0.04,                        # the risk-free rate of return. Use the US Fed or Treasury yields that are closest to the horizon of the expiry date
)

# 3. compute the future probability distribution using the data and parameters
prob = ProbCurve.from_chain(chain, market)

# 4. query the computed result to understand market-implied probabilities and other statistics
prob.plot()
plt.show()

prob_below = prob.prob_below(100)   # P(price < 100)
prob_above = prob.prob_above(120)   # P(price >= 120)
q50 = prob.quantile(0.50)           # median implied price
skew = prob.skew()                  # skew

example

3B. Usage for computing probabilities over time

import matplotlib.pyplot as plt

from oipd import MarketInputs, ProbSurface, sources

# 1. download multi-expiry data using the built-in yfinance connection
ticker = "PLTR"
chain_surface, snapshot_surface = sources.fetch_chain(
    ticker,
    horizon="12m",  # auto-fetch all listed expiries inside the horizon
)

# 2. fill in the parameters
surface_market = MarketInputs(
    valuation_date=snapshot_surface.date,               # date on which the options data was downloaded
    underlying_price=snapshot_surface.underlying_price, # price of the underlying stock at download time
    risk_free_rate=0.04,                                # risk-free rate for the horizon
)

# 3. compute the probability surface using the data and parameters
surface = ProbSurface.from_chain(chain_surface, surface_market)

# 4. query and visualize the surface
surface.plot_fan() # Plot a fan chart of price probability over time
plt.show()

# 5. query at arbitrary maturities directly from ProbSurface
pdf_45d = surface.pdf(100, t=45/365)       # density at K=100, 45 days
cdf_45d = surface.cdf(100, t="2025-02-15") # equivalent date-style maturity input
q50_45d = surface.quantile(0.50, t=45/365) # median at 45 days

# 6. "slice" the surface to get a ProbCurve, and query its statistical properties in the same manner as in example A 
surface.expiries                                  # list all the expiry dates that were captured
curve = surface.slice(surface.expiries[0]) # get a slice on the first expiry
curve.prob_below(100)                      # query probabilities and statistics 
curve.kurtosis()                           

example

OIPD also supports manual CSV or DataFrame uploads.

See more examples for demos.

Community

Pull requests welcome! Reach out on GitHub issues to discuss design choices.

Join the Discord community to share ideas, discuss strategies, and get support. Message me with your feature requests, and let me know how you use this.

Contributors

Thanks to everyone who has contributed code:

Contributors

And special thanks for support on theory, implementation, or advisory:

  • integral-alpha.com
  • Jannic H., Chun H. H., and Melanie C.
  • and others who prefer to go unnamed

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oipd-2.0.2.tar.gz (184.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oipd-2.0.2-py3-none-any.whl (170.9 kB view details)

Uploaded Python 3

File details

Details for the file oipd-2.0.2.tar.gz.

File metadata

  • Download URL: oipd-2.0.2.tar.gz
  • Upload date:
  • Size: 184.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for oipd-2.0.2.tar.gz
Algorithm Hash digest
SHA256 f806b9adbedce7c61d4c48a81a8c21f2bd3d77486f0d40e7175b4cc6901923d0
MD5 5d42818ebee525446768ebb048ce7253
BLAKE2b-256 b9c32aed7becd6d0d536c9a70ce6fe58927d8d1809ca6776871976919edfbaa5

See more details on using hashes here.

File details

Details for the file oipd-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: oipd-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 170.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for oipd-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6ec8fd5a797122365cdf4fb8090dc82d84886c72352438252a3338de804015c8
MD5 4263acc89df56f39f9f74e09d362e3f4
BLAKE2b-256 a942b57ecde6a6a77b835a98225e45fcee141cf77ee1a4fe5dd7d2ff33e93097

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page