Skip to content

Commit 89ceda2

Browse files
committed
more tests
1 parent f7a7757 commit 89ceda2

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

test/test_hybridhestonhullwhite_process.py

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
from __future__ import division
2-
from __future__ import print_function
3-
41
import unittest
52

63
import numpy as np
@@ -15,12 +12,14 @@
1512
from quantlib.instruments.option import VanillaOption
1613

1714
from quantlib.time.api import (today, Years, Actual365Fixed,
18-
Period, May, Date,
15+
Period, May, Date, Actual360,
1916
NullCalendar)
2017

2118
from quantlib.processes.api import (BlackScholesMertonProcess,
2219
HestonProcess,
23-
HullWhiteProcess)
20+
HullWhiteProcess,
21+
HullWhiteForwardProcess,
22+
HybridHestonHullWhiteProcess)
2423

2524
from quantlib.models.equity.heston_model import (
2625
HestonModel)
@@ -33,17 +32,18 @@
3332
AnalyticBSMHullWhiteEngine,
3433
AnalyticHestonEngine,
3534
AnalyticHestonHullWhiteEngine,
36-
FdHestonHullWhiteVanillaEngine)
35+
FdHestonHullWhiteVanillaEngine,
36+
MCHestonHullWhiteEngine)
3737

3838
from quantlib.quotes import SimpleQuote
3939

40-
from quantlib.instruments.payoffs import (
41-
PlainVanillaPayoff)
40+
from quantlib.instruments.payoffs import PlainVanillaPayoff
4241

4342
from quantlib.methods.finitedifferences.solvers.fdmbackwardsolver import FdmSchemeDesc
4443

4544
from .utilities import flat_rate
4645

46+
from math import sin, exp
4747

4848
class HybridHestonHullWhiteProcessTestCase(unittest.TestCase):
4949

@@ -96,8 +96,8 @@ def setUp(self):
9696
self.dates = dates
9797

9898
def test_bsm_hw(self):
99-
print("Testing European option pricing for a BSM process" +
100-
" with one-factor Hull-White model...")
99+
"""Testing European option pricing for a BSM process
100+
with one-factor Hull-White model"""
101101

102102
dc = Actual365Fixed()
103103
todays_date = today()
@@ -248,12 +248,8 @@ def test_compare_bsm_bsmhw_hestonhw(self):
248248
self.assertAlmostEqual(npv_bsm, npv_hestonhw, delta=tol)
249249

250250
def test_compare_BsmHW_HestonHW(self):
251-
"""
252-
From Quantlib test suite
253-
"""
254-
255-
print("Comparing European option pricing for a BSM " +
256-
"process with one-factor Hull-White model...")
251+
"""Comparing European option pricing for a BSM
252+
process with one-factor Hull-White model"""
257253

258254
dc = Actual365Fixed()
259255

@@ -356,8 +352,8 @@ def test_zanette(self):
356352
# constant yield and div curves
357353

358354
dates = [todays_date + Period(i, Years) for i in range(3)]
359-
rates = [0.04 for i in range(3)]
360-
divRates = [0.03 for i in range(3)]
355+
rates = [0.04] * 3
356+
divRates = [0.03] * 3
361357
r_ts = HandleYieldTermStructure(ZeroCurve(dates, rates, dc))
362358
q_ts = HandleYieldTermStructure(ZeroCurve(dates, divRates, dc))
363359

@@ -421,3 +417,50 @@ def price_cal(rho, tGrid):
421417
expected_price = [11.38, ] * 4 + [12.79, ] * 4 + [14.06, ] * 4
422418

423419
np.testing.assert_almost_equal(calc_price, expected_price, 2)
420+
421+
def test_mc_vanilla_pricing(self):
422+
"""Testing Monte-Carlo vanilla option pricing"""
423+
dc = Actual360()
424+
todays_date = today()
425+
settings = Settings()
426+
settings.evaluation_date = todays_date
427+
dates = [todays_date + Period(i, Years) for i in range(41)]
428+
rates = [0.03 + 0.0003 * exp(sin(i / 4.0)) for i in range(41)]
429+
div_rates = [0.02 + 0.0001 * exp(sin(i / 5.0)) for i in range(41)]
430+
maturity = todays_date + Period(20, Years)
431+
432+
s0 = SimpleQuote(100)
433+
r_ts = HandleYieldTermStructure(ZeroCurve(dates, rates, dc))
434+
q_ts = HandleYieldTermStructure(ZeroCurve(dates, div_rates, dc))
435+
vol = SimpleQuote(0.25)
436+
vol_ts = BlackConstantVol(todays_date, NullCalendar(), vol, dc)
437+
bsm_process= BlackScholesMertonProcess(s0, q_ts, r_ts, vol_ts)
438+
heston_process = HestonProcess(r_ts, q_ts, s0, 0.0625, 0.5, 0.0625, 1e-5, 0.3)
439+
hw_process = HullWhiteForwardProcess(r_ts, 0.01, 0.01)
440+
hw_process.forward_measure_time = dc.year_fraction(todays_date, maturity)
441+
442+
tol = 0.05
443+
corr = [-0.9, -0.5, 0.0, 0.5, 0.9]
444+
strike = [100.0]
445+
exercise = EuropeanExercise(maturity)
446+
for rho in corr:
447+
for s in strike:
448+
joint_process = HybridHestonHullWhiteProcess(heston_process, hw_process, rho)
449+
payoff = PlainVanillaPayoff(OptionType.Put, s)
450+
option_heston_hw = VanillaOption(payoff, exercise)
451+
engine = MCHestonHullWhiteEngine(joint_process,
452+
time_steps=1,
453+
required_tolerance=tol,
454+
seed=42)
455+
option_heston_hw.set_pricing_engine(engine)
456+
hw_model = HullWhite(r_ts, hw_process.a, hw_process.sigma)
457+
option_BsmHW = VanillaOption(payoff, exercise)
458+
option_BsmHW.set_pricing_engine(AnalyticBSMHullWhiteEngine(rho, bsm_process, hw_model))
459+
calculated = option_heston_hw.npv
460+
error = option_heston_hw.error_estimate
461+
expected = option_BsmHW.npv
462+
print(abs(calculated - expected), error)
463+
if rho == 0:
464+
self.assertTrue(abs(calculated - expected) < tol)
465+
else:
466+
self.assertTrue(abs(calculated - expected) < 1.2 * error)

0 commit comments

Comments
 (0)