1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2020 Lew Wei Hao
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include "fdcir.hpp"
21#include "fdheston.hpp"
22#include "utilities.hpp"
23#include <ql/instruments/barrieroption.hpp>
24#include <ql/models/equity/hestonmodel.hpp>
25#include <ql/pricingengines/barrier/fdhestonbarrierengine.hpp>
26#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
27#include <ql/pricingengines/vanilla/fdblackscholesvanillaengine.hpp>
28#include <ql/pricingengines/vanilla/fdcirvanillaengine.hpp>
29#include <ql/processes/coxingersollrossprocess.hpp>
30#include <ql/quotes/simplequote.hpp>
31#include <ql/termstructures/volatility/equityfx/localconstantvol.hpp>
32#include <ql/termstructures/yield/flatforward.hpp>
33#include <ql/time/daycounters/actual365fixed.hpp>
34
35using namespace QuantLib;
36using boost::unit_test_framework::test_suite;
37
38void FdCIRTest::testFdmCIRConvergence() {
39 BOOST_TEST_MESSAGE("Testing FDM CIR convergence...");
40
41 FdmSchemeDesc schemes[] = {
42 FdmSchemeDesc::Hundsdorfer(),
43 FdmSchemeDesc::ModifiedCraigSneyd(),
44 FdmSchemeDesc::ModifiedHundsdorfer(),
45 FdmSchemeDesc::CraigSneyd(),
46 FdmSchemeDesc::TrBDF2(),
47 FdmSchemeDesc::CrankNicolson(),
48 };
49
50 // set up dates
51 Date today = Date::todaysDate();
52
53 // our options
54 Option::Type type(Option::Put);
55 Real underlying = 36;
56 Real strike = 40;
57 Spread dividendYield = 0.00;
58 Rate riskFreeRate = 0.06;
59 Volatility volatility = 0.20;
60 Date maturity = today + 365;
61 DayCounter dayCounter = Actual365Fixed();
62
63 ext::shared_ptr<Exercise> europeanExercise(
64 new EuropeanExercise(maturity));
65
66 Handle<Quote> underlyingH(
67 ext::shared_ptr<Quote>(new SimpleQuote(underlying)));
68
69 Handle<YieldTermStructure> flatTermStructure(
70 ext::shared_ptr<YieldTermStructure>(flatRate(today, forward: riskFreeRate, dc: dayCounter)));
71 Handle<YieldTermStructure> flatDividendTS(
72 ext::shared_ptr<YieldTermStructure>(flatRate(today, forward: dividendYield, dc: dayCounter)));
73 Handle<BlackVolTermStructure> flatVolTS(
74 ext::shared_ptr<BlackVolTermStructure>(flatVol(today, volatility, dc: dayCounter)));
75 ext::shared_ptr<StrikedTypePayoff> payoff(
76 new PlainVanillaPayoff(type, strike));
77 ext::shared_ptr<BlackScholesMertonProcess> bsmProcess(
78 new BlackScholesMertonProcess(underlyingH, flatDividendTS,
79 flatTermStructure, flatVolTS));
80
81 VanillaOption europeanOption(payoff, europeanExercise);
82
83 Real speed = 1.2188;
84 Real cirSigma = 0.02438;
85 Real level = 0.0183;
86 Real initialRate = 0.06;
87 Real rho = 0.00789;
88 Real lambda = -0.5726;
89 Real newSpeed = speed + (cirSigma*lambda); //1.0792
90 Real newLevel = (level * speed)/(speed + (cirSigma*lambda));//// 0.0240
91
92 ext::shared_ptr<CoxIngersollRossProcess> cirProcess(new CoxIngersollRossProcess(newSpeed, cirSigma, initialRate, newLevel));
93
94 Real expected = 4.275;
95 Real tolerance = 0.0003;
96
97 for (const auto& scheme : schemes) {
98 ext::shared_ptr<PricingEngine> fdcirengine =
99 MakeFdCIRVanillaEngine(cirProcess, bsmProcess, rho).withFdmSchemeDesc(schemeDesc: scheme);
100 europeanOption.setPricingEngine(fdcirengine);
101 Real calculated = europeanOption.NPV();
102 if (std::fabs(x: expected - calculated) > tolerance) {
103 BOOST_ERROR("Failed to reproduce expected npv"
104 << "\n calculated: " << calculated
105 << "\n expected: " << expected
106 << "\n tolerance: " << tolerance);
107 }
108 }
109}
110
111test_suite* FdCIRTest::suite(SpeedLevel speed) {
112 auto* suite = BOOST_TEST_SUITE("Finite Difference CIR tests");
113
114 suite->add(QUANTLIB_TEST_CASE(&FdCIRTest::testFdmCIRConvergence));
115
116 return suite;
117}
118
119

source code of quantlib/test-suite/fdcir.cpp