Skip to content

Instantly share code, notes, and snippets.

@cesarvargas00
Last active March 20, 2023 21:09
Show Gist options
  • Select an option

  • Save cesarvargas00/5f9a4e5b224ced18b63c27dd1c94c399 to your computer and use it in GitHub Desktop.

Select an option

Save cesarvargas00/5f9a4e5b224ced18b63c27dd1c94c399 to your computer and use it in GitHub Desktop.
black and scholes
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "85bfc30b",
"metadata": {},
"outputs": [],
"source": [
"\"\"\"\n",
"black and scholes formula implementation\n",
"author: cesar vargas\n",
"license: MIT\n",
"\"\"\"\n",
"\n",
"import math\n",
"from statistics import NormalDist\n",
"\n",
"\"\"\"\n",
"S = stock price\n",
"X = strike\n",
"r = discount rate\n",
"T = days to maturity\n",
"vol = volatility\n",
"type = call | put\n",
"C = option price\n",
"\"\"\"\n",
"\n",
"def bs(S, X, r, T, vol, type='call'):\n",
" if S == 0: return 0\n",
" if T == 0: return max(S - X, 0) if type == 'call' else max(X - S, 0)\n",
"\n",
" T = T / 252\n",
" d1 = (math.log(S / X) + (r + (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" d2 = (math.log(S / X) + (r - (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
"\n",
" return S * NormalDist().cdf(d1) - X * math.exp(-r * T) * NormalDist().cdf(d2) if type == 'call' else X * math.exp(-r * T) * NormalDist().cdf(-d2) - S * NormalDist().cdf(-d1)\n",
"\n",
"def vega(S, X, r, T, vol):\n",
" if T == 0:\n",
" return 0\n",
" T = T / 252\n",
" d1 = (math.log(S / X) + (r + (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" r = S * NormalDist().pdf(d1) * T ** .5\n",
" return r\n",
"\n",
"def gamma(S, X, r, T, vol):\n",
" if T == 0:\n",
" return 0\n",
" T = T / 252\n",
" d1 = (math.log(S / X) + (r + (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" return NormalDist().pdf(d1)/(S * vol * T ** .5)\n",
"\n",
"def delta(S, X, r, T, vol, type='call'):\n",
" if T == 0:\n",
" return 0\n",
" T = T / 252\n",
" d1 = (math.log(S / X) + (r + (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" return NormalDist().cdf(d1) if type == 'call' else NormalDist().cdf(d1) - 1\n",
"\n",
"def theta(S, X, r, T, vol, type='call'):\n",
" if T == 0:\n",
" return 0\n",
" T = T / 252\n",
" direction = 1 if type == 'call' else -1\n",
" d1 = (math.log(S / X) + (r + (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" d2 = (math.log(S / X) + (r - (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" return -1*((S * NormalDist().pdf(d1) * vol) / (2 * T ** .5)) - direction * r * X * math.exp(-r * T) * NormalDist().cdf(direction * d2)\n",
"\n",
"def rho(S, X, r, T, vol, type='call'):\n",
" if T == 0:\n",
" return 0\n",
" T = T / 252\n",
" direction = 1 if type == 'call' else -1\n",
" d2 = (math.log(S / X) + (r - (vol ** 2) / 2) * T) / (vol * T ** .5)\n",
" return direction * X * T * math.exp(-r * T) * NormalDist().cdf(direction * d2)\n",
"\n",
"def iv(S, X, r, T, C, type='call', precision=5, max_iterations=20):\n",
" def iv_estimate(T, C, S): # https://www.tandfonline.com/doi/abs/10.2469/faj.v44.n5.80\n",
" T = T / 252\n",
" return ((2 * math.pi / T) ** .5) * C / S\n",
" iv = iv_estimate(T, C, S)\n",
" iv_next = 0\n",
" i = 0\n",
" while(i < max_iterations and round(iv_next, precision) != round(iv , precision)):\n",
" v = vega(S, X, r, T, iv)\n",
" if iv_next != 0:\n",
" iv = iv_next\n",
" iv_next = iv - (bs(S, X, r, T, iv, type) - C) / v # newton raphson\n",
" i += 1\n",
" return iv"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "df20a524",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.17721275420860705"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"iv(23.78, 23.46, .0265, 21, 0.69)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "66a25845",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.6900000163013331"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bs(23.78, 23.46, .0265, 21, 0.17721275420860705)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "88174084",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.31019211083346937"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gamma(23.78, 23.46, .0265, 21, 0.17721275420860705)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "750918e4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.37735225598835226"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"delta(23.78, 23.46, .0265, 21, 0.17721275420860705)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "19a0f3a5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"-0.012434336238683103"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"theta(23.78, 23.46, .0265, 21, 0.17721275420860705)/252"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "39bf130a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.025904080319670925"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vega(23.78, 23.46, .0265, 21, 0.17721275420860705)/100"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "0f2ef7bb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.00011922411350132915"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rho(23.78, 23.46, .0265, 21, 0.17721275420860705)/10000"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e97b4904",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment