Skip to content

Instantly share code, notes, and snippets.

@CY0xZ
Last active August 29, 2022 19:13
Show Gist options
  • Save CY0xZ/24551846ddc002f2b588a29f334f5253 to your computer and use it in GitHub Desktop.
Save CY0xZ/24551846ddc002f2b588a29f334f5253 to your computer and use it in GitHub Desktop.
Implied Volatility using C++ and Python.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Implied Volatility using C++ and Python.ipynb",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/CY0xZ/24551846ddc002f2b588a29f334f5253/implied-volatility-using-c-and-python.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vR7ZuynzhwNp"
},
"source": [
"#Implied Volatility using Bisection Function provided by CY0xZ\n",
"\n",
"https://sites.google.com/view/vinegarhill-financelabs/black-scholes-merton/implied-volatility\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "oE7U6xz7hgwu",
"outputId": "2b61269e-7d91-4e46-f4df-85a1982e6b52"
},
"source": [
"%%writefile main.cpp\n",
"\n",
"//Implied Volatility using Black Scholes with Dividend\n",
"//Needs to be tested more (looks to be working)\n",
"// Documents/VirtualWindowsOracle\n",
"\n",
"#include <iostream>\n",
"#include <cmath>\n",
"#include <vector>\n",
"\n",
"\n",
"using namespace std;\n",
"\n",
"// N(0,1) density\n",
"double\n",
"f (double x)\n",
"{\n",
" double pi = 4.0 * atan (1.0);\n",
" return exp (-x * x * 0.5) / sqrt (2 * pi);\n",
"}\n",
"\n",
"// Boole's Rule\n",
"double\n",
"Boole (double StartPoint, double EndPoint, int n)\n",
"{\n",
" vector < double >X (n + 1, 0.0);\n",
" vector < double >Y (n + 1, 0.0);\n",
" double delta_x = (EndPoint - StartPoint) / double (n);\n",
" for (int i = 0; i <= n; i++)\n",
" {\n",
" X[i] = StartPoint + i * delta_x;\n",
" Y[i] = f (X[i]);\n",
" }\n",
" double sum = 0;\n",
" for (int t = 0; t <= (n - 1) / 4; t++)\n",
" {\n",
" int ind = 4 * t;\n",
" sum +=\n",
"\t(1 / 45.0) * (14 * Y[ind] + 64 * Y[ind + 1] + 24 * Y[ind + 2] +\n",
"\t\t 64 * Y[ind + 3] + 14 * Y[ind + 4]) * delta_x;\n",
" }\n",
" return sum;\n",
"}\n",
"\n",
"// N(0,1) cdf by Boole's Rule\n",
"double\n",
"N (double x)\n",
"{\n",
" return Boole (-10.0, x, 240);\n",
"}\n",
"\n",
"// Black-Scholes Call Price\n",
"double\n",
"BSPrice (double S, double K, double r, double T, double q, double v, char PutCall)\n",
"{\n",
" double d = (log (S / K) + T * (r - q + 0.5 * v * v)) / (v * sqrt (T));\n",
" double call = S *exp(-q*T)* N (d) - exp (-r * T) * K * N (d - v * sqrt (T));\n",
" if (PutCall == 'C')\n",
" return call;\n",
" else\n",
" // Put Parity\n",
" return call - S*exp (-q * T) + K * exp (-r * T);\n",
"}\n",
"\n",
"// Bisection Algorithm\n",
"double BisecBSV(double S, double K, double r, double T, double q,\n",
" double a, double b, double MktPrice, char PutCall) {\n",
" const int MaxIter = 50000;\n",
" double Tol = 0.0000001;\n",
" double midP = 0.0, midCdif;\n",
" double lowCdif = MktPrice - BSPrice(S, K, r, T, q, a, PutCall);\n",
" double highCdif = MktPrice - BSPrice(S, K, r, T, q, b, PutCall);\n",
" if (lowCdif*highCdif > 0)\n",
" return -1;\n",
" else\n",
" for (int i = 0; i <= MaxIter; i++) {\n",
" midP = (a + b) / 2.0;\n",
" midCdif = MktPrice - BSPrice(S, K, r, T, q, midP, PutCall);\n",
" if (abs(midCdif)<Tol) goto LastLine;\n",
" else {\n",
" if (midCdif>0) a = midP;\n",
" else b = midP;\n",
" }\n",
" }\n",
"LastLine:\n",
" return midP;\n",
"}\n",
"\n",
"// Main program\n",
"int main() {\n",
" double S = 100;\t\t\t// Spot Price\n",
" double K = 100;\t\t\t// Exercise\n",
" double r = 0.05;\t\t\t// Interest Rate\n",
" double T = 1; // Maturity in Years\n",
" double q = 0.0;\n",
" double a = 0.00000001;\t\t// Bisection algorithm starting value for lower volatility\n",
" double b = 7.0;\t\t\t// Bisection algorithm starting value for higher volatility\n",
" double MktPrice = 10.4506;\n",
" \n",
" char PutCall = 'C';\t\t// C\n",
" \n",
" double IV = BisecBSV(S, K, r, T, q, a, b, MktPrice, PutCall);\n",
" cout << \" Implied Volatility = \" << IV << \" \" << endl;\n",
" \n",
"}\n"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"Overwriting main.cpp\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "GAQJltOFhuuQ",
"outputId": "b29a0f6c-c923-40a2-986d-da63b3453121"
},
"source": [
"%%script bash\n",
"\n",
"g++ main.cpp -std=c++11\n",
"./a.out"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
" Implied Volatility = 0.2 \n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "U3T1GNtFqL3Q"
},
"source": [
"#Python Code for Implied Volatility for Black Scholes Model"
]
},
{
"cell_type": "code",
"metadata": {
"id": "rTuW25skoqNw"
},
"source": [
"# https://github.com/YuChenAmberLu?tab=repositories \n",
"# Adapted for Dividends by Shang and Byrne\n",
"# import certain packages\n",
"from math import log, sqrt, pi, exp\n",
"from scipy.stats import norm\n",
"\n",
"#import numpy as np\n",
"#import pandas as pd\n",
"#from pandas import DataFrame\n",
"\n",
"# Underlying price (per share): S; \n",
"# Strike price of the option (per share): K;\n",
"# Time to maturity (years): T;\n",
"# Continuously compounding risk-free interest rate: r;\n",
"# Continuously compounding dividend: q;\n",
"# Volatility: sigma;\n",
"\n",
"## define two functions, d1 and d2 in Black-Scholes model\n",
"def d1(S,K,T,r,q,sigma):\n",
" return(log(S/K)+(r - q +sigma**2/2.)*T)/sigma*sqrt(T)\n",
"def d2(S,K,T,r,q,sigma):\n",
" return d1(S,K,T,r,q,sigma)-sigma*sqrt(T)\n",
"\n",
"\n",
"## define the call options price function\n",
"def bs_call(S,K,T,r,q,sigma):\n",
" return S*exp(-q*T)*norm.cdf(d1(S,K,T,r,q,sigma))-K*exp(-r*T)*norm.cdf(d2(S,K,T,r,q,sigma))\n",
"\n",
"## define the put options price function\n",
"def bs_put(S,K,T,r,q,sigma):\n",
" return K*exp(-r*T)-S*exp(-q*T)+bs_call(S,K,T,r,q,sigma)\n",
"\n",
"# Implied Volatility using bisection\n",
"# quantconnect.com/forum/discussion/2269/generate-volatility-surface-plot-by-interpolation/p1\n",
"def implied_vol(option_type, option_price, S, K, r, T, q):\n",
" # apply bisection method to get the implied volatility by solving the BSM function\n",
" precision = 0.00001\n",
" upper_vol = 50.0\n",
" max_vol = 50.0\n",
" min_vol = 0.0001\n",
" lower_vol = 0.0001\n",
" iteration = 0 \n",
"\n",
" while 1:\n",
" iteration +=1 \n",
" mid_vol = (upper_vol + lower_vol)/2.0\n",
" \n",
" if option_type == 'c':\n",
" price = bs_call(S,K,T,r,q,mid_vol)\n",
" lower_price = bs_call(S,K,T,r,q,lower_vol)\n",
" if (lower_price - option_price) * (price - option_price) > 0:\n",
" lower_vol = mid_vol \n",
" else:\n",
" upper_vol = mid_vol\n",
" if abs(price - option_price) < precision: break\n",
" if mid_vol > max_vol - 5 : \n",
" mid_vol = 0.0001\n",
" break\n",
"\n",
" elif option_type == 'p':\n",
" price = bs_put(S,K,T,r,q,mid_vol)\n",
" upper_price = bs_put(S,K,T,r,q,upper_vol)\n",
"\n",
" if (upper_price - option_price) * (price - option_price) > 0:\n",
" upper_vol = mid_vol \n",
" else:\n",
" lower_vol = mid_vol \n",
" \n",
" if abs(price - option_price) < precision: break \n",
" \n",
" if iteration > 100: break\n",
" \n",
" return mid_vol "
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "-RXsk96PqA7l"
},
"source": [
"# implied_vol(option_type, option_price, S, K, r, T, q)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "lnaJN1Thox_L",
"outputId": "787a9e56-b9f1-4026-8661-0a54fb208355"
},
"source": [
"print (implied_vol('p', 5.57, 100, 100, 0.05, 1, 0)) "
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"0.199906290602684\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xLpyGgyPrObe",
"outputId": "a29d900e-bf78-41da-d532-1442deecb7f3"
},
"source": [
"print (implied_vol('c', 10.4506, 100, 100, 0.05, 1, 0)) "
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"0.20000054025873543\n"
],
"name": "stdout"
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment