{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"\n",
"# Binomial Pricing Model\n",
"### [(Go to Quant Lab)](https://israeldi.github.io/quantlab/)\n",
"\n",
"#### Source: Numerical Methods in Finance with C++\n",
"\n",
"© Maciej J. Capinski, Tomasz Zastawniak\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Table of Contents\n",
"\n",
"1. [Random Numbers](#1.-Random-Numbers)\n",
"2. [Plotting Random Samples](#2.-Plotting-Random-Samples)\n",
"3. [Simulation](#3.-Simulation)\n",
" - 3.1 [Random Variables](#3.1-Random-Variables)\n",
" - 3.2 [Stochastic Processes](#3.2-Stochastic-Processes)\n",
" - 3.2.1 [Geometric Brownian Motion](#3.2.1-Geometric-Brownian-Motion)\n",
" - 3.2.2 [Square-Root Diffusion](#3.2.2-Square-Root-Diffusion)\n",
" - 3.2.3 [Stochastic Processes](#3.2-Stochastic-Processes)\n",
" - 3.2.4 [Stochastic Processes](#3.2-Stochastic-Processes)\n",
" - 3.3 [Variance Reduction](#3.3-Variance-Reduction)\n",
"4. [Valuation](#4.-Valuation)\n",
" - 4.1 [European Options](#4.1-European-Options)\n",
" - 4.2 [American Options](#4.2-American-Options)\n",
"5. [Risk Measures](#5.-Risk-Measures)\n",
" - 5.1 [Value-at-Risk](#5.1-Value-at-Risk)\n",
" - 5.2 [Credit Value Adjustments](#5.2-Credit-Value-Adjustments)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Initially import all the modules we will be using for our notebook"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"import numpy as np\n",
"import numpy.random as npr \n",
"# from pylab import plt, mpl\n",
"import sys\n",
"import os"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 Creating Main Program"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hi there\n"
]
},
{
"ename": "KeyboardInterrupt",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py\u001b[0m in \u001b[0;36m_input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m 884\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 885\u001b[0;31m \u001b[0mident\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreply\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstdin_socket\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 886\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/jupyter_client/session.py\u001b[0m in \u001b[0;36mrecv\u001b[0;34m(self, socket, mode, content, copy)\u001b[0m\n\u001b[1;32m 802\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 803\u001b[0;31m \u001b[0mmsg_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msocket\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecv_multipart\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 804\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mzmq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mZMQError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/zmq/sugar/socket.py\u001b[0m in \u001b[0;36mrecv_multipart\u001b[0;34m(self, flags, copy, track)\u001b[0m\n\u001b[1;32m 469\u001b[0m \"\"\"\n\u001b[0;32m--> 470\u001b[0;31m \u001b[0mparts\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mflags\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtrack\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtrack\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 471\u001b[0m \u001b[0;31m# have first part already, only loop while more to receive\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32mzmq/backend/cython/socket.pyx\u001b[0m in \u001b[0;36mzmq.backend.cython.socket.Socket.recv\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mzmq/backend/cython/socket.pyx\u001b[0m in \u001b[0;36mzmq.backend.cython.socket.Socket.recv\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mzmq/backend/cython/socket.pyx\u001b[0m in \u001b[0;36mzmq.backend.cython.socket._recv_copy\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/zmq/backend/cython/checkrc.pxd\u001b[0m in \u001b[0;36mzmq.backend.cython.checkrc._check_rc\u001b[0;34m()\u001b[0m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: ",
"\nDuring handling of the above exception, another exception occurred:\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m__name__\u001b[0m\u001b[0;34m==\u001b[0m \u001b[0;34m\"__main__\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Hi there\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0minput\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Provide a character: \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py\u001b[0m in \u001b[0;36mraw_input\u001b[0;34m(self, prompt)\u001b[0m\n\u001b[1;32m 858\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_parent_ident\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 859\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_parent_header\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 860\u001b[0;31m \u001b[0mpassword\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 861\u001b[0m )\n\u001b[1;32m 862\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py\u001b[0m in \u001b[0;36m_input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m 888\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 889\u001b[0m \u001b[0;31m# re-raise KeyboardInterrupt, to truncate traceback\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 890\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 891\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 892\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"if __name__== \"__main__\":\n",
" print(\"Hi there\")\n",
" input(\"Provide a character: \")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Directory where we will save our plots\n",
"directory = \"./images\"\n",
"if not os.path.exists(directory):\n",
" os.makedirs(directory)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 Entering Data\n",
"#### ([Back to Top](#Table-of-Contents))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"ename": "KeyboardInterrupt",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py\u001b[0m in \u001b[0;36m_input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m 884\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 885\u001b[0;31m \u001b[0mident\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreply\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstdin_socket\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 886\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/jupyter_client/session.py\u001b[0m in \u001b[0;36mrecv\u001b[0;34m(self, socket, mode, content, copy)\u001b[0m\n\u001b[1;32m 802\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 803\u001b[0;31m \u001b[0mmsg_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msocket\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecv_multipart\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 804\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mzmq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mZMQError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/zmq/sugar/socket.py\u001b[0m in \u001b[0;36mrecv_multipart\u001b[0;34m(self, flags, copy, track)\u001b[0m\n\u001b[1;32m 469\u001b[0m \"\"\"\n\u001b[0;32m--> 470\u001b[0;31m \u001b[0mparts\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mflags\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtrack\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtrack\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 471\u001b[0m \u001b[0;31m# have first part already, only loop while more to receive\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32mzmq/backend/cython/socket.pyx\u001b[0m in \u001b[0;36mzmq.backend.cython.socket.Socket.recv\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mzmq/backend/cython/socket.pyx\u001b[0m in \u001b[0;36mzmq.backend.cython.socket.Socket.recv\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mzmq/backend/cython/socket.pyx\u001b[0m in \u001b[0;36mzmq.backend.cython.socket._recv_copy\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/zmq/backend/cython/checkrc.pxd\u001b[0m in \u001b[0;36mzmq.backend.cython.checkrc._check_rc\u001b[0;34m()\u001b[0m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: ",
"\nDuring handling of the above exception, another exception occurred:\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m__name__\u001b[0m\u001b[0;34m==\u001b[0m \u001b[0;34m\"__main__\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mS0\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Enter S_0: \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mU\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Enter U: \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mD\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Enter D: \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mR\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Enter R: \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py\u001b[0m in \u001b[0;36mraw_input\u001b[0;34m(self, prompt)\u001b[0m\n\u001b[1;32m 858\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_parent_ident\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 859\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_parent_header\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 860\u001b[0;31m \u001b[0mpassword\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 861\u001b[0m )\n\u001b[1;32m 862\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py\u001b[0m in \u001b[0;36m_input_request\u001b[0;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[1;32m 888\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 889\u001b[0m \u001b[0;31m# re-raise KeyboardInterrupt, to truncate traceback\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 890\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 891\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 892\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"if __name__== \"__main__\":\n",
" S0 = float(input(\"Enter S_0: \"))\n",
" U = float(input(\"Enter U: \"))\n",
" D = float(input(\"Enter D: \"))\n",
" R = float(input(\"Enter R: \"))\n",
"\n",
" # making sure that 0= U or R <= D):\n",
" print(\"Arbitrage exists\")\n",
" print(\"Terminating program\")\n",
" sys.exit()\n",
"\n",
" print(\"Input data checked\")\n",
" print(\"There is no arbitrage\\n\")\n",
" \n",
" # compute risk-neutral probability\n",
" print(\"q = \", (R - D) / (U - D))\n",
" \n",
" # compute stock price at node n=3,i=2\n",
" n = 3; i = 2\n",
" print(\"n = \", n)\n",
" print(\"i = \", i)\n",
" print(\"S(n,i) = \", S0* math.pow(1 + U,i) * math.pow(1 + D, n - i))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.3 Functions\n",
"#### ([Back to Top](#Table-of-Contents))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"uuid": "4618b170-6bd3-4500-905a-0fe402f198c1"
},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'U' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m__name__\u001b[0m\u001b[0;34m==\u001b[0m \u001b[0;34m\"__main__\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 40\u001b[0m \u001b[0;31m# compute risk-neutral probability\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 41\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"q = \"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mRiskNeutProb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mU\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mD\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mR\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 42\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 43\u001b[0m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mGetInputData\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'U' is not defined"
]
}
],
"source": [
"# computing risk-neutral probability\n",
"def RiskNeutProb(U, D, R):\n",
" return (R - D) / (U - D)\n",
"\n",
"# computing the stock price at node n,i\n",
"def S(S0, U, D, n, i):\n",
" return S0 * math.pow(1 + U,i) * math.pow(1 + D, n - i)\n",
"\n",
"def isValidInput(S0, U, D, R):\n",
" # making sure that 0= U or R <= D):\n",
" print(\"Arbitrage exists\")\n",
" print(\"Terminating program\")\n",
" return 0\n",
" \n",
" return 1\n",
"\n",
"# inputting, displaying and checking model data\n",
"def GetInputData():\n",
" #entering data\n",
" params = (\"S0\", \"U\", \"D\", \"R\")\n",
" S0, U, D, R = [float(input(\"Enter %s: \" % (var))) for var in params]\n",
" \n",
" if not isValidInput(S0, U, D, R):\n",
" return 0\n",
" \n",
" print(\"Input data checked\")\n",
" print(\"There is no arbitrage\\n\")\n",
" d = locals().copy()\n",
" return d\n",
"\n",
"\n",
"if __name__== \"__main__\":\n",
" # compute risk-neutral probability\n",
" print(\"q = \", RiskNeutProb(U, D, R))\n",
" \n",
" output = GetInputData()\n",
" if output == 0:\n",
" sys.exit()\n",
" \n",
" # Update our parameters\n",
" locals().update(output)\n",
" \n",
" # compute stock price at node n=3,i=2\n",
" n = 3; i = 2\n",
" print(\"n = \", n)\n",
" print(\"i = \", i)\n",
" print(\"S(n,i) = \", S(S0,U,D,n,i))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.0 Object Oriented European and American\n",
"#### ([Back to Top](#Table-of-Contents))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.19822404128088741"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Binomial Model (Parent class) ---------------------------------------------------\n",
"class BinModel:\n",
" def __init__(self, S0=100, U=0.1, D=-0.1, R=0):\n",
" self.S0 = S0\n",
" self.U = U\n",
" self.D = D\n",
" self.R = R\n",
" \n",
" def RiskNeutProb(self):\n",
" return (self.R - self.D) / (self.U - self.D)\n",
" \n",
" def S(self, n, i):\n",
" return self.S0 * math.pow(1 + self.U, i) * math.pow(1 + self.D, n - i)\n",
" \n",
" \n",
"# European Option class ------------------------------------------------------------------\n",
"class EurOption():\n",
" \n",
" def PriceByCRR(self, Model, N=3):\n",
" q = Model.RiskNeutProb();\n",
" Price = np.zeros(N + 1)\n",
" \n",
" for i in range(0, N + 1):\n",
" Price[i] = self.Payoff(Model.S(N, i))\n",
" \n",
" for n in range(N - 1, -1, -1):\n",
" for i in range(0, n + 1):\n",
" Price[i] = (q * Price[i+1] + (1 - q) * Price[i]) / (1 + Model.R);\n",
"\n",
" return Price[0]\n",
" \n",
"# American Option class\n",
"class AmOption():\n",
" def PriceBySnell(self, Model, N=3):\n",
" q=Model.RiskNeutProb()\n",
" Price = np.zeros(N + 1)\n",
" \n",
" for i in range(0, N + 1):\n",
" Price[i] = self.Payoff(Model.S(N, i))\n",
"\n",
" for n in range(N - 1, -1, -1):\n",
" for i in range(0, n + 1):\n",
" ContVal = (q * Price[i+1] + (1 - q) * Price[i]) / (1 + Model.R)\n",
" Price[i] = self.Payoff(Model.S(n,i))\n",
" if (ContVal > Price[i]):\n",
" Price[i] = ContVal\n",
" \n",
" return Price[0]\n",
" \n",
"class AsianOption()\n",
" def PriceAsian(self, Model, N=3):\n",
" q = Model.RiskNeutProb();\n",
" Price = np.zeros(N + 1)\n",
" \n",
" for i in range(0, 2 * N + 1):\n",
" \n",
" Price[i] = self.Payoff(Model.S(N, i))\n",
" \n",
" for n in range(N - 1, -1, -1):\n",
" for i in range(0, n + 1):\n",
" Price[i] = (q * Price[i+1] + (1 - q) * Price[i]) / (1 + Model.R);\n",
"\n",
" return Price[0]\n",
"\n",
"# Payoff Classes ---------------------------------------------------------------------------- \n",
"class Call(EurOption, AmOption):\n",
" \n",
" def __init__(self, K=1):\n",
" self.K = K\n",
" \n",
" def Payoff(self, z):\n",
" if (z > self.K): \n",
" return z - self.K\n",
" \n",
" return 0\n",
"\n",
"class Put(EurOption, AmOption):\n",
" \n",
" def __init__(self, K=1):\n",
" self.K = K\n",
" \n",
" def Payoff(self, z):\n",
" if (z < self.K): \n",
" return self.K - z\n",
" \n",
" return 0\n",
"\n",
"class Digital_Call(EurOption, AmOption):\n",
" def __init__(self, K=1):\n",
" self.K = K\n",
" \n",
" def Payoff(self, z):\n",
" if self.K < z:\n",
" return 1\n",
" return 0\n",
" \n",
"class BullSpread(EurOption, AmOption):\n",
" def __init__(self, K1=1, K2 = 2):\n",
" self.K1 = K1\n",
" self.K2 = K2\n",
" \n",
" def Payoff\n",
" \n",
"\n",
"model = BinModel(S0=10, U=0.2, D=-0.1, R=0.1)\n",
"Option1 = Digital_Call(K=22)\n",
"Option1.PriceByCRR(model, N=6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises:\n",
"\n",
"1. Modify the `PriceByCRR()` function in `EurOption` Class to compute the time $0$ price of a European option using the **Cox–Ross–Rubinstein (CRR)** formula:\n",
"$$H(0)=\\frac{1}{(1+R)^{N}}\\sum_{i=0}^{N}\\frac{N!}{i!(N-i)!}q^{i}(1-q)^{N-i}h(S(N,I))$$\n",
"\n",
"\n",
"2. The payoff of a **digital call** with strike price $K$ is:\n",
"$$h^{digit\\thinspace call}(z)=\\begin{cases}\n",
"1 & \\textrm{{if} }K