├── README.md ├── LICENSE.txt ├── .gitignore └── code ├── finpy_01.ipynb └── finpy_04.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # Financial Theory with Python 2 | 3 | **A Gentle Introduction** 4 | 5 | ## About this Repository 6 | 7 | This repository provides Python code and Jupyter Notebooks accompanying the 8 | _**Financial Theory with Python — A Gentle Introduction**_ book published by [O'Reilly](https://learning.oreilly.com/library/view/financial-theory-with/9781098104344/). 9 | 10 | 11 | 12 | You can **register for free** on our [Quant Platform](http://finpy.pqp.io) to make 13 | easy use of the Python code in the cloud. No local Python installation is required. 14 | 15 | ## Copyright & Disclaimer 16 | 17 | © Dr. Yves J. Hilpisch | The Python Quants GmbH | September 2021 18 | 19 | All code and Jupyter Notebooks come without representations or warranties, to the extent permitted by applicable law. They are intended for personal use only and do not represent any investment advice or recommendation of any form. 20 | 21 | 22 | 23 | http://tpq.io | training@tpq.io | http://twitter.com/dyjh 24 | 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | All the contents as well as the code, Jupyter Notebooks and other materials in this Github repository and on the Quant Platform (http://finpy.pqp.io) related to Financial Theory with Python (book, course, class, program) by Dr. Yves J. Hilpisch (The Python Quants GmbH) are copyrighted and only intended for personal use. 2 | 3 | Any kind of sharing, distribution, duplication, etc. without written permission by the The Python Quants GmbH is prohibited. 4 | 5 | The contents, Python code, Jupyter Notebooks and other materials come without warranties or representations, to the extent permitted by applicable law. 6 | 7 | Notice that the code provided might be work in progress and that substantial additions, changes, updates, etc. can take place in the future. It is advised to regularly check for updates. 8 | 9 | None of the material represents any kind of recommendation or investment advice. The material is only meant as a technical illustration. Leveraged and unleveraged trading of financial instruments, and contracts for difference (CFDs) in particular, involves a number of risks. Make sure to understand and manage these risks. 10 | 11 | (c) Dr. Yves J. Hilpisch | The Python Quants GmbH | October 2021 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Specifics 2 | dx/ 3 | *.swp 4 | _build/ 5 | *.cfg 6 | .DS_Store 7 | source/ 8 | trading* 9 | 10 | # Byte-compiled / optimized / DLL files 11 | __pycache__/ 12 | *.py[cod] 13 | *$py.class 14 | 15 | 16 | # C extensions 17 | *.so 18 | 19 | # Distribution / packaging 20 | .Python 21 | build/ 22 | develop-eggs/ 23 | dist/ 24 | downloads/ 25 | eggs/ 26 | .eggs/ 27 | lib/ 28 | lib64/ 29 | parts/ 30 | sdist/ 31 | var/ 32 | wheels/ 33 | *.egg-info/ 34 | .installed.cfg 35 | *.egg 36 | MANIFEST 37 | 38 | # PyInstaller 39 | # Usually these files are written by a python script from a template 40 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 41 | *.manifest 42 | *.spec 43 | 44 | # Installer logs 45 | pip-log.txt 46 | pip-delete-this-directory.txt 47 | 48 | # Unit test / coverage reports 49 | htmlcov/ 50 | .tox/ 51 | .coverage 52 | .coverage.* 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | *.cover 57 | .hypothesis/ 58 | .pytest_cache/ 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | db.sqlite3 68 | 69 | # Flask stuff: 70 | instance/ 71 | .webassets-cache 72 | 73 | # Scrapy stuff: 74 | .scrapy 75 | 76 | # Sphinx documentation 77 | docs/_build/ 78 | 79 | # PyBuilder 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # celery beat schedule file 89 | celerybeat-schedule 90 | 91 | # SageMath parsed files 92 | *.sage.py 93 | 94 | # Environments 95 | .env 96 | .venv 97 | env/ 98 | venv/ 99 | ENV/ 100 | env.bak/ 101 | venv.bak/ 102 | 103 | # Spyder project settings 104 | .spyderproject 105 | .spyproject 106 | 107 | # Rope project settings 108 | .ropeproject 109 | 110 | # mkdocs documentation 111 | /site 112 | 113 | # mypy 114 | .mypy_cache/ 115 | -------------------------------------------------------------------------------- /code/finpy_01.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\"The
" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Financial Theory with Python\n", 15 | "**—A Gentle Introduction**\n", 16 | "\n", 17 | "Dr Yves J Hilpisch | The Python Quants | The AI Machine\n", 18 | "\n", 19 | "http://tpq.io | http://aimachine.io | [@dyjh](http://twitter.com/dyjh)\n", 20 | "\n", 21 | "" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "## Chapter 01 — Finance and Python" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "## Approach of the Book" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 1, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "vu = 1.5" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 2, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "vd = 3.75" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 3, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "data": { 63 | "text/plain": [ 64 | "float" 65 | ] 66 | }, 67 | "execution_count": 3, 68 | "metadata": {}, 69 | "output_type": "execute_result" 70 | } 71 | ], 72 | "source": [ 73 | "type(vu)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 4, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "data": { 83 | "text/plain": [ 84 | "5.25" 85 | ] 86 | }, 87 | "execution_count": 4, 88 | "metadata": {}, 89 | "output_type": "execute_result" 90 | } 91 | ], 92 | "source": [ 93 | "vu + vd" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 5, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "import numpy as np" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 6, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "v = np.array((vu, vd))" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 7, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "data": { 121 | "text/plain": [ 122 | "array([1.5 , 3.75])" 123 | ] 124 | }, 125 | "execution_count": 7, 126 | "metadata": {}, 127 | "output_type": "execute_result" 128 | } 129 | ], 130 | "source": [ 131 | "v" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 8, 137 | "metadata": {}, 138 | "outputs": [ 139 | { 140 | "data": { 141 | "text/plain": [ 142 | "dtype('float64')" 143 | ] 144 | }, 145 | "execution_count": 8, 146 | "metadata": {}, 147 | "output_type": "execute_result" 148 | } 149 | ], 150 | "source": [ 151 | "v.dtype" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 9, 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "data": { 161 | "text/plain": [ 162 | "(2,)" 163 | ] 164 | }, 165 | "execution_count": 9, 166 | "metadata": {}, 167 | "output_type": "execute_result" 168 | } 169 | ], 170 | "source": [ 171 | "v.shape" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 10, 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "data": { 181 | "text/plain": [ 182 | "array([3. , 7.5])" 183 | ] 184 | }, 185 | "execution_count": 10, 186 | "metadata": {}, 187 | "output_type": "execute_result" 188 | } 189 | ], 190 | "source": [ 191 | "v + v" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 11, 197 | "metadata": {}, 198 | "outputs": [ 199 | { 200 | "data": { 201 | "text/plain": [ 202 | "array([ 4.5 , 11.25])" 203 | ] 204 | }, 205 | "execution_count": 11, 206 | "metadata": {}, 207 | "output_type": "execute_result" 208 | } 209 | ], 210 | "source": [ 211 | "3 * v" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 12, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "S = np.array((20, 5))" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 13, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "K = 15" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": 14, 235 | "metadata": {}, 236 | "outputs": [], 237 | "source": [ 238 | "C = np.maximum(S - K, 0)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 15, 244 | "metadata": {}, 245 | "outputs": [ 246 | { 247 | "data": { 248 | "text/plain": [ 249 | "array([5, 0])" 250 | ] 251 | }, 252 | "execution_count": 15, 253 | "metadata": {}, 254 | "output_type": "execute_result" 255 | } 256 | ], 257 | "source": [ 258 | "C" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "\"The
\n", 266 | "\n", 267 | "http://tpq.io | @dyjh | training@tpq.io" 268 | ] 269 | } 270 | ], 271 | "metadata": { 272 | "anaconda-cloud": {}, 273 | "kernelspec": { 274 | "display_name": "Python 3 (ipykernel)", 275 | "language": "python", 276 | "name": "python3" 277 | }, 278 | "language_info": { 279 | "codemirror_mode": { 280 | "name": "ipython", 281 | "version": 3 282 | }, 283 | "file_extension": ".py", 284 | "mimetype": "text/x-python", 285 | "name": "python", 286 | "nbconvert_exporter": "python", 287 | "pygments_lexer": "ipython3", 288 | "version": "3.10.12" 289 | } 290 | }, 291 | "nbformat": 4, 292 | "nbformat_minor": 4 293 | } 294 | -------------------------------------------------------------------------------- /code/finpy_04.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\"The
" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Financial Theory with Python\n", 15 | "**—A Gentle Introduction**\n", 16 | "\n", 17 | "Dr Yves J Hilpisch | The Python Quants | The AI Machine\n", 18 | "\n", 19 | "http://tpq.io | http://aimachine.io | [@dyjh](http://twitter.com/dyjh)\n", 20 | "\n", 21 | "" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "## Chapter 04 — Optimality and Equilibrium" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "## Utility Maximization" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 1, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "def u(c):\n", 45 | " return -c[0] * c[1]" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 2, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "w = 10" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 3, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "from scipy.optimize import minimize" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 4, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "cons = ({'type': 'eq', 'fun': lambda c: c[0] + c[1] - w})" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 5, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "opt = minimize(u, (1, 1), constraints=cons)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 6, 87 | "metadata": {}, 88 | "outputs": [ 89 | { 90 | "data": { 91 | "text/plain": [ 92 | " fun: -24.999999999999996\n", 93 | " jac: array([-5., -5.])\n", 94 | " message: 'Optimization terminated successfully'\n", 95 | " nfev: 6\n", 96 | " nit: 2\n", 97 | " njev: 2\n", 98 | " status: 0\n", 99 | " success: True\n", 100 | " x: array([5., 5.])" 101 | ] 102 | }, 103 | "execution_count": 6, 104 | "metadata": {}, 105 | "output_type": "execute_result" 106 | } 107 | ], 108 | "source": [ 109 | "opt" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 7, 115 | "metadata": {}, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "array([5., 5.])" 121 | ] 122 | }, 123 | "execution_count": 7, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | } 127 | ], 128 | "source": [ 129 | "opt['x']" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 8, 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "data": { 139 | "text/plain": [ 140 | "24.999999999999996" 141 | ] 142 | }, 143 | "execution_count": 8, 144 | "metadata": {}, 145 | "output_type": "execute_result" 146 | } 147 | ], 148 | "source": [ 149 | "-opt['fun'] " 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 9, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "def iu(u, c0):\n", 159 | " return u / c0" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 10, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "def c1(c0):\n", 169 | " return w - c0" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 11, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "import numpy as np\n", 179 | "np.set_printoptions(precision=5)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 12, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "from pylab import mpl, plt\n", 189 | "plt.style.use('seaborn-v0_8')\n", 190 | "mpl.rcParams['font.family'] = 'serif'\n", 191 | "%config InlineBackend.figure_formats = ['svg']" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 13, 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "c0 = np.linspace(1, w)" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 14, 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "data": { 210 | "image/svg+xml": [ 211 | "\n", 212 | "\n", 214 | "\n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " 2023-10-16T06:35:25.900047\n", 220 | " image/svg+xml\n", 221 | " \n", 222 | " \n", 223 | " Matplotlib v3.8.0, https://matplotlib.org/\n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 458 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 544 | " \n", 545 | " \n", 546 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 649 | " \n", 650 | " \n", 651 | " \n", 652 | " \n", 653 | " \n", 654 | " \n", 655 | " \n", 656 | " \n", 657 | " \n", 660 | " \n", 661 | " \n", 662 | " \n", 663 | " \n", 664 | " \n", 665 | " \n", 666 | " \n", 667 | " \n", 668 | " \n", 669 | " \n", 670 | " \n", 671 | " \n", 672 | " \n", 723 | " \n", 724 | " \n", 725 | " \n", 776 | " \n", 777 | " \n", 778 | " \n", 829 | " \n", 830 | " \n", 831 | " \n", 882 | " \n", 883 | " \n", 884 | " \n", 885 | " \n", 896 | " \n", 897 | " \n", 898 | " \n", 899 | " \n", 900 | " \n", 901 | " \n", 902 | " \n", 905 | " \n", 906 | " \n", 907 | " \n", 910 | " \n", 911 | " \n", 912 | " \n", 915 | " \n", 916 | " \n", 917 | " \n", 920 | " \n", 921 | " \n", 922 | " \n", 923 | " \n", 927 | " \n", 928 | " \n", 929 | " \n", 930 | " \n", 931 | " \n", 932 | " \n", 963 | " \n", 988 | " \n", 1019 | " \n", 1057 | " \n", 1082 | " \n", 1105 | " \n", 1106 | " \n", 1128 | " \n", 1149 | " \n", 1178 | " \n", 1211 | " \n", 1235 | " \n", 1271 | " \n", 1294 | " \n", 1295 | " \n", 1296 | " \n", 1297 | " \n", 1298 | " \n", 1299 | " \n", 1300 | " \n", 1301 | " \n", 1302 | " \n", 1303 | " \n", 1304 | " \n", 1305 | " \n", 1306 | " \n", 1307 | " \n", 1308 | " \n", 1309 | " \n", 1310 | " \n", 1311 | " \n", 1312 | " \n", 1313 | " \n", 1314 | " \n", 1315 | " \n", 1319 | " \n", 1320 | " \n", 1321 | " \n", 1322 | " \n", 1323 | " \n", 1324 | " \n", 1347 | " \n", 1360 | " \n", 1374 | " \n", 1399 | " \n", 1400 | " \n", 1401 | " \n", 1402 | " \n", 1403 | " \n", 1404 | " \n", 1405 | " \n", 1406 | " \n", 1407 | " \n", 1411 | " \n", 1412 | " \n", 1413 | " \n", 1414 | " \n", 1415 | " \n", 1416 | " \n", 1440 | " \n", 1441 | " \n", 1442 | " \n", 1443 | " \n", 1444 | " \n", 1445 | " \n", 1446 | " \n", 1447 | " \n", 1448 | " \n", 1452 | " \n", 1453 | " \n", 1454 | " \n", 1455 | " \n", 1456 | " \n", 1457 | " \n", 1489 | " \n", 1490 | " \n", 1491 | " \n", 1492 | " \n", 1493 | " \n", 1494 | " \n", 1495 | " \n", 1496 | " \n", 1497 | " \n", 1498 | " \n", 1499 | " \n", 1500 | " \n", 1501 | " \n", 1502 | " \n", 1503 | " \n", 1504 | " \n", 1505 | " \n", 1530 | " \n", 1543 | " \n", 1552 | " \n", 1565 | " \n", 1566 | " \n", 1567 | " \n", 1568 | " \n", 1569 | " \n", 1570 | " \n", 1571 | " \n", 1572 | " \n", 1573 | " \n", 1574 | " \n", 1575 | " \n", 1576 | " \n", 1577 | " \n", 1578 | " \n", 1579 | " \n", 1580 | " \n", 1581 | " \n", 1582 | " \n", 1583 | "\n" 1584 | ], 1585 | "text/plain": [ 1586 | "
" 1587 | ] 1588 | }, 1589 | "metadata": {}, 1590 | "output_type": "display_data" 1591 | } 1592 | ], 1593 | "source": [ 1594 | "plt.figure(figsize=(10, 6))\n", 1595 | "plt.plot(c0, c1(c0), label='budget constraint', lw=3.0)\n", 1596 | "plt.plot(c0, iu(15, c0), '--', label='$u=15$')\n", 1597 | "plt.plot(c0, iu(25, c0), label='$u=25$')\n", 1598 | "plt.plot(c0, iu(35, c0), '-.', label='$u=35$')\n", 1599 | "plt.plot(opt['x'][0], opt['x'][1], 'ro', label='$c=(5, 5)$')\n", 1600 | "plt.legend(loc=0);" 1601 | ] 1602 | }, 1603 | { 1604 | "cell_type": "markdown", 1605 | "metadata": {}, 1606 | "source": [ 1607 | "## Logarithmic Function" 1608 | ] 1609 | }, 1610 | { 1611 | "cell_type": "code", 1612 | "execution_count": 15, 1613 | "metadata": {}, 1614 | "outputs": [], 1615 | "source": [ 1616 | "x = np.linspace(0.5, 10, 50)" 1617 | ] 1618 | }, 1619 | { 1620 | "cell_type": "code", 1621 | "execution_count": 16, 1622 | "metadata": {}, 1623 | "outputs": [ 1624 | { 1625 | "data": { 1626 | "text/plain": [ 1627 | "array([0.5 , 0.69388, 0.88776, 1.08163, 1.27551])" 1628 | ] 1629 | }, 1630 | "execution_count": 16, 1631 | "metadata": {}, 1632 | "output_type": "execute_result" 1633 | } 1634 | ], 1635 | "source": [ 1636 | "x[:5]" 1637 | ] 1638 | }, 1639 | { 1640 | "cell_type": "code", 1641 | "execution_count": 17, 1642 | "metadata": {}, 1643 | "outputs": [], 1644 | "source": [ 1645 | "u = np.log(x)" 1646 | ] 1647 | }, 1648 | { 1649 | "cell_type": "code", 1650 | "execution_count": 18, 1651 | "metadata": {}, 1652 | "outputs": [], 1653 | "source": [ 1654 | "u1 = 1 / x" 1655 | ] 1656 | }, 1657 | { 1658 | "cell_type": "code", 1659 | "execution_count": 19, 1660 | "metadata": {}, 1661 | "outputs": [], 1662 | "source": [ 1663 | "u2 = -1 / x ** 2" 1664 | ] 1665 | }, 1666 | { 1667 | "cell_type": "code", 1668 | "execution_count": 20, 1669 | "metadata": {}, 1670 | "outputs": [ 1671 | { 1672 | "data": { 1673 | "image/svg+xml": [ 1674 | "\n", 1675 | "\n", 1677 | "\n", 1678 | " \n", 1679 | " \n", 1680 | " \n", 1681 | " \n", 1682 | " 2023-10-16T06:35:25.999774\n", 1683 | " image/svg+xml\n", 1684 | " \n", 1685 | " \n", 1686 | " Matplotlib v3.8.0, https://matplotlib.org/\n", 1687 | " \n", 1688 | " \n", 1689 | " \n", 1690 | " \n", 1691 | " \n", 1692 | " \n", 1693 | " \n", 1694 | " \n", 1695 | " \n", 1696 | " \n", 1697 | " \n", 1703 | " \n", 1704 | " \n", 1705 | " \n", 1706 | " \n", 1712 | " \n", 1713 | " \n", 1714 | " \n", 1715 | " \n", 1716 | " \n", 1719 | " \n", 1720 | " \n", 1721 | " \n", 1722 | " \n", 1723 | " \n", 1724 | " \n", 1725 | " \n", 1750 | " \n", 1751 | " \n", 1752 | " \n", 1753 | " \n", 1754 | " \n", 1755 | " \n", 1756 | " \n", 1757 | " \n", 1760 | " \n", 1761 | " \n", 1762 | " \n", 1763 | " \n", 1764 | " \n", 1765 | " \n", 1766 | " \n", 1789 | " \n", 1790 | " \n", 1791 | " \n", 1792 | " \n", 1793 | " \n", 1794 | " \n", 1795 | " \n", 1796 | " \n", 1799 | " \n", 1800 | " \n", 1801 | " \n", 1802 | " \n", 1803 | " \n", 1804 | " \n", 1805 | " \n", 1836 | " \n", 1837 | " \n", 1838 | " \n", 1839 | " \n", 1840 | " \n", 1841 | " \n", 1842 | " \n", 1843 | " \n", 1846 | " \n", 1847 | " \n", 1848 | " \n", 1849 | " \n", 1850 | " \n", 1851 | " \n", 1852 | " \n", 1891 | " \n", 1892 | " \n", 1893 | " \n", 1894 | " \n", 1895 | " \n", 1896 | " \n", 1897 | " \n", 1898 | " \n", 1901 | " \n", 1902 | " \n", 1903 | " \n", 1904 | " \n", 1905 | " \n", 1906 | " \n", 1907 | " \n", 1921 | " \n", 1942 | " \n", 1943 | " \n", 1944 | " \n", 1945 | " \n", 1946 | " \n", 1947 | " \n", 1948 | " \n", 1949 | " \n", 1950 | " \n", 1951 | " \n", 1952 | " \n", 1955 | " \n", 1956 | " \n", 1957 | " \n", 1958 | " \n", 1959 | " \n", 1960 | " \n", 1961 | " \n", 1968 | " \n", 1969 | " \n", 1970 | " \n", 1971 | " \n", 1972 | " \n", 1973 | " \n", 1974 | " \n", 1975 | " \n", 1976 | " \n", 1979 | " \n", 1980 | " \n", 1981 | " \n", 1982 | " \n", 1983 | " \n", 1984 | " \n", 1985 | " \n", 2019 | " \n", 2020 | " \n", 2021 | " \n", 2022 | " \n", 2023 | " \n", 2024 | " \n", 2025 | " \n", 2026 | " \n", 2027 | " \n", 2030 | " \n", 2031 | " \n", 2032 | " \n", 2033 | " \n", 2034 | " \n", 2035 | " \n", 2036 | " \n", 2037 | " \n", 2038 | " \n", 2039 | " \n", 2040 | " \n", 2041 | " \n", 2042 | " \n", 2045 | " \n", 2046 | " \n", 2047 | " \n", 2048 | " \n", 2049 | " \n", 2050 | " \n", 2051 | " \n", 2052 | " \n", 2053 | " \n", 2054 | " \n", 2055 | " \n", 2056 | " \n", 2057 | " \n", 2060 | " \n", 2061 | " \n", 2062 | " \n", 2063 | " \n", 2064 | " \n", 2065 | " \n", 2066 | " \n", 2067 | " \n", 2068 | " \n", 2069 | " \n", 2070 | " \n", 2071 | " \n", 2074 | " \n", 2075 | " \n", 2076 | " \n", 2077 | " \n", 2078 | " \n", 2079 | " \n", 2080 | " \n", 2081 | " \n", 2082 | " \n", 2083 | " \n", 2084 | " \n", 2085 | " \n", 2088 | " \n", 2089 | " \n", 2090 | " \n", 2091 | " \n", 2092 | " \n", 2093 | " \n", 2094 | " \n", 2095 | " \n", 2096 | " \n", 2097 | " \n", 2098 | " \n", 2099 | " \n", 2150 | " \n", 2151 | " \n", 2152 | " \n", 2203 | " \n", 2204 | " \n", 2205 | " \n", 2256 | " \n", 2257 | " \n", 2258 | " \n", 2261 | " \n", 2262 | " \n", 2263 | " \n", 2266 | " \n", 2267 | " \n", 2268 | " \n", 2271 | " \n", 2272 | " \n", 2273 | " \n", 2276 | " \n", 2277 | " \n", 2278 | " \n", 2279 | " \n", 2283 | " \n", 2284 | " \n", 2285 | " \n", 2286 | " \n", 2287 | " \n", 2288 | " \n", 2311 | " \n", 2312 | " \n", 2313 | " \n", 2314 | " \n", 2315 | " \n", 2316 | " \n", 2320 | " \n", 2321 | " \n", 2322 | " \n", 2323 | " \n", 2324 | " \n", 2325 | " \n", 2357 | " \n", 2364 | " \n", 2379 | " \n", 2380 | " \n", 2381 | " \n", 2382 | " \n", 2383 | " \n", 2384 | " \n", 2385 | " \n", 2386 | " \n", 2387 | " \n", 2388 | " \n", 2392 | " \n", 2393 | " \n", 2394 | " \n", 2395 | " \n", 2396 | " \n", 2397 | " \n", 2421 | " \n", 2422 | " \n", 2423 | " \n", 2424 | " \n", 2425 | " \n", 2426 | " \n", 2427 | " \n", 2428 | " \n", 2429 | " \n", 2430 | " \n", 2431 | " \n", 2432 | " \n", 2433 | " \n", 2434 | " \n", 2435 | " \n", 2436 | " \n", 2437 | " \n", 2438 | " \n", 2439 | "\n" 2440 | ], 2441 | "text/plain": [ 2442 | "
" 2443 | ] 2444 | }, 2445 | "metadata": {}, 2446 | "output_type": "display_data" 2447 | } 2448 | ], 2449 | "source": [ 2450 | "plt.figure(figsize=(10, 6))\n", 2451 | "plt.plot(x, u, label='$u$')\n", 2452 | "plt.plot(x, u1, '--', label='$du/dx$')\n", 2453 | "plt.plot(x, u2, '-.', label='$d^2u/dx^2$')\n", 2454 | "plt.legend(loc=0);" 2455 | ] 2456 | }, 2457 | { 2458 | "cell_type": "markdown", 2459 | "metadata": {}, 2460 | "source": [ 2461 | "## Time-Additive Utility" 2462 | ] 2463 | }, 2464 | { 2465 | "cell_type": "code", 2466 | "execution_count": 21, 2467 | "metadata": {}, 2468 | "outputs": [], 2469 | "source": [ 2470 | "import math" 2471 | ] 2472 | }, 2473 | { 2474 | "cell_type": "code", 2475 | "execution_count": 22, 2476 | "metadata": {}, 2477 | "outputs": [], 2478 | "source": [ 2479 | "from scipy.optimize import minimize" 2480 | ] 2481 | }, 2482 | { 2483 | "cell_type": "code", 2484 | "execution_count": 23, 2485 | "metadata": {}, 2486 | "outputs": [], 2487 | "source": [ 2488 | "kappa = 10 / 11" 2489 | ] 2490 | }, 2491 | { 2492 | "cell_type": "code", 2493 | "execution_count": 24, 2494 | "metadata": {}, 2495 | "outputs": [], 2496 | "source": [ 2497 | "def U(c):\n", 2498 | " return -(math.log(c[0]) + kappa * math.log(c[1]))" 2499 | ] 2500 | }, 2501 | { 2502 | "cell_type": "code", 2503 | "execution_count": 25, 2504 | "metadata": {}, 2505 | "outputs": [], 2506 | "source": [ 2507 | "w = 10" 2508 | ] 2509 | }, 2510 | { 2511 | "cell_type": "code", 2512 | "execution_count": 26, 2513 | "metadata": {}, 2514 | "outputs": [], 2515 | "source": [ 2516 | "cons = ({'type': 'eq', 'fun': lambda c: c[0] + c[1] - w})" 2517 | ] 2518 | }, 2519 | { 2520 | "cell_type": "code", 2521 | "execution_count": 27, 2522 | "metadata": {}, 2523 | "outputs": [], 2524 | "source": [ 2525 | "opt = minimize(U, (1, 1), constraints=cons)" 2526 | ] 2527 | }, 2528 | { 2529 | "cell_type": "code", 2530 | "execution_count": 28, 2531 | "metadata": {}, 2532 | "outputs": [ 2533 | { 2534 | "data": { 2535 | "text/plain": [ 2536 | " fun: -3.0747286083026886\n", 2537 | " jac: array([-0.19091, -0.19091])\n", 2538 | " message: 'Optimization terminated successfully'\n", 2539 | " nfev: 18\n", 2540 | " nit: 6\n", 2541 | " njev: 6\n", 2542 | " status: 0\n", 2543 | " success: True\n", 2544 | " x: array([5.23811, 4.76189])" 2545 | ] 2546 | }, 2547 | "execution_count": 28, 2548 | "metadata": {}, 2549 | "output_type": "execute_result" 2550 | } 2551 | ], 2552 | "source": [ 2553 | "opt" 2554 | ] 2555 | }, 2556 | { 2557 | "cell_type": "code", 2558 | "execution_count": 29, 2559 | "metadata": {}, 2560 | "outputs": [ 2561 | { 2562 | "data": { 2563 | "text/plain": [ 2564 | "array([5.23811, 4.76189])" 2565 | ] 2566 | }, 2567 | "execution_count": 29, 2568 | "metadata": {}, 2569 | "output_type": "execute_result" 2570 | } 2571 | ], 2572 | "source": [ 2573 | "opt['x']" 2574 | ] 2575 | }, 2576 | { 2577 | "cell_type": "code", 2578 | "execution_count": 30, 2579 | "metadata": {}, 2580 | "outputs": [ 2581 | { 2582 | "data": { 2583 | "text/plain": [ 2584 | "3.0747286083026886" 2585 | ] 2586 | }, 2587 | "execution_count": 30, 2588 | "metadata": {}, 2589 | "output_type": "execute_result" 2590 | } 2591 | ], 2592 | "source": [ 2593 | "-opt['fun']" 2594 | ] 2595 | }, 2596 | { 2597 | "cell_type": "markdown", 2598 | "metadata": {}, 2599 | "source": [ 2600 | "## Optimal Investment Portfolio" 2601 | ] 2602 | }, 2603 | { 2604 | "cell_type": "code", 2605 | "execution_count": 31, 2606 | "metadata": {}, 2607 | "outputs": [], 2608 | "source": [ 2609 | "B = (10, (11, 11))" 2610 | ] 2611 | }, 2612 | { 2613 | "cell_type": "code", 2614 | "execution_count": 32, 2615 | "metadata": {}, 2616 | "outputs": [], 2617 | "source": [ 2618 | "S = (10, (20, 5))" 2619 | ] 2620 | }, 2621 | { 2622 | "cell_type": "code", 2623 | "execution_count": 33, 2624 | "metadata": {}, 2625 | "outputs": [], 2626 | "source": [ 2627 | "M0 = np.array((B[0], S[0]))" 2628 | ] 2629 | }, 2630 | { 2631 | "cell_type": "code", 2632 | "execution_count": 34, 2633 | "metadata": {}, 2634 | "outputs": [], 2635 | "source": [ 2636 | "M = np.array((B[1], S[1])).T" 2637 | ] 2638 | }, 2639 | { 2640 | "cell_type": "code", 2641 | "execution_count": 35, 2642 | "metadata": {}, 2643 | "outputs": [], 2644 | "source": [ 2645 | "p = 0.5" 2646 | ] 2647 | }, 2648 | { 2649 | "cell_type": "code", 2650 | "execution_count": 36, 2651 | "metadata": {}, 2652 | "outputs": [], 2653 | "source": [ 2654 | "P = np.array((p, 1-p))" 2655 | ] 2656 | }, 2657 | { 2658 | "cell_type": "code", 2659 | "execution_count": 37, 2660 | "metadata": {}, 2661 | "outputs": [], 2662 | "source": [ 2663 | "def U(phi):\n", 2664 | " c1 = np.dot(M, phi)\n", 2665 | " return -np.dot(P, np.log(c1))" 2666 | ] 2667 | }, 2668 | { 2669 | "cell_type": "code", 2670 | "execution_count": 38, 2671 | "metadata": {}, 2672 | "outputs": [ 2673 | { 2674 | "data": { 2675 | "text/plain": [ 2676 | "2.3978952727983707" 2677 | ] 2678 | }, 2679 | "execution_count": 38, 2680 | "metadata": {}, 2681 | "output_type": "execute_result" 2682 | } 2683 | ], 2684 | "source": [ 2685 | "-U((1, 0))" 2686 | ] 2687 | }, 2688 | { 2689 | "cell_type": "code", 2690 | "execution_count": 39, 2691 | "metadata": {}, 2692 | "outputs": [ 2693 | { 2694 | "data": { 2695 | "text/plain": [ 2696 | "2.3025850929940455" 2697 | ] 2698 | }, 2699 | "execution_count": 39, 2700 | "metadata": {}, 2701 | "output_type": "execute_result" 2702 | } 2703 | ], 2704 | "source": [ 2705 | "-U((0, 1))" 2706 | ] 2707 | }, 2708 | { 2709 | "cell_type": "code", 2710 | "execution_count": 40, 2711 | "metadata": {}, 2712 | "outputs": [ 2713 | { 2714 | "data": { 2715 | "text/plain": [ 2716 | "2.410140782802518" 2717 | ] 2718 | }, 2719 | "execution_count": 40, 2720 | "metadata": {}, 2721 | "output_type": "execute_result" 2722 | } 2723 | ], 2724 | "source": [ 2725 | "-U((0.5, 0.5))" 2726 | ] 2727 | }, 2728 | { 2729 | "cell_type": "code", 2730 | "execution_count": 41, 2731 | "metadata": {}, 2732 | "outputs": [], 2733 | "source": [ 2734 | "w = 10" 2735 | ] 2736 | }, 2737 | { 2738 | "cell_type": "code", 2739 | "execution_count": 42, 2740 | "metadata": {}, 2741 | "outputs": [], 2742 | "source": [ 2743 | "cons = ({'type': 'eq',\n", 2744 | " 'fun': lambda phi: np.dot(M0, phi) - w})" 2745 | ] 2746 | }, 2747 | { 2748 | "cell_type": "code", 2749 | "execution_count": 43, 2750 | "metadata": {}, 2751 | "outputs": [], 2752 | "source": [ 2753 | "opt = minimize(U, (1, 1), constraints=cons)" 2754 | ] 2755 | }, 2756 | { 2757 | "cell_type": "code", 2758 | "execution_count": 44, 2759 | "metadata": {}, 2760 | "outputs": [ 2761 | { 2762 | "data": { 2763 | "text/plain": [ 2764 | " fun: -2.4183062699261972\n", 2765 | " jac: array([-1. , -0.99999])\n", 2766 | " message: 'Optimization terminated successfully'\n", 2767 | " nfev: 15\n", 2768 | " nit: 5\n", 2769 | " njev: 5\n", 2770 | " status: 0\n", 2771 | " success: True\n", 2772 | " x: array([0.69442, 0.30558])" 2773 | ] 2774 | }, 2775 | "execution_count": 44, 2776 | "metadata": {}, 2777 | "output_type": "execute_result" 2778 | } 2779 | ], 2780 | "source": [ 2781 | "opt" 2782 | ] 2783 | }, 2784 | { 2785 | "cell_type": "code", 2786 | "execution_count": 45, 2787 | "metadata": {}, 2788 | "outputs": [ 2789 | { 2790 | "data": { 2791 | "text/plain": [ 2792 | "array([0.69442, 0.30558])" 2793 | ] 2794 | }, 2795 | "execution_count": 45, 2796 | "metadata": {}, 2797 | "output_type": "execute_result" 2798 | } 2799 | ], 2800 | "source": [ 2801 | "opt['x']" 2802 | ] 2803 | }, 2804 | { 2805 | "cell_type": "code", 2806 | "execution_count": 46, 2807 | "metadata": {}, 2808 | "outputs": [ 2809 | { 2810 | "data": { 2811 | "text/plain": [ 2812 | "2.4183062699261972" 2813 | ] 2814 | }, 2815 | "execution_count": 46, 2816 | "metadata": {}, 2817 | "output_type": "execute_result" 2818 | } 2819 | ], 2820 | "source": [ 2821 | "-opt['fun']" 2822 | ] 2823 | }, 2824 | { 2825 | "cell_type": "code", 2826 | "execution_count": 47, 2827 | "metadata": {}, 2828 | "outputs": [ 2829 | { 2830 | "data": { 2831 | "text/plain": [ 2832 | "2.4183062699261972" 2833 | ] 2834 | }, 2835 | "execution_count": 47, 2836 | "metadata": {}, 2837 | "output_type": "execute_result" 2838 | } 2839 | ], 2840 | "source": [ 2841 | "-U(opt['x'])" 2842 | ] 2843 | }, 2844 | { 2845 | "cell_type": "code", 2846 | "execution_count": 48, 2847 | "metadata": {}, 2848 | "outputs": [ 2849 | { 2850 | "data": { 2851 | "text/plain": [ 2852 | "array([13.75022, 9.16652])" 2853 | ] 2854 | }, 2855 | "execution_count": 48, 2856 | "metadata": {}, 2857 | "output_type": "execute_result" 2858 | } 2859 | ], 2860 | "source": [ 2861 | "np.dot(M, opt['x'])" 2862 | ] 2863 | }, 2864 | { 2865 | "cell_type": "markdown", 2866 | "metadata": {}, 2867 | "source": [ 2868 | "## Time-Additive Expected Utility" 2869 | ] 2870 | }, 2871 | { 2872 | "cell_type": "code", 2873 | "execution_count": 49, 2874 | "metadata": {}, 2875 | "outputs": [], 2876 | "source": [ 2877 | "M0 = np.array((1, B[0], S[0]))" 2878 | ] 2879 | }, 2880 | { 2881 | "cell_type": "code", 2882 | "execution_count": 50, 2883 | "metadata": {}, 2884 | "outputs": [], 2885 | "source": [ 2886 | "kappa = 10 / 11" 2887 | ] 2888 | }, 2889 | { 2890 | "cell_type": "code", 2891 | "execution_count": 51, 2892 | "metadata": {}, 2893 | "outputs": [], 2894 | "source": [ 2895 | "def U(phi):\n", 2896 | " c0 = phi[0]\n", 2897 | " c1 = np.dot(M, phi[1:])\n", 2898 | " return -(np.log(c0) + kappa * np.dot(P, np.log(c1)))" 2899 | ] 2900 | }, 2901 | { 2902 | "cell_type": "code", 2903 | "execution_count": 52, 2904 | "metadata": {}, 2905 | "outputs": [], 2906 | "source": [ 2907 | "opt = minimize(U, (1, 1, 1), constraints=cons)" 2908 | ] 2909 | }, 2910 | { 2911 | "cell_type": "code", 2912 | "execution_count": 53, 2913 | "metadata": {}, 2914 | "outputs": [ 2915 | { 2916 | "data": { 2917 | "text/plain": [ 2918 | " fun: -3.1799295980286093\n", 2919 | " jac: array([-0.19088, -1.90932, -1.90974])\n", 2920 | " message: 'Optimization terminated successfully'\n", 2921 | " nfev: 32\n", 2922 | " nit: 8\n", 2923 | " njev: 8\n", 2924 | " status: 0\n", 2925 | " success: True\n", 2926 | " x: array([5.23899, 0.33087, 0.14523])" 2927 | ] 2928 | }, 2929 | "execution_count": 53, 2930 | "metadata": {}, 2931 | "output_type": "execute_result" 2932 | } 2933 | ], 2934 | "source": [ 2935 | "opt" 2936 | ] 2937 | }, 2938 | { 2939 | "cell_type": "code", 2940 | "execution_count": 54, 2941 | "metadata": {}, 2942 | "outputs": [ 2943 | { 2944 | "data": { 2945 | "text/plain": [ 2946 | "3.1799295980286093" 2947 | ] 2948 | }, 2949 | "execution_count": 54, 2950 | "metadata": {}, 2951 | "output_type": "execute_result" 2952 | } 2953 | ], 2954 | "source": [ 2955 | "-opt['fun']" 2956 | ] 2957 | }, 2958 | { 2959 | "cell_type": "code", 2960 | "execution_count": 55, 2961 | "metadata": {}, 2962 | "outputs": [ 2963 | { 2964 | "data": { 2965 | "text/plain": [ 2966 | "5.23898714830318" 2967 | ] 2968 | }, 2969 | "execution_count": 55, 2970 | "metadata": {}, 2971 | "output_type": "execute_result" 2972 | } 2973 | ], 2974 | "source": [ 2975 | "opt['x'][0]" 2976 | ] 2977 | }, 2978 | { 2979 | "cell_type": "code", 2980 | "execution_count": 56, 2981 | "metadata": {}, 2982 | "outputs": [ 2983 | { 2984 | "data": { 2985 | "text/plain": [ 2986 | "array([6.54422, 4.36571])" 2987 | ] 2988 | }, 2989 | "execution_count": 56, 2990 | "metadata": {}, 2991 | "output_type": "execute_result" 2992 | } 2993 | ], 2994 | "source": [ 2995 | "np.dot(M, opt['x'][1:])" 2996 | ] 2997 | }, 2998 | { 2999 | "cell_type": "markdown", 3000 | "metadata": {}, 3001 | "source": [ 3002 | "## A Numerical Example I" 3003 | ] 3004 | }, 3005 | { 3006 | "cell_type": "code", 3007 | "execution_count": 57, 3008 | "metadata": {}, 3009 | "outputs": [], 3010 | "source": [ 3011 | "p = 1 / 3" 3012 | ] 3013 | }, 3014 | { 3015 | "cell_type": "code", 3016 | "execution_count": 58, 3017 | "metadata": {}, 3018 | "outputs": [], 3019 | "source": [ 3020 | "P = np.array((p, (1-p)))" 3021 | ] 3022 | }, 3023 | { 3024 | "cell_type": "code", 3025 | "execution_count": 59, 3026 | "metadata": {}, 3027 | "outputs": [], 3028 | "source": [ 3029 | "B1 = np.array((11, 11))" 3030 | ] 3031 | }, 3032 | { 3033 | "cell_type": "code", 3034 | "execution_count": 60, 3035 | "metadata": {}, 3036 | "outputs": [], 3037 | "source": [ 3038 | "S1 = np.array((20, 5))" 3039 | ] 3040 | }, 3041 | { 3042 | "cell_type": "code", 3043 | "execution_count": 61, 3044 | "metadata": {}, 3045 | "outputs": [], 3046 | "source": [ 3047 | "zeta = np.dot(S1 / (B1 + S1), P) / np.dot(B1 / (B1 + S1), P)" 3048 | ] 3049 | }, 3050 | { 3051 | "cell_type": "code", 3052 | "execution_count": 62, 3053 | "metadata": {}, 3054 | "outputs": [ 3055 | { 3056 | "data": { 3057 | "text/plain": [ 3058 | "0.7342657342657343" 3059 | ] 3060 | }, 3061 | "execution_count": 62, 3062 | "metadata": {}, 3063 | "output_type": "execute_result" 3064 | } 3065 | ], 3066 | "source": [ 3067 | "zeta" 3068 | ] 3069 | }, 3070 | { 3071 | "cell_type": "code", 3072 | "execution_count": 63, 3073 | "metadata": {}, 3074 | "outputs": [], 3075 | "source": [ 3076 | "w = 15" 3077 | ] 3078 | }, 3079 | { 3080 | "cell_type": "code", 3081 | "execution_count": 64, 3082 | "metadata": {}, 3083 | "outputs": [], 3084 | "source": [ 3085 | "B0 = w / (1 + zeta)" 3086 | ] 3087 | }, 3088 | { 3089 | "cell_type": "code", 3090 | "execution_count": 65, 3091 | "metadata": {}, 3092 | "outputs": [ 3093 | { 3094 | "data": { 3095 | "text/plain": [ 3096 | "8.649193548387098" 3097 | ] 3098 | }, 3099 | "execution_count": 65, 3100 | "metadata": {}, 3101 | "output_type": "execute_result" 3102 | } 3103 | ], 3104 | "source": [ 3105 | "B0" 3106 | ] 3107 | }, 3108 | { 3109 | "cell_type": "code", 3110 | "execution_count": 66, 3111 | "metadata": {}, 3112 | "outputs": [], 3113 | "source": [ 3114 | "S0 = zeta * B0" 3115 | ] 3116 | }, 3117 | { 3118 | "cell_type": "code", 3119 | "execution_count": 67, 3120 | "metadata": {}, 3121 | "outputs": [ 3122 | { 3123 | "data": { 3124 | "text/plain": [ 3125 | "6.350806451612904" 3126 | ] 3127 | }, 3128 | "execution_count": 67, 3129 | "metadata": {}, 3130 | "output_type": "execute_result" 3131 | } 3132 | ], 3133 | "source": [ 3134 | "S0" 3135 | ] 3136 | }, 3137 | { 3138 | "cell_type": "code", 3139 | "execution_count": 68, 3140 | "metadata": {}, 3141 | "outputs": [ 3142 | { 3143 | "data": { 3144 | "text/plain": [ 3145 | "15.000000000000002" 3146 | ] 3147 | }, 3148 | "execution_count": 68, 3149 | "metadata": {}, 3150 | "output_type": "execute_result" 3151 | } 3152 | ], 3153 | "source": [ 3154 | "B0 + S0" 3155 | ] 3156 | }, 3157 | { 3158 | "cell_type": "code", 3159 | "execution_count": 69, 3160 | "metadata": {}, 3161 | "outputs": [], 3162 | "source": [ 3163 | "i = B1.mean() / B0 - 1" 3164 | ] 3165 | }, 3166 | { 3167 | "cell_type": "code", 3168 | "execution_count": 70, 3169 | "metadata": {}, 3170 | "outputs": [ 3171 | { 3172 | "data": { 3173 | "text/plain": [ 3174 | "0.2717948717948717" 3175 | ] 3176 | }, 3177 | "execution_count": 70, 3178 | "metadata": {}, 3179 | "output_type": "execute_result" 3180 | } 3181 | ], 3182 | "source": [ 3183 | "i" 3184 | ] 3185 | }, 3186 | { 3187 | "cell_type": "code", 3188 | "execution_count": 71, 3189 | "metadata": {}, 3190 | "outputs": [], 3191 | "source": [ 3192 | "mu = np.dot(S1, P) / S0 - 1" 3193 | ] 3194 | }, 3195 | { 3196 | "cell_type": "code", 3197 | "execution_count": 72, 3198 | "metadata": {}, 3199 | "outputs": [ 3200 | { 3201 | "data": { 3202 | "text/plain": [ 3203 | "0.5746031746031743" 3204 | ] 3205 | }, 3206 | "execution_count": 72, 3207 | "metadata": {}, 3208 | "output_type": "execute_result" 3209 | } 3210 | ], 3211 | "source": [ 3212 | "mu" 3213 | ] 3214 | }, 3215 | { 3216 | "cell_type": "code", 3217 | "execution_count": 73, 3218 | "metadata": {}, 3219 | "outputs": [], 3220 | "source": [ 3221 | "import sympy as sy" 3222 | ] 3223 | }, 3224 | { 3225 | "cell_type": "code", 3226 | "execution_count": 74, 3227 | "metadata": {}, 3228 | "outputs": [], 3229 | "source": [ 3230 | "q = sy.Symbol('q')" 3231 | ] 3232 | }, 3233 | { 3234 | "cell_type": "code", 3235 | "execution_count": 75, 3236 | "metadata": {}, 3237 | "outputs": [], 3238 | "source": [ 3239 | "eq = (q * 20 + (1 - q) * 5) / (1 + i) - S0" 3240 | ] 3241 | }, 3242 | { 3243 | "cell_type": "code", 3244 | "execution_count": 76, 3245 | "metadata": {}, 3246 | "outputs": [ 3247 | { 3248 | "data": { 3249 | "text/latex": [ 3250 | "$\\displaystyle 11.7943548387097 q - 2.41935483870968$" 3251 | ], 3252 | "text/plain": [ 3253 | "11.7943548387097*q - 2.41935483870968" 3254 | ] 3255 | }, 3256 | "execution_count": 76, 3257 | "metadata": {}, 3258 | "output_type": "execute_result" 3259 | } 3260 | ], 3261 | "source": [ 3262 | "eq" 3263 | ] 3264 | }, 3265 | { 3266 | "cell_type": "code", 3267 | "execution_count": 77, 3268 | "metadata": {}, 3269 | "outputs": [], 3270 | "source": [ 3271 | "q = sy.solve(eq)[0]" 3272 | ] 3273 | }, 3274 | { 3275 | "cell_type": "code", 3276 | "execution_count": 78, 3277 | "metadata": {}, 3278 | "outputs": [ 3279 | { 3280 | "data": { 3281 | "text/latex": [ 3282 | "$\\displaystyle 0.205128205128205$" 3283 | ], 3284 | "text/plain": [ 3285 | "0.205128205128205" 3286 | ] 3287 | }, 3288 | "execution_count": 78, 3289 | "metadata": {}, 3290 | "output_type": "execute_result" 3291 | } 3292 | ], 3293 | "source": [ 3294 | "q" 3295 | ] 3296 | }, 3297 | { 3298 | "cell_type": "code", 3299 | "execution_count": 79, 3300 | "metadata": {}, 3301 | "outputs": [], 3302 | "source": [ 3303 | "Q = np.array((q, 1-q))" 3304 | ] 3305 | }, 3306 | { 3307 | "cell_type": "code", 3308 | "execution_count": 80, 3309 | "metadata": {}, 3310 | "outputs": [ 3311 | { 3312 | "data": { 3313 | "text/latex": [ 3314 | "$\\displaystyle 8.6491935483871$" 3315 | ], 3316 | "text/plain": [ 3317 | "8.64919354838710" 3318 | ] 3319 | }, 3320 | "execution_count": 80, 3321 | "metadata": {}, 3322 | "output_type": "execute_result" 3323 | } 3324 | ], 3325 | "source": [ 3326 | "np.dot(B1, Q) / (1 + i)" 3327 | ] 3328 | }, 3329 | { 3330 | "cell_type": "code", 3331 | "execution_count": 81, 3332 | "metadata": {}, 3333 | "outputs": [ 3334 | { 3335 | "data": { 3336 | "text/latex": [ 3337 | "$\\displaystyle 6.3508064516129$" 3338 | ], 3339 | "text/plain": [ 3340 | "6.35080645161290" 3341 | ] 3342 | }, 3343 | "execution_count": 81, 3344 | "metadata": {}, 3345 | "output_type": "execute_result" 3346 | } 3347 | ], 3348 | "source": [ 3349 | "np.dot(S1, Q) / (1 + i)" 3350 | ] 3351 | }, 3352 | { 3353 | "cell_type": "markdown", 3354 | "metadata": {}, 3355 | "source": [ 3356 | "## Pricing in Incomplete Markets" 3357 | ] 3358 | }, 3359 | { 3360 | "cell_type": "code", 3361 | "execution_count": 82, 3362 | "metadata": {}, 3363 | "outputs": [], 3364 | "source": [ 3365 | "p = 1 / 3" 3366 | ] 3367 | }, 3368 | { 3369 | "cell_type": "code", 3370 | "execution_count": 83, 3371 | "metadata": {}, 3372 | "outputs": [], 3373 | "source": [ 3374 | "P = np.array((p, p, p))" 3375 | ] 3376 | }, 3377 | { 3378 | "cell_type": "code", 3379 | "execution_count": 84, 3380 | "metadata": {}, 3381 | "outputs": [], 3382 | "source": [ 3383 | "B1 = np.array((11, 11, 11))" 3384 | ] 3385 | }, 3386 | { 3387 | "cell_type": "code", 3388 | "execution_count": 85, 3389 | "metadata": {}, 3390 | "outputs": [], 3391 | "source": [ 3392 | "S1 = np.array((20, 10, 5))" 3393 | ] 3394 | }, 3395 | { 3396 | "cell_type": "code", 3397 | "execution_count": 86, 3398 | "metadata": {}, 3399 | "outputs": [], 3400 | "source": [ 3401 | "zeta = np.dot(S1 / (B1 + S1), P) / np.dot(B1 / (B1 + S1), P)" 3402 | ] 3403 | }, 3404 | { 3405 | "cell_type": "code", 3406 | "execution_count": 87, 3407 | "metadata": {}, 3408 | "outputs": [ 3409 | { 3410 | "data": { 3411 | "text/plain": [ 3412 | "0.9155274934101636" 3413 | ] 3414 | }, 3415 | "execution_count": 87, 3416 | "metadata": {}, 3417 | "output_type": "execute_result" 3418 | } 3419 | ], 3420 | "source": [ 3421 | "zeta" 3422 | ] 3423 | }, 3424 | { 3425 | "cell_type": "code", 3426 | "execution_count": 88, 3427 | "metadata": {}, 3428 | "outputs": [], 3429 | "source": [ 3430 | "w = 15" 3431 | ] 3432 | }, 3433 | { 3434 | "cell_type": "code", 3435 | "execution_count": 89, 3436 | "metadata": {}, 3437 | "outputs": [], 3438 | "source": [ 3439 | "B0 = w / (1 + zeta)" 3440 | ] 3441 | }, 3442 | { 3443 | "cell_type": "code", 3444 | "execution_count": 90, 3445 | "metadata": {}, 3446 | "outputs": [ 3447 | { 3448 | "data": { 3449 | "text/plain": [ 3450 | "7.8307411674347165" 3451 | ] 3452 | }, 3453 | "execution_count": 90, 3454 | "metadata": {}, 3455 | "output_type": "execute_result" 3456 | } 3457 | ], 3458 | "source": [ 3459 | "B0" 3460 | ] 3461 | }, 3462 | { 3463 | "cell_type": "code", 3464 | "execution_count": 91, 3465 | "metadata": {}, 3466 | "outputs": [], 3467 | "source": [ 3468 | "S0 = zeta * B0" 3469 | ] 3470 | }, 3471 | { 3472 | "cell_type": "code", 3473 | "execution_count": 92, 3474 | "metadata": {}, 3475 | "outputs": [ 3476 | { 3477 | "data": { 3478 | "text/plain": [ 3479 | "7.169258832565284" 3480 | ] 3481 | }, 3482 | "execution_count": 92, 3483 | "metadata": {}, 3484 | "output_type": "execute_result" 3485 | } 3486 | ], 3487 | "source": [ 3488 | "S0" 3489 | ] 3490 | }, 3491 | { 3492 | "cell_type": "code", 3493 | "execution_count": 93, 3494 | "metadata": {}, 3495 | "outputs": [ 3496 | { 3497 | "data": { 3498 | "text/plain": [ 3499 | "15.0" 3500 | ] 3501 | }, 3502 | "execution_count": 93, 3503 | "metadata": {}, 3504 | "output_type": "execute_result" 3505 | } 3506 | ], 3507 | "source": [ 3508 | "B0 + S0" 3509 | ] 3510 | }, 3511 | { 3512 | "cell_type": "code", 3513 | "execution_count": 94, 3514 | "metadata": {}, 3515 | "outputs": [], 3516 | "source": [ 3517 | "i = B1.mean() / B0 - 1" 3518 | ] 3519 | }, 3520 | { 3521 | "cell_type": "code", 3522 | "execution_count": 95, 3523 | "metadata": {}, 3524 | "outputs": [ 3525 | { 3526 | "data": { 3527 | "text/plain": [ 3528 | "0.40472016183411985" 3529 | ] 3530 | }, 3531 | "execution_count": 95, 3532 | "metadata": {}, 3533 | "output_type": "execute_result" 3534 | } 3535 | ], 3536 | "source": [ 3537 | "i" 3538 | ] 3539 | }, 3540 | { 3541 | "cell_type": "code", 3542 | "execution_count": 96, 3543 | "metadata": {}, 3544 | "outputs": [], 3545 | "source": [ 3546 | "mu = np.dot(S1, P) / S0 - 1" 3547 | ] 3548 | }, 3549 | { 3550 | "cell_type": "code", 3551 | "execution_count": 97, 3552 | "metadata": {}, 3553 | "outputs": [ 3554 | { 3555 | "data": { 3556 | "text/plain": [ 3557 | "0.6273183796451287" 3558 | ] 3559 | }, 3560 | "execution_count": 97, 3561 | "metadata": {}, 3562 | "output_type": "execute_result" 3563 | } 3564 | ], 3565 | "source": [ 3566 | "mu" 3567 | ] 3568 | }, 3569 | { 3570 | "cell_type": "markdown", 3571 | "metadata": {}, 3572 | "source": [ 3573 | "## Martingale Measures in Incomplete Markets" 3574 | ] 3575 | }, 3576 | { 3577 | "cell_type": "code", 3578 | "execution_count": 98, 3579 | "metadata": {}, 3580 | "outputs": [], 3581 | "source": [ 3582 | "qu = sy.Symbol('qu')\n", 3583 | "qm = sy.Symbol('qm')" 3584 | ] 3585 | }, 3586 | { 3587 | "cell_type": "code", 3588 | "execution_count": 99, 3589 | "metadata": {}, 3590 | "outputs": [], 3591 | "source": [ 3592 | "eq = (qu * 20 + qm * 10 + (1 - qu - qm) * 5) / (1 + i) - S0" 3593 | ] 3594 | }, 3595 | { 3596 | "cell_type": "code", 3597 | "execution_count": 100, 3598 | "metadata": {}, 3599 | "outputs": [ 3600 | { 3601 | "data": { 3602 | "text/latex": [ 3603 | "$\\displaystyle 3.55942780337942 qm + 10.6782834101383 qu - 3.60983102918587$" 3604 | ], 3605 | "text/plain": [ 3606 | "3.55942780337942*qm + 10.6782834101383*qu - 3.60983102918587" 3607 | ] 3608 | }, 3609 | "execution_count": 100, 3610 | "metadata": {}, 3611 | "output_type": "execute_result" 3612 | } 3613 | ], 3614 | "source": [ 3615 | "eq" 3616 | ] 3617 | }, 3618 | { 3619 | "cell_type": "code", 3620 | "execution_count": 101, 3621 | "metadata": {}, 3622 | "outputs": [], 3623 | "source": [ 3624 | "Q = sy.solve(eq, set=True)" 3625 | ] 3626 | }, 3627 | { 3628 | "cell_type": "code", 3629 | "execution_count": 102, 3630 | "metadata": {}, 3631 | "outputs": [ 3632 | { 3633 | "data": { 3634 | "text/plain": [ 3635 | "([qm], {(1.01416048550236 - 3.00000000000001*qu,)})" 3636 | ] 3637 | }, 3638 | "execution_count": 102, 3639 | "metadata": {}, 3640 | "output_type": "execute_result" 3641 | } 3642 | ], 3643 | "source": [ 3644 | "Q" 3645 | ] 3646 | }, 3647 | { 3648 | "cell_type": "markdown", 3649 | "metadata": {}, 3650 | "source": [ 3651 | "## A Numerical Example II" 3652 | ] 3653 | }, 3654 | { 3655 | "cell_type": "code", 3656 | "execution_count": 103, 3657 | "metadata": {}, 3658 | "outputs": [], 3659 | "source": [ 3660 | "p = 1 / 3" 3661 | ] 3662 | }, 3663 | { 3664 | "cell_type": "code", 3665 | "execution_count": 104, 3666 | "metadata": {}, 3667 | "outputs": [], 3668 | "source": [ 3669 | "P = np.array((p, p, p))" 3670 | ] 3671 | }, 3672 | { 3673 | "cell_type": "code", 3674 | "execution_count": 105, 3675 | "metadata": {}, 3676 | "outputs": [], 3677 | "source": [ 3678 | "B1 = np.array((11, 11, 11))" 3679 | ] 3680 | }, 3681 | { 3682 | "cell_type": "code", 3683 | "execution_count": 106, 3684 | "metadata": {}, 3685 | "outputs": [], 3686 | "source": [ 3687 | "S1 = np.array((20, 10, 5))" 3688 | ] 3689 | }, 3690 | { 3691 | "cell_type": "code", 3692 | "execution_count": 107, 3693 | "metadata": {}, 3694 | "outputs": [], 3695 | "source": [ 3696 | "C1 = np.array((5, 0, 0))" 3697 | ] 3698 | }, 3699 | { 3700 | "cell_type": "code", 3701 | "execution_count": 108, 3702 | "metadata": {}, 3703 | "outputs": [], 3704 | "source": [ 3705 | "zeta_1 = (np.dot(S1 / (B1 + S1 + C1), P) /\n", 3706 | " np.dot(B1 / (B1 + S1 + C1), P))" 3707 | ] 3708 | }, 3709 | { 3710 | "cell_type": "code", 3711 | "execution_count": 109, 3712 | "metadata": {}, 3713 | "outputs": [ 3714 | { 3715 | "data": { 3716 | "text/plain": [ 3717 | "0.8862001308044474" 3718 | ] 3719 | }, 3720 | "execution_count": 109, 3721 | "metadata": {}, 3722 | "output_type": "execute_result" 3723 | } 3724 | ], 3725 | "source": [ 3726 | "zeta_1" 3727 | ] 3728 | }, 3729 | { 3730 | "cell_type": "code", 3731 | "execution_count": 110, 3732 | "metadata": {}, 3733 | "outputs": [], 3734 | "source": [ 3735 | "zeta_2 = (np.dot(C1 / (B1 + S1 + C1), P) /\n", 3736 | " np.dot(B1 / (B1 + S1 + C1), P))" 3737 | ] 3738 | }, 3739 | { 3740 | "cell_type": "code", 3741 | "execution_count": 111, 3742 | "metadata": {}, 3743 | "outputs": [ 3744 | { 3745 | "data": { 3746 | "text/plain": [ 3747 | "0.09156311314584695" 3748 | ] 3749 | }, 3750 | "execution_count": 111, 3751 | "metadata": {}, 3752 | "output_type": "execute_result" 3753 | } 3754 | ], 3755 | "source": [ 3756 | "zeta_2" 3757 | ] 3758 | }, 3759 | { 3760 | "cell_type": "code", 3761 | "execution_count": 112, 3762 | "metadata": {}, 3763 | "outputs": [], 3764 | "source": [ 3765 | "w = 15" 3766 | ] 3767 | }, 3768 | { 3769 | "cell_type": "code", 3770 | "execution_count": 113, 3771 | "metadata": {}, 3772 | "outputs": [], 3773 | "source": [ 3774 | "B0 = w / (1 + zeta_1 + zeta_2)" 3775 | ] 3776 | }, 3777 | { 3778 | "cell_type": "code", 3779 | "execution_count": 114, 3780 | "metadata": {}, 3781 | "outputs": [ 3782 | { 3783 | "data": { 3784 | "text/plain": [ 3785 | "7.584325396825396" 3786 | ] 3787 | }, 3788 | "execution_count": 114, 3789 | "metadata": {}, 3790 | "output_type": "execute_result" 3791 | } 3792 | ], 3793 | "source": [ 3794 | "B0" 3795 | ] 3796 | }, 3797 | { 3798 | "cell_type": "code", 3799 | "execution_count": 115, 3800 | "metadata": {}, 3801 | "outputs": [], 3802 | "source": [ 3803 | "S0 = zeta_1 * B0" 3804 | ] 3805 | }, 3806 | { 3807 | "cell_type": "code", 3808 | "execution_count": 116, 3809 | "metadata": {}, 3810 | "outputs": [ 3811 | { 3812 | "data": { 3813 | "text/plain": [ 3814 | "6.721230158730158" 3815 | ] 3816 | }, 3817 | "execution_count": 116, 3818 | "metadata": {}, 3819 | "output_type": "execute_result" 3820 | } 3821 | ], 3822 | "source": [ 3823 | "S0" 3824 | ] 3825 | }, 3826 | { 3827 | "cell_type": "code", 3828 | "execution_count": 117, 3829 | "metadata": {}, 3830 | "outputs": [], 3831 | "source": [ 3832 | "C0 = zeta_2 * B0" 3833 | ] 3834 | }, 3835 | { 3836 | "cell_type": "code", 3837 | "execution_count": 118, 3838 | "metadata": {}, 3839 | "outputs": [ 3840 | { 3841 | "data": { 3842 | "text/plain": [ 3843 | "0.6944444444444443" 3844 | ] 3845 | }, 3846 | "execution_count": 118, 3847 | "metadata": {}, 3848 | "output_type": "execute_result" 3849 | } 3850 | ], 3851 | "source": [ 3852 | "C0" 3853 | ] 3854 | }, 3855 | { 3856 | "cell_type": "code", 3857 | "execution_count": 119, 3858 | "metadata": {}, 3859 | "outputs": [ 3860 | { 3861 | "data": { 3862 | "text/plain": [ 3863 | "14.999999999999998" 3864 | ] 3865 | }, 3866 | "execution_count": 119, 3867 | "metadata": {}, 3868 | "output_type": "execute_result" 3869 | } 3870 | ], 3871 | "source": [ 3872 | "B0 + S0 + C0" 3873 | ] 3874 | }, 3875 | { 3876 | "cell_type": "code", 3877 | "execution_count": 120, 3878 | "metadata": {}, 3879 | "outputs": [], 3880 | "source": [ 3881 | "i = B1.mean() / B0 - 1" 3882 | ] 3883 | }, 3884 | { 3885 | "cell_type": "code", 3886 | "execution_count": 121, 3887 | "metadata": {}, 3888 | "outputs": [ 3889 | { 3890 | "data": { 3891 | "text/plain": [ 3892 | "0.45035971223021587" 3893 | ] 3894 | }, 3895 | "execution_count": 121, 3896 | "metadata": {}, 3897 | "output_type": "execute_result" 3898 | } 3899 | ], 3900 | "source": [ 3901 | "i" 3902 | ] 3903 | }, 3904 | { 3905 | "cell_type": "code", 3906 | "execution_count": 122, 3907 | "metadata": {}, 3908 | "outputs": [], 3909 | "source": [ 3910 | "muS = np.dot(S1, P) / S0 - 1" 3911 | ] 3912 | }, 3913 | { 3914 | "cell_type": "code", 3915 | "execution_count": 123, 3916 | "metadata": {}, 3917 | "outputs": [ 3918 | { 3919 | "data": { 3920 | "text/plain": [ 3921 | "0.7357933579335794" 3922 | ] 3923 | }, 3924 | "execution_count": 123, 3925 | "metadata": {}, 3926 | "output_type": "execute_result" 3927 | } 3928 | ], 3929 | "source": [ 3930 | "muS" 3931 | ] 3932 | }, 3933 | { 3934 | "cell_type": "code", 3935 | "execution_count": 124, 3936 | "metadata": {}, 3937 | "outputs": [], 3938 | "source": [ 3939 | "muC = np.dot(C1, P) / C0 - 1" 3940 | ] 3941 | }, 3942 | { 3943 | "cell_type": "code", 3944 | "execution_count": 125, 3945 | "metadata": {}, 3946 | "outputs": [ 3947 | { 3948 | "data": { 3949 | "text/plain": [ 3950 | "1.4000000000000004" 3951 | ] 3952 | }, 3953 | "execution_count": 125, 3954 | "metadata": {}, 3955 | "output_type": "execute_result" 3956 | } 3957 | ], 3958 | "source": [ 3959 | "muC" 3960 | ] 3961 | }, 3962 | { 3963 | "cell_type": "code", 3964 | "execution_count": 126, 3965 | "metadata": {}, 3966 | "outputs": [], 3967 | "source": [ 3968 | "M = np.array((B1, S1, C1)).T" 3969 | ] 3970 | }, 3971 | { 3972 | "cell_type": "code", 3973 | "execution_count": 127, 3974 | "metadata": {}, 3975 | "outputs": [ 3976 | { 3977 | "data": { 3978 | "text/plain": [ 3979 | "array([[11, 20, 5],\n", 3980 | " [11, 10, 0],\n", 3981 | " [11, 5, 0]])" 3982 | ] 3983 | }, 3984 | "execution_count": 127, 3985 | "metadata": {}, 3986 | "output_type": "execute_result" 3987 | } 3988 | ], 3989 | "source": [ 3990 | "M" 3991 | ] 3992 | }, 3993 | { 3994 | "cell_type": "code", 3995 | "execution_count": 128, 3996 | "metadata": {}, 3997 | "outputs": [], 3998 | "source": [ 3999 | "M0 = np.array((B0, S0, C0))" 4000 | ] 4001 | }, 4002 | { 4003 | "cell_type": "code", 4004 | "execution_count": 129, 4005 | "metadata": {}, 4006 | "outputs": [], 4007 | "source": [ 4008 | "Q = np.linalg.solve(M.T / (1 + i), M0)" 4009 | ] 4010 | }, 4011 | { 4012 | "cell_type": "code", 4013 | "execution_count": 130, 4014 | "metadata": {}, 4015 | "outputs": [ 4016 | { 4017 | "data": { 4018 | "text/plain": [ 4019 | "array([0.20144, 0.34532, 0.45324])" 4020 | ] 4021 | }, 4022 | "execution_count": 130, 4023 | "metadata": {}, 4024 | "output_type": "execute_result" 4025 | } 4026 | ], 4027 | "source": [ 4028 | "Q" 4029 | ] 4030 | }, 4031 | { 4032 | "cell_type": "code", 4033 | "execution_count": 131, 4034 | "metadata": {}, 4035 | "outputs": [ 4036 | { 4037 | "data": { 4038 | "text/plain": [ 4039 | "1.0" 4040 | ] 4041 | }, 4042 | "execution_count": 131, 4043 | "metadata": {}, 4044 | "output_type": "execute_result" 4045 | } 4046 | ], 4047 | "source": [ 4048 | "sum(Q)" 4049 | ] 4050 | }, 4051 | { 4052 | "cell_type": "code", 4053 | "execution_count": 132, 4054 | "metadata": {}, 4055 | "outputs": [ 4056 | { 4057 | "data": { 4058 | "text/plain": [ 4059 | "True" 4060 | ] 4061 | }, 4062 | "execution_count": 132, 4063 | "metadata": {}, 4064 | "output_type": "execute_result" 4065 | } 4066 | ], 4067 | "source": [ 4068 | "np.allclose(np.dot(M.T, Q), M0 * (1 + i))" 4069 | ] 4070 | }, 4071 | { 4072 | "cell_type": "markdown", 4073 | "metadata": {}, 4074 | "source": [ 4075 | "\"The
\n", 4076 | "\n", 4077 | "http://tpq.io | @dyjh | training@tpq.io" 4078 | ] 4079 | } 4080 | ], 4081 | "metadata": { 4082 | "anaconda-cloud": {}, 4083 | "kernelspec": { 4084 | "display_name": "Python 3 (ipykernel)", 4085 | "language": "python", 4086 | "name": "python3" 4087 | }, 4088 | "language_info": { 4089 | "codemirror_mode": { 4090 | "name": "ipython", 4091 | "version": 3 4092 | }, 4093 | "file_extension": ".py", 4094 | "mimetype": "text/x-python", 4095 | "name": "python", 4096 | "nbconvert_exporter": "python", 4097 | "pygments_lexer": "ipython3", 4098 | "version": "3.10.12" 4099 | } 4100 | }, 4101 | "nbformat": 4, 4102 | "nbformat_minor": 4 4103 | } 4104 | --------------------------------------------------------------------------------