QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
fdsimpleextoustorageengine.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2011 Klaus Spanderen
5 Copyright (C) 2014 Ralph Schreyer
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
25#include <ql/experimental/finitedifferences/fdmexpextouinnervaluecalculator.hpp>
26#include <ql/experimental/finitedifferences/fdmsimple2dextousolver.hpp>
27#include <ql/experimental/finitedifferences/fdsimpleextoustorageengine.hpp>
28#include <ql/experimental/processes/extendedornsteinuhlenbeckprocess.hpp>
29#include <ql/math/comparison.hpp>
30#include <ql/methods/finitedifferences/meshers/fdmmeshercomposite.hpp>
31#include <ql/methods/finitedifferences/meshers/fdmsimpleprocess1dmesher.hpp>
32#include <ql/methods/finitedifferences/meshers/predefined1dmesher.hpp>
33#include <ql/methods/finitedifferences/meshers/uniform1dmesher.hpp>
34#include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp>
35#include <ql/methods/finitedifferences/solvers/fdmbackwardsolver.hpp>
36#include <ql/methods/finitedifferences/solvers/fdmsolverdesc.hpp>
37#include <ql/methods/finitedifferences/stepconditions/fdmsimplestoragecondition.hpp>
38#include <ql/methods/finitedifferences/stepconditions/fdmstepconditioncomposite.hpp>
39#include <ql/methods/finitedifferences/utilities/fdminnervaluecalculator.hpp>
40#include <ql/pricingengines/vanilla/fdsimplebsswingengine.hpp>
41#include <ql/termstructures/yieldtermstructure.hpp>
42#include <utility>
43
44namespace QuantLib {
45
46 namespace {
47 class FdmStorageValue : public FdmInnerValueCalculator {
48 public:
49 explicit FdmStorageValue(ext::shared_ptr<FdmMesher> mesher)
50 : mesher_(std::move(mesher)) {}
51
52 Real innerValue(const FdmLinearOpIterator& iter, Time) override {
53 const Real s = std::exp(mesher_->location(iter, 0));
54 const Real v = mesher_->location(iter, 1);
55 return s*v;
56 }
57 Real avgInnerValue(const FdmLinearOpIterator& iter, Time t) override {
58 return innerValue(iter, t);
59 }
60
61 private:
62 const ext::shared_ptr<FdmMesher> mesher_;
63
64 };
65
66 class LessButNotCloseEnough {
67 public:
68 bool operator()(Real a, Real b) const {
69 return !(close_enough(a, b, 100) || b < a);
70 }
71 };
72 }
73
75 ext::shared_ptr<ExtendedOrnsteinUhlenbeckProcess> process,
76 ext::shared_ptr<YieldTermStructure> rTS,
77 Size tGrid,
78 Size xGrid,
79 Size yGrid,
80 ext::shared_ptr<Shape> shape,
81 const FdmSchemeDesc& schemeDesc)
82 : process_(std::move(process)), rTS_(std::move(rTS)), tGrid_(tGrid), xGrid_(xGrid),
83 yGrid_(yGrid), shape_(std::move(shape)), schemeDesc_(schemeDesc) {}
84
86
87 // 1. Exercise
88 QL_REQUIRE(arguments_.exercise->type() == Exercise::Bermudan,
89 "Bermudan exercise supported only");
90
91 // 2. Mesher
92 const Time maturity
93 = rTS_->dayCounter().yearFraction(rTS_->referenceDate(),
94 arguments_.exercise->lastDate());
95
96 const ext::shared_ptr<Fdm1dMesher> xMesher(
98
99 ext::shared_ptr<Fdm1dMesher> storageMesher;
100
101 if(yGrid_ == Null<Size>()){
102 //elevator mesher
103 std::vector<Real> storageValues(1, arguments_.capacity);
104 storageValues.reserve(
106
107 for (Real level=0; level <= arguments_.capacity;
108 level+=arguments_.changeRate) {
109 storageValues.push_back(level);
110 storageValues.push_back(arguments_.capacity - level);
111 }
112
113 const std::set<Real, LessButNotCloseEnough> orderedValues(
114 storageValues.begin(), storageValues.end());
115 storageValues.assign(orderedValues.begin(), orderedValues.end());
116
117 storageMesher = ext::shared_ptr<Fdm1dMesher>(
118 new Predefined1dMesher(storageValues));
119 }
120 else {
121 // uniform mesher
122 storageMesher = ext::shared_ptr<Fdm1dMesher>(
124 }
125
126 const ext::shared_ptr<FdmMesher> mesher (
127 new FdmMesherComposite(xMesher, storageMesher));
128
129 // 3. Calculator
130 ext::shared_ptr<FdmInnerValueCalculator> storageCalculator(
131 new FdmStorageValue(mesher));
132
133 // 4. Step conditions
134 std::list<ext::shared_ptr<StepCondition<Array> > > stepConditions;
135 std::list<std::vector<Time> > stoppingTimes;
136
137 // 4.1 Bermudan step conditions
138 std::vector<Time> exerciseTimes;
139 for (auto i : arguments_.exercise->dates()) {
140 const Time t = rTS_->dayCounter().yearFraction(rTS_->referenceDate(), i);
141
142 QL_REQUIRE(t >= 0, "exercise dates must not contain past date");
143 exerciseTimes.push_back(t);
144 }
145 stoppingTimes.push_back(exerciseTimes);
146
147 ext::shared_ptr<Payoff> payoff(
149
150 ext::shared_ptr<FdmInnerValueCalculator> underlyingCalculator(
151 new FdmExpExtOUInnerValueCalculator(payoff, mesher, shape_));
152
153 stepConditions.push_back(ext::shared_ptr<StepCondition<Array> >(
154 new FdmSimpleStorageCondition(exerciseTimes,
155 mesher, underlyingCalculator,
157
158 ext::shared_ptr<FdmStepConditionComposite> conditions(
159 new FdmStepConditionComposite(stoppingTimes, stepConditions));
160
161 // 5. Boundary conditions
162 const FdmBoundaryConditionSet boundaries;
163
164 // 6. Solver
165 FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
166 storageCalculator, maturity, tGrid_, 0 };
167
168 ext::shared_ptr<FdmSimple2dExtOUSolver> solver(
171 rTS_, solverDesc, schemeDesc_));
172
173 const Real x = process_->x0();
174 const Real y = arguments_.load;
175
176 results_.value = solver->valueAt(x, y);
177 }
178}
FdSimpleExtOUStorageEngine(ext::shared_ptr< ExtendedOrnsteinUhlenbeckProcess > p, ext::shared_ptr< YieldTermStructure > rTS, Size tGrid=50, Size xGrid=100, Size yGrid=Null< Size >(), ext::shared_ptr< Shape > shape=ext::shared_ptr< Shape >(), const FdmSchemeDesc &schemeDesc=FdmSchemeDesc::Douglas())
const ext::shared_ptr< YieldTermStructure > rTS_
const ext::shared_ptr< ExtendedOrnsteinUhlenbeckProcess > process_
Shared handle to an observable.
Definition: handle.hpp:41
template class providing a null value for a given type.
Definition: null.hpp:76
Plain-vanilla payoff.
Definition: payoffs.hpp:105
condition to be applied at every time step
ext::shared_ptr< BermudanExercise > exercise
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
bool close_enough(const Quantity &m1, const Quantity &m2, Size n)
Definition: quantity.cpp:182
OperatorTraits< FdmLinearOp >::bc_set FdmBoundaryConditionSet
STL namespace.