Last active
December 7, 2024 12:54
-
-
Save ChypherC0d3/24551846ddc002f2b588a29f334f5253 to your computer and use it in GitHub Desktop.
Implied Volatility using C++ and Python.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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