Last active
March 20, 2023 21:09
-
-
Save cesarvargas00/5f9a4e5b224ced18b63c27dd1c94c399 to your computer and use it in GitHub Desktop.
black and scholes
This file contains hidden or 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
| { | |
| "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