Skip to content

Commit c8d88ca

Browse files
committed
Changed HW2 to use PyFENG functions
1 parent 3492470 commit c8d88ca

File tree

4 files changed

+75
-183
lines changed

4 files changed

+75
-183
lines changed

py/HW2/TestCode_BasketSpread.ipynb

+68-48
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Basket option implementation based on normal model"
7+
"# Basket option implementation with Bachelier model CV"
88
]
99
},
1010
{
@@ -24,19 +24,12 @@
2424
"outputs": [],
2525
"source": [
2626
"import numpy as np\n",
27+
"import pyfeng as pf\n",
28+
"\n",
2729
"#import option_models as opt\n",
28-
"from option_models import basket\n",
29-
"from option_models import bsm\n",
30-
"from option_models import normal"
30+
"from option_models import basket"
3131
]
3232
},
33-
{
34-
"cell_type": "code",
35-
"execution_count": null,
36-
"metadata": {},
37-
"outputs": [],
38-
"source": []
39-
},
4033
{
4134
"cell_type": "code",
4235
"execution_count": 3,
@@ -49,7 +42,7 @@
4942
"\n",
5043
"spot = np.ones(4) * 100\n",
5144
"vol = np.ones(4) * 0.4\n",
52-
"weights = np.array([0, 1, 0, 0])\n",
45+
"weights = np.array([1, 0, 0, 0])\n",
5346
"divr = np.zeros(4)\n",
5447
"intr = 0\n",
5548
"cor_m = 0.5*np.identity(4) + 0.5\n",
@@ -89,8 +82,8 @@
8982
"name": "stdout",
9083
"output_type": "stream",
9184
"text": [
92-
"[0 1 0 0]\n",
93-
"26.92956987643586\n"
85+
"[1 0 0 0]\n",
86+
"26.570984651213593\n"
9487
]
9588
}
9689
],
@@ -111,15 +104,15 @@
111104
"name": "stdout",
112105
"output_type": "stream",
113106
"text": [
114-
"26.92956987643586 26.570845957870503\n"
107+
"26.570984651213593 26.570845957870503\n"
115108
]
116109
}
117110
],
118111
"source": [
119112
"# Compare the price to normal model formula\n",
120113
"\n",
121-
"norm1 = normal.NormalModel(vol=40)\n",
122-
"price_norm = norm1.price(strike=120, spot=100, texp=texp, cp=1)\n",
114+
"norm1 = pf.Norm(sigma=40)\n",
115+
"price_norm = norm1.price(strike, spot[0], texp, cp=1)\n",
123116
"print(price_basket, price_norm)"
124117
]
125118
},
@@ -136,7 +129,7 @@
136129
" [0.9999 1. 0.9999 0.9999]\n",
137130
" [0.9999 0.9999 1. 0.9999]\n",
138131
" [0.9999 0.9999 0.9999 1. ]]\n",
139-
"26.761395615904505 26.570845957870503\n"
132+
"26.57211110181949 26.570845957870503\n"
140133
]
141134
}
142135
],
@@ -188,10 +181,11 @@
188181
{
189182
"data": {
190183
"text/plain": [
191-
"array([[1. , 0.5, 0.5, 0.5],\n",
192-
" [0.5, 1. , 0.5, 0.5],\n",
193-
" [0.5, 0.5, 1. , 0.5],\n",
194-
" [0.5, 0.5, 0.5, 1. ]])"
184+
"(array([0.25, 0.25, 0.25, 0.25]),\n",
185+
" array([[1. , 0.5, 0.5, 0.5],\n",
186+
" [0.5, 1. , 0.5, 0.5],\n",
187+
" [0.5, 0.5, 1. , 0.5],\n",
188+
" [0.5, 0.5, 0.5, 1. ]]))"
195189
]
196190
},
197191
"execution_count": 9,
@@ -200,7 +194,7 @@
200194
}
201195
],
202196
"source": [
203-
"cor_m"
197+
"weights, cor_m"
204198
]
205199
},
206200
{
@@ -212,7 +206,7 @@
212206
"name": "stdout",
213207
"output_type": "stream",
214208
"text": [
215-
"28.168716545630815 28.0073695\n"
209+
"28.22782882893394 28.0073695\n"
216210
]
217211
}
218212
],
@@ -280,6 +274,25 @@
280274
"price_basket = basket.basket_price_mc(strike, spot, vol, weights, texp, cor_m, bsm=True)"
281275
]
282276
},
277+
{
278+
"cell_type": "code",
279+
"execution_count": 13,
280+
"metadata": {},
281+
"outputs": [
282+
{
283+
"name": "stdout",
284+
"output_type": "stream",
285+
"text": [
286+
"0.0 28.713486748445934\n"
287+
]
288+
}
289+
],
290+
"source": [
291+
"bsm1 = pf.Bsm(sigma=vol[0])\n",
292+
"price_bsm = bsm1.price(strike, spot[0], texp, cp=1)\n",
293+
"print(price_basket, price_bsm)"
294+
]
295+
},
283296
{
284297
"cell_type": "markdown",
285298
"metadata": {},
@@ -289,7 +302,7 @@
289302
},
290303
{
291304
"cell_type": "code",
292-
"execution_count": 13,
305+
"execution_count": 14,
293306
"metadata": {},
294307
"outputs": [],
295308
"source": [
@@ -300,22 +313,23 @@
300313
"weights = np.array([1, -1])\n",
301314
"divr = np.array([1, 1])*0.05\n",
302315
"intr = 0.1\n",
303-
"cor_m = np.array([[1, 0.5], [0.5, 1]])\n",
316+
"cor = 0.5\n",
317+
"cor_m = np.array([[1, cor], [cor, 1]])\n",
304318
"texp = 1\n",
305319
"strike = 0\n",
306320
"price_exact = 8.5132252"
307321
]
308322
},
309323
{
310324
"cell_type": "code",
311-
"execution_count": 14,
325+
"execution_count": 15,
312326
"metadata": {},
313327
"outputs": [
314328
{
315329
"name": "stdout",
316330
"output_type": "stream",
317331
"text": [
318-
"8.348852807225292 8.5132252\n"
332+
"8.317680907159142 8.5132252\n"
319333
]
320334
}
321335
],
@@ -337,31 +351,44 @@
337351
},
338352
{
339353
"cell_type": "code",
340-
"execution_count": 15,
354+
"execution_count": 16,
341355
"metadata": {},
342-
"outputs": [],
356+
"outputs": [
357+
{
358+
"data": {
359+
"text/plain": [
360+
"0.0"
361+
]
362+
},
363+
"execution_count": 16,
364+
"metadata": {},
365+
"output_type": "execute_result"
366+
}
367+
],
343368
"source": [
344369
"# Once the implementation is finished the BSM model price should also work\n",
345370
"price_spread = basket.basket_price_mc(\n",
346-
" strike, spot, vol*spot, weights, texp, cor_m, intr=intr, divr=divr, bsm=True)"
371+
" strike, spot, vol*spot, weights, texp, cor_m, intr=intr, divr=divr, bsm=True)\n",
372+
"price_spread"
347373
]
348374
},
349375
{
350376
"cell_type": "code",
351-
"execution_count": 16,
377+
"execution_count": 17,
352378
"metadata": {},
353379
"outputs": [
354380
{
355381
"name": "stdout",
356382
"output_type": "stream",
357383
"text": [
358-
"8.5132252295455 0.0\n"
384+
"8.513225229545505 0.0\n"
359385
]
360386
}
361387
],
362388
"source": [
363389
"# You also test Kirk's approximation\n",
364-
"price_kirk = basket.spread_price_kirk(strike, spot, vol, texp, 0.5, intr, divr)\n",
390+
"kirk = pf.BsmSpreadKirk(vol, cor=cor, divr=divr, intr=intr)\n",
391+
"price_kirk = kirk.price(strike, spot, texp)\n",
365392
"print(price_kirk, price_spread)"
366393
]
367394
},
@@ -375,7 +402,7 @@
375402
},
376403
{
377404
"cell_type": "code",
378-
"execution_count": 17,
405+
"execution_count": 18,
379406
"metadata": {},
380407
"outputs": [],
381408
"source": [
@@ -392,7 +419,7 @@
392419
},
393420
{
394421
"cell_type": "code",
395-
"execution_count": 18,
422+
"execution_count": 19,
396423
"metadata": {},
397424
"outputs": [
398425
{
@@ -401,7 +428,7 @@
401428
"0.0"
402429
]
403430
},
404-
"execution_count": 18,
431+
"execution_count": 19,
405432
"metadata": {},
406433
"output_type": "execute_result"
407434
}
@@ -413,7 +440,7 @@
413440
},
414441
{
415442
"cell_type": "code",
416-
"execution_count": 19,
443+
"execution_count": 20,
417444
"metadata": {},
418445
"outputs": [],
419446
"source": [
@@ -425,7 +452,7 @@
425452
},
426453
{
427454
"cell_type": "code",
428-
"execution_count": 20,
455+
"execution_count": 21,
429456
"metadata": {},
430457
"outputs": [
431458
{
@@ -439,19 +466,12 @@
439466
"source": [
440467
"print(price_basket)"
441468
]
442-
},
443-
{
444-
"cell_type": "code",
445-
"execution_count": null,
446-
"metadata": {},
447-
"outputs": [],
448-
"source": []
449469
}
450470
],
451471
"metadata": {
452472
"anaconda-cloud": {},
453473
"kernelspec": {
454-
"display_name": "Python 3",
474+
"display_name": "Python 3 (ipykernel)",
455475
"language": "python",
456476
"name": "python3"
457477
},
@@ -465,7 +485,7 @@
465485
"name": "python",
466486
"nbconvert_exporter": "python",
467487
"pygments_lexer": "ipython3",
468-
"version": "3.8.5"
488+
"version": "3.8.11"
469489
}
470490
},
471491
"nbformat": 4,

py/HW2/option_models/basket.py

+7-15
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
"""
77
import numpy as np
88
import scipy.stats as ss
9-
from .bsm import bsm_formula
10-
from .normal import normal_formula
9+
import pyfeng as pf
1110

1211
def basket_check_args(spot, vol, corr_m, weights):
1312
'''
@@ -63,7 +62,7 @@ def basket_price_mc(
6362
forward = spot / disc_fac * div_fac
6463

6564
cov_m = vol * cor_m * vol[:,None]
66-
chol_m = np.linalg.cholesky(cov_m)
65+
chol_m = np.linalg.cholesky(cov_m) # L matrix in slides
6766

6867
n_assets = spot.size
6968
znorm_m = np.random.normal(size=(n_assets, n_samples))
@@ -94,20 +93,13 @@ def basket_price_norm_analytic(
9493
1. compute the forward of the basket
9594
2. compute the normal volatility of basket
9695
3. plug in the forward and volatility to the normal price formula
97-
normal_formula(strike, spot, vol, texp, intr=0.0, divr=0.0, cp=1)
98-
it is already imorted
96+
97+
norm = pf.Norm(sigma, intr=intr, divr=divr)
98+
norm.price(strike, spot, texp, cp=cp)
9999
100100
PUT YOUR CODE BELOW
101101
'''
102102

103+
104+
103105
return 0.0
104-
105-
def spread_price_kirk(strike, spot, vol, texp, corr, intr=0, divr=0, cp=1):
106-
div_fac = np.exp(-texp*divr)
107-
disc_fac = np.exp(-texp*intr)
108-
forward = spot / disc_fac * div_fac
109-
vol2 = vol[1]*forward[1]/(forward[1]+strike)
110-
vol_r = np.sqrt(vol[0]**2 + vol2*(vol2 - 2*corr*vol[0]))
111-
price = disc_fac * bsm_formula(forward[1]+strike, forward[0], vol_r, texp, cp=cp)
112-
113-
return price

0 commit comments

Comments
 (0)