This project aims to take a CSV extract of the option prices and output an implied Probability Density Function from the option prices. Here my input is a simple extract from Deribit. On the top right, you can see the CSV file. I want to generate this PDF using this CSV file.
Morgan Stanley explains how assuming risk-neutral probabilities you can use butterfly options strategies to estimate the odds of the underlying expiring in this range.
Ignoring the premium payment, the average payoff in the butterfly range is: max_payoff/2
If you look at football betting quotes, the likelihood of an event happening is: 1/payoff
Let's look at a sample example: Man City are playing Luton at home (which they are this weekend), they have a payoff of 1.1 Their implied odds of winning are 1/1.1 ~ 91% (including the premium charged by the bookmaker)
It's the same thing in this case. You pay a premium p betting the stock will expire in the butterfly range. The average payoff will be max_payoff/2 = bfly_width/2.
The implied odds for this range are given by: premium / average payoff
Using bids and asks marks in the CSV file, it is easy to price butterflies. However, this isn't accurate enough since there are insufficient data points. I will calibrate a SABR stochastic volatility model to the mid-price, recreating a volatility smile. However, this strategy might not be representative and I might want to calibrate the model to the bids and asks to include trading costs.
Given the number of option prices we're dealing with, SABR stochastic volatility (plot below) is much better than interpolation since we won't risk overfitting our option prices.
The options data file doesn't include the price of the underlying future, which means we need to extract it from the option prices. Assuming zero rates, the Put-Call Parity (PCP) states:
Call_Price - Put_Price = Underlying_Price - Strike_Price
Since in crypto our Call and Put prices are expressed in units of underlying, we can write PCP as:
(Call_Price - Put_Price)Underlying_Price = Underlying_Price - Strike_Price
Solving for Spot:
Underlying = - (Strike)/(Call - Put - 1)
Using this formula on all option pairs and averaging the Underlying yields a quite strong approximation of the underlying future price.
The .plot_pdf_cdf(self) function yields the following plots:
The main issue with this code is the risk of not converging the calibration. I did a good job randomising the inital_values and calibrating several times to find the best params but this might still not be enough and the algo might fail to converge in some cases. The calibration didn't work as well for 27SEP24 expiration but still produced a strong approximation. So far the code prices butterflies with the SABR mid-price curve. It is not considering the spread.