Skip to content

Commit 647f1a4

Browse files
committed
Fixes
1 parent 3b625f2 commit 647f1a4

File tree

1 file changed

+41
-25
lines changed

1 file changed

+41
-25
lines changed

lectures/monte_carlo.md

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ kernelspec:
1111
name: python3
1212
---
1313

14+
15+
1416
# Monte Carlo and Option Pricing
1517

1618
## Overview
@@ -46,7 +48,7 @@ import matplotlib.pyplot as plt
4648
from numpy.random import randn
4749
```
4850

49-
+++ {"user_expressions": []}
51+
5052

5153
## An Introduction to Monte Carlo
5254

@@ -150,7 +152,7 @@ p = 0.5
150152
σ_1, σ_2, σ_3 = 0.1, 0.05, 0.2
151153
```
152154

153-
+++ {"user_expressions": []}
155+
154156

155157
#### A Routine using Loops in Python
156158

@@ -174,6 +176,8 @@ for i in range(n):
174176
S / n
175177
```
176178

179+
180+
177181
We can also construct a function that contains these operations:
178182

179183
```{code-cell} ipython3
@@ -187,14 +191,16 @@ def compute_mean(n=1_000_000):
187191
return (S / n)
188192
```
189193

190-
+++ {"user_expressions": []}
194+
191195

192196
Now let's call it.
193197

194198
```{code-cell} ipython3
195199
compute_mean()
196200
```
197201

202+
203+
198204
### A Vectorized Routine
199205

200206
If we want a more accurate estimate we should increase $n$.
@@ -218,7 +224,7 @@ def compute_mean_vectorized(n=1_000_000):
218224
compute_mean_vectorized()
219225
```
220226

221-
+++ {"user_expressions": []}
227+
222228

223229
Notice that this routine is much faster.
224230

@@ -230,7 +236,7 @@ We can increase $n$ to get more accuracy and still have reasonable speed:
230236
compute_mean_vectorized(n=10_000_000)
231237
```
232238

233-
+++ {"user_expressions": []}
239+
234240

235241
## Pricing a European Call Option under Risk Neutrality
236242

@@ -277,7 +283,7 @@ $$
277283
\mathbb E G = \frac{1}{2} \times 10^6 + \frac{1}{2} \times 0 = 5 \times 10^5
278284
$$
279285

280-
+++ {"user_expressions": []}
286+
281287

282288
### A Comment on Risk
283289

@@ -299,7 +305,7 @@ these promises.
299305
Nonetheless, the risk-neutral price is an important benchmark, which economists
300306
and financial market participants try to calculate every day.
301307

302-
+++ {"user_expressions": []}
308+
303309

304310
### Discounting
305311

@@ -329,7 +335,7 @@ $$
329335
= \beta^n 5 \times 10^5
330336
$$
331337

332-
+++ {"user_expressions": []}
338+
333339

334340
### European Call Options
335341

@@ -381,15 +387,15 @@ n = 10
381387
β = 0.95
382388
```
383389

384-
+++ {"user_expressions": []}
390+
385391

386392
We set the simulation size to
387393

388394
```{code-cell} ipython3
389395
M = 10_000_000
390396
```
391397

392-
+++ {"user_expressions": []}
398+
393399

394400
Here is our code
395401

@@ -400,7 +406,7 @@ P = β**n * np.mean(return_draws)
400406
print(f"The Monte Carlo option price is approximately {P:3f}")
401407
```
402408

403-
+++ {"user_expressions": []}
409+
404410

405411
## Pricing Via a Dynamic Model
406412

@@ -472,7 +478,7 @@ $$
472478

473479
Here $\{\eta_t\}$ is also IID and standard normal.
474480

475-
+++ {"user_expressions": []}
481+
476482

477483
### Default Parameters
478484

@@ -486,7 +492,7 @@ S0 = 10
486492
h0 = 0
487493
```
488494

489-
+++ {"user_expressions": []}
495+
490496

491497
(Here `S0` is $S_0$ and `h0` is $h_0$.)
492498

@@ -498,7 +504,7 @@ n = 10
498504
β = 0.95
499505
```
500506

501-
+++ {"user_expressions": []}
507+
502508

503509
### Visualizations
504510

@@ -521,7 +527,7 @@ def simulate_asset_price_path(μ=μ, S0=S0, h0=h0, n=n, ρ=ρ, ν=ν):
521527
return np.exp(s)
522528
```
523529

524-
+++ {"user_expressions": []}
530+
525531

526532
Here we plot the paths and the log of the paths.
527533

@@ -540,7 +546,7 @@ fig.tight_layout()
540546
plt.show()
541547
```
542548

543-
+++ {"user_expressions": []}
549+
544550

545551
### Computing the Price
546552

@@ -591,7 +597,7 @@ def compute_call_price(β=β,
591597
compute_call_price()
592598
```
593599

594-
+++ {"user_expressions": []}
600+
595601

596602
## Exercises
597603

@@ -637,6 +643,8 @@ def compute_call_price(β=β,
637643
compute_call_price()
638644
```
639645

646+
647+
640648
Notice that this version is faster than the one using a Python loop.
641649

642650
Now let's try with larger $M$ to get a more accurate calculation.
@@ -646,13 +654,20 @@ Now let's try with larger $M$ to get a more accurate calculation.
646654
compute_call_price(M=10_000_000)
647655
```
648656

657+
658+
649659
```{solution-end}
650660
```
651661

652662
```{exercise}
653663
:label: monte_carlo_ex2
654664
655-
Consider that a European call option may be written on an underlying with spot price of \$100 and a knockout barrier of \$120. This option behaves in every way like a vanilla European call, except if the spot price ever moves above \$120, the option "knocks out" and the contract is null and void. Note that the option does not reactivate if the spot price falls below \$120 again.
665+
Consider that a European call option may be written on an underlying with spot price of \$100 and a knockout barrier of \$120.
666+
667+
This option behaves in every way like a vanilla European call, except if the spot price ever moves above \$120, the option "knocks out" and the contract is null and void.
668+
669+
Note that the option does not reactivate if the spot price falls below \$120 again.
670+
656671
Use the dynamics defined in {eq}`s_mc_dyms` to price the European call option.
657672
```
658673

@@ -688,16 +703,17 @@ def compute_call_price_with_barrier(β=β,
688703
for m in range(M):
689704
s = np.log(S0)
690705
h = h0
706+
is_null = False
691707
# Simulate forward in time
692708
for t in range(n):
693-
s_next = s + μ + np.exp(h) * randn()
709+
s = s + μ + np.exp(h) * randn()
694710
h = ρ * h + ν * randn()
695-
# Contract is closed as S_n > barrier price
696-
if np.exp(s_next) > bp:
697-
break
698-
s = s_next
699-
# And add the value max{S_n - K, 0} to current_sum
700-
current_sum += np.maximum(np.exp(s) - K, 0)
711+
if np.exp(s) > bp:
712+
is_null = True
713+
714+
if not is_null:
715+
# And add the value max{S_n - K, 0} to current_sum
716+
current_sum += np.maximum(np.exp(s) - K, 0)
701717
702718
return β**n * current_sum / M
703719
```

0 commit comments

Comments
 (0)