ml-finance-python
python scripts for finance machine learning
git clone https://9o.is/git/ml-finance-python.git
lab_123.ipynb
(12205B)
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# Interactive Plotting and Monte Carlo Simulations of CPPI"
8 ]
9 },
10 {
11 "cell_type": "code",
12 "execution_count": 1,
13 "metadata": {},
14 "outputs": [],
15 "source": [
16 "import ipywidgets as widgets\n",
17 "from IPython.display import display\n",
18 "import pandas as pd\n",
19 "import edhec_risk_kit_123 as erk\n",
20 "\n",
21 "%load_ext autoreload\n",
22 "%autoreload 2"
23 ]
24 },
25 {
26 "cell_type": "markdown",
27 "metadata": {},
28 "source": [
29 "## GBM Simulations"
30 ]
31 },
32 {
33 "cell_type": "code",
34 "execution_count": 2,
35 "metadata": {},
36 "outputs": [],
37 "source": [
38 "def show_gbm(n_scenarios, mu, sigma):\n",
39 " \"\"\"\n",
40 " Draw the results of a stock price evolution under a Geometric Brownian Motion model\n",
41 " \"\"\"\n",
42 " s_0=100\n",
43 " prices = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, s_0=s_0)\n",
44 " ax = prices.plot(legend=False, color=\"indianred\", alpha = 0.5, linewidth=2, figsize=(12,5))\n",
45 " ax.axhline(y=100, ls=\":\", color=\"black\")\n",
46 " # draw a dot at the origin\n",
47 " ax.plot(0,s_0, marker='o',color='darkred', alpha=0.2)\n"
48 ]
49 },
50 {
51 "cell_type": "code",
52 "execution_count": 3,
53 "metadata": {},
54 "outputs": [],
55 "source": [
56 "gbm_controls = widgets.interactive(show_gbm, \n",
57 " n_scenarios=widgets.IntSlider(min=1, max=1000, step=1, value=1), \n",
58 " mu=(0., +.2,.01),\n",
59 " sigma=(0, .3, .01)\n",
60 ")"
61 ]
62 },
63 {
64 "cell_type": "code",
65 "execution_count": 4,
66 "metadata": {},
67 "outputs": [
68 {
69 "data": {
70 "application/vnd.jupyter.widget-view+json": {
71 "model_id": "b2cf050bcda641caa2b3ce79cc1b7bf1",
72 "version_major": 2,
73 "version_minor": 0
74 },
75 "text/plain": [
76 "interactive(children=(IntSlider(value=1, description='n_scenarios', max=1000, min=1), FloatSlider(value=0.1, d…"
77 ]
78 },
79 "metadata": {},
80 "output_type": "display_data"
81 }
82 ],
83 "source": [
84 "display(gbm_controls)"
85 ]
86 },
87 {
88 "cell_type": "markdown",
89 "metadata": {},
90 "source": [
91 "# Interactive CPPI Monte Carlo Testing"
92 ]
93 },
94 {
95 "cell_type": "code",
96 "execution_count": 5,
97 "metadata": {},
98 "outputs": [
99 {
100 "data": {
101 "application/vnd.jupyter.widget-view+json": {
102 "model_id": "f247e88c15cf4ac2bfc0bf670ac394ce",
103 "version_major": 2,
104 "version_minor": 0
105 },
106 "text/plain": [
107 "interactive(children=(IntSlider(value=50, description='n_scenarios', max=1000, min=1, step=5), FloatSlider(val…"
108 ]
109 },
110 "metadata": {},
111 "output_type": "display_data"
112 }
113 ],
114 "source": [
115 "def show_cppi(n_scenarios=50, mu=0.07, sigma=0.15, m=3, floor=0., riskfree_rate=0.03, y_max=100):\n",
116 " \"\"\"\n",
117 " Plot the results of a Monte Carlo Simulation of CPPI\n",
118 " \"\"\"\n",
119 " start = 100\n",
120 " sim_rets = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, prices=False, steps_per_year=12)\n",
121 " risky_r = pd.DataFrame(sim_rets)\n",
122 " # run the \"back\"-test\n",
123 " btr = erk.run_cppi(risky_r=pd.DataFrame(risky_r),riskfree_rate=riskfree_rate,m=m, start=start, floor=floor)\n",
124 " wealth = btr[\"Wealth\"]\n",
125 " y_max=wealth.values.max()*y_max/100\n",
126 " ax = wealth.plot(legend=False, alpha=0.3, color=\"indianred\", figsize=(12, 6))\n",
127 " ax.axhline(y=start, ls=\":\", color=\"black\")\n",
128 " ax.axhline(y=start*floor, ls=\"--\", color=\"red\")\n",
129 " ax.set_ylim(top=y_max)\n",
130 "\n",
131 "cppi_controls = widgets.interactive(show_cppi, \n",
132 " n_scenarios=widgets.IntSlider(min=1, max=1000, step=5, value=50), \n",
133 " mu=(0., +.2, .01),\n",
134 " sigma=(0, .30, .05),\n",
135 " floor=(0, 2, .1),\n",
136 " m=(1, 5, .5),\n",
137 " riskfree_rate=(0, .05, .01),\n",
138 " y_max=widgets.IntSlider(min=0, max=100, step=1, value=100,\n",
139 " description=\"Zoom Y Axis\")\n",
140 ")\n",
141 "display(cppi_controls)"
142 ]
143 },
144 {
145 "cell_type": "markdown",
146 "metadata": {},
147 "source": [
148 "# Adding a Histogram and Reporting Floor Violations"
149 ]
150 },
151 {
152 "cell_type": "code",
153 "execution_count": 6,
154 "metadata": {},
155 "outputs": [
156 {
157 "data": {
158 "application/vnd.jupyter.widget-view+json": {
159 "model_id": "db0278b4b2064464a17c08bf8ccdd2fa",
160 "version_major": 2,
161 "version_minor": 0
162 },
163 "text/plain": [
164 "interactive(children=(IntSlider(value=50, description='n_scenarios', max=1000, min=1, step=5), FloatSlider(val…"
165 ]
166 },
167 "metadata": {},
168 "output_type": "display_data"
169 }
170 ],
171 "source": [
172 "import matplotlib.pyplot as plt\n",
173 "\n",
174 "def show_cppi(n_scenarios=50, mu=0.07, sigma=0.15, m=3, floor=0., riskfree_rate=0.03, y_max=100):\n",
175 " \"\"\"\n",
176 " Plot the results of a Monte Carlo Simulation of CPPI\n",
177 " \"\"\"\n",
178 " start = 100\n",
179 " sim_rets = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, prices=False, steps_per_year=12)\n",
180 " risky_r = pd.DataFrame(sim_rets)\n",
181 " # run the \"back\"-test\n",
182 " btr = erk.run_cppi(risky_r=pd.DataFrame(risky_r),riskfree_rate=riskfree_rate,m=m, start=start, floor=floor)\n",
183 " wealth = btr[\"Wealth\"]\n",
184 " # calculate terminal wealth stats\n",
185 " y_max=wealth.values.max()*y_max/100\n",
186 " terminal_wealth = wealth.iloc[-1]\n",
187 " # Plot!\n",
188 " fig, (wealth_ax, hist_ax) = plt.subplots(nrows=1, ncols=2, sharey=True, gridspec_kw={'width_ratios':[3,2]}, figsize=(24, 9))\n",
189 " plt.subplots_adjust(wspace=0.0)\n",
190 " \n",
191 " wealth.plot(ax=wealth_ax, legend=False, alpha=0.3, color=\"indianred\")\n",
192 " wealth_ax.axhline(y=start, ls=\":\", color=\"black\")\n",
193 " wealth_ax.axhline(y=start*floor, ls=\"--\", color=\"red\")\n",
194 " wealth_ax.set_ylim(top=y_max)\n",
195 " \n",
196 " terminal_wealth.plot.hist(ax=hist_ax, bins=50, ec='w', fc='indianred', orientation='horizontal')\n",
197 " hist_ax.axhline(y=start, ls=\":\", color=\"black\")\n",
198 "\n",
199 "cppi_controls = widgets.interactive(show_cppi, \n",
200 " n_scenarios=widgets.IntSlider(min=1, max=1000, step=5, value=50), \n",
201 " mu=(0., +.2, .01),\n",
202 " sigma=(0, .3, .05),\n",
203 " floor=(0, 2, .1),\n",
204 " m=(1, 5, .5),\n",
205 " riskfree_rate=(0, .05, .01),\n",
206 " y_max=widgets.IntSlider(min=0, max=100, step=1, value=100,\n",
207 " description=\"Zoom Y Axis\")\n",
208 ")\n",
209 "display(cppi_controls)"
210 ]
211 },
212 {
213 "cell_type": "markdown",
214 "metadata": {},
215 "source": [
216 "# Adding Terminal Wealth Statistics"
217 ]
218 },
219 {
220 "cell_type": "code",
221 "execution_count": 7,
222 "metadata": {},
223 "outputs": [
224 {
225 "data": {
226 "application/vnd.jupyter.widget-view+json": {
227 "model_id": "86ad8169669145e88ac879e0c5736ffb",
228 "version_major": 2,
229 "version_minor": 0
230 },
231 "text/plain": [
232 "interactive(children=(IntSlider(value=50, description='n_scenarios', max=1000, min=1, step=5), FloatSlider(val…"
233 ]
234 },
235 "metadata": {},
236 "output_type": "display_data"
237 }
238 ],
239 "source": [
240 "import matplotlib.pyplot as plt\n",
241 "import numpy as np\n",
242 "\n",
243 "def show_cppi(n_scenarios=50, mu=0.07, sigma=0.15, m=3, floor=0., riskfree_rate=0.03, steps_per_year=12, y_max=100):\n",
244 " \"\"\"\n",
245 " Plot the results of a Monte Carlo Simulation of CPPI\n",
246 " \"\"\"\n",
247 " start = 100\n",
248 " sim_rets = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, prices=False, steps_per_year=steps_per_year)\n",
249 " risky_r = pd.DataFrame(sim_rets)\n",
250 " # run the \"back\"-test\n",
251 " btr = erk.run_cppi(risky_r=pd.DataFrame(risky_r),riskfree_rate=riskfree_rate,m=m, start=start, floor=floor)\n",
252 " wealth = btr[\"Wealth\"]\n",
253 "\n",
254 " # calculate terminal wealth stats\n",
255 " y_max=wealth.values.max()*y_max/100\n",
256 " terminal_wealth = wealth.iloc[-1]\n",
257 " \n",
258 " tw_mean = terminal_wealth.mean()\n",
259 " tw_median = terminal_wealth.median()\n",
260 " failure_mask = np.less(terminal_wealth, start*floor)\n",
261 " n_failures = failure_mask.sum()\n",
262 " p_fail = n_failures/n_scenarios\n",
263 "\n",
264 " e_shortfall = np.dot(terminal_wealth-start*floor, failure_mask)/n_failures if n_failures > 0 else 0.0\n",
265 "\n",
266 " # Plot!\n",
267 " fig, (wealth_ax, hist_ax) = plt.subplots(nrows=1, ncols=2, sharey=True, gridspec_kw={'width_ratios':[3,2]}, figsize=(24, 9))\n",
268 " plt.subplots_adjust(wspace=0.0)\n",
269 " \n",
270 " wealth.plot(ax=wealth_ax, legend=False, alpha=0.3, color=\"indianred\")\n",
271 " wealth_ax.axhline(y=start, ls=\":\", color=\"black\")\n",
272 " wealth_ax.axhline(y=start*floor, ls=\"--\", color=\"red\")\n",
273 " wealth_ax.set_ylim(top=y_max)\n",
274 " \n",
275 " terminal_wealth.plot.hist(ax=hist_ax, bins=50, ec='w', fc='indianred', orientation='horizontal')\n",
276 " hist_ax.axhline(y=start, ls=\":\", color=\"black\")\n",
277 " hist_ax.axhline(y=tw_mean, ls=\":\", color=\"blue\")\n",
278 " hist_ax.axhline(y=tw_median, ls=\":\", color=\"purple\")\n",
279 " hist_ax.annotate(f\"Mean: ${int(tw_mean)}\", xy=(.7, .9),xycoords='axes fraction', fontsize=24)\n",
280 " hist_ax.annotate(f\"Median: ${int(tw_median)}\", xy=(.7, .85),xycoords='axes fraction', fontsize=24)\n",
281 " if (floor > 0.01):\n",
282 " hist_ax.axhline(y=start*floor, ls=\"--\", color=\"red\", linewidth=3)\n",
283 " hist_ax.annotate(f\"Violations: {n_failures} ({p_fail*100:2.2f}%)\\nE(shortfall)=${e_shortfall:2.2f}\", xy=(.7, .7), xycoords='axes fraction', fontsize=24)\n",
284 "\n",
285 "cppi_controls = widgets.interactive(show_cppi,\n",
286 " n_scenarios=widgets.IntSlider(min=1, max=1000, step=5, value=50), \n",
287 " mu=(0., +.2, .01),\n",
288 " sigma=(0, .3, .05),\n",
289 " floor=(0, 2, .1),\n",
290 " m=(1, 5, .5),\n",
291 " riskfree_rate=(0, .05, .01),\n",
292 " steps_per_year=widgets.IntSlider(min=1, max=12, step=1, value=12,\n",
293 " description=\"Rebals/Year\"),\n",
294 " y_max=widgets.IntSlider(min=0, max=100, step=1, value=100,\n",
295 " description=\"Zoom Y Axis\")\n",
296 ")\n",
297 "display(cppi_controls)"
298 ]
299 },
300 {
301 "cell_type": "code",
302 "execution_count": null,
303 "metadata": {},
304 "outputs": [],
305 "source": []
306 },
307 {
308 "cell_type": "code",
309 "execution_count": null,
310 "metadata": {},
311 "outputs": [],
312 "source": []
313 }
314 ],
315 "metadata": {
316 "kernelspec": {
317 "display_name": "Python 3",
318 "language": "python",
319 "name": "python3"
320 },
321 "language_info": {
322 "codemirror_mode": {
323 "name": "ipython",
324 "version": 3
325 },
326 "file_extension": ".py",
327 "mimetype": "text/x-python",
328 "name": "python",
329 "nbconvert_exporter": "python",
330 "pygments_lexer": "ipython3",
331 "version": "3.8.8"
332 }
333 },
334 "nbformat": 4,
335 "nbformat_minor": 4
336 }