1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006 StatPro Italia srl
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 <ql/methods/montecarlo/parametricexercise.hpp>
21#include <ql/math/optimization/problem.hpp>
22#include <ql/math/optimization/constraint.hpp>
23
24namespace QuantLib {
25
26 namespace {
27
28 class ValueEstimate : public CostFunction {
29 public:
30 ValueEstimate(const std::vector<NodeData>& simulationData,
31 const ParametricExercise& exercise,
32 Size exerciseIndex);
33 Real value(const Array& parameters) const override;
34 Array values(const Array&) const override {
35 QL_FAIL("values method not implemented");
36 }
37
38 private:
39 const std::vector<NodeData>& simulationData_;
40 const ParametricExercise& exercise_;
41 Size exerciseIndex_;
42 mutable std::vector<Real> parameters_;
43 };
44
45 ValueEstimate::ValueEstimate(
46 const std::vector<NodeData>& simulationData,
47 const ParametricExercise& exercise,
48 Size exerciseIndex)
49 : simulationData_(simulationData), exercise_(exercise),
50 exerciseIndex_(exerciseIndex),
51 parameters_(exercise.numberOfParameters()[exerciseIndex]) {
52 for (const auto& i : simulationData_) {
53 if (i.isValid)
54 return;
55 }
56 QL_FAIL("no valid paths");
57 }
58
59 Real ValueEstimate::value(const Array& parameters) const {
60 std::copy(first: parameters.begin(), last: parameters.end(),
61 result: parameters_.begin());
62 Real sum = 0.0;
63 Size n = 0;
64 for (const auto& i : simulationData_) {
65 if (i.isValid) {
66 ++n;
67 if (exercise_.exercise(exerciseNumber: exerciseIndex_, parameters: parameters_, variables: i.values))
68 sum += i.exerciseValue;
69 else
70 sum += i.cumulatedCashFlows;
71 }
72 }
73 return -sum/n;
74 }
75
76 }
77
78
79
80 Real genericEarlyExerciseOptimization(
81 std::vector<std::vector<NodeData> >& simulationData,
82 const ParametricExercise& exercise,
83 std::vector<std::vector<Real> >& parameters,
84 const EndCriteria& endCriteria,
85 OptimizationMethod& method) {
86
87 Size steps = simulationData.size();
88 parameters.resize(new_size: steps-1);
89
90 for (Size i=steps-1; i!=0; --i) {
91 const std::vector<NodeData>& exerciseData = simulationData[i];
92
93 parameters[i-1].resize(new_size: exercise.numberOfParameters()[i-1]);
94
95
96 // optimize
97 ValueEstimate f(exerciseData, exercise, i-1);
98
99 Array guess(parameters[i-1].size());
100 exercise.guess(exerciseNumber: i-1, parameters&: parameters[i-1]);
101 std::copy(first: parameters[i-1].begin(), last: parameters[i-1].end(),
102 result: guess.begin());
103
104 NoConstraint c;
105
106 Problem p(f, c, guess);
107 method.minimize(P&: p, endCriteria);
108
109 Array result = p.currentValue();
110 std::copy(first: result.begin(), last: result.end(),
111 result: parameters[i-1].begin());
112
113 std::vector<NodeData>& previousData = simulationData[i-1];
114 for (Size j=0; j<previousData.size(); ++j) {
115 if (exerciseData[j].isValid) {
116 if (exercise.exercise(exerciseNumber: i-1,
117 parameters: parameters[i-1],
118 variables: exerciseData[j].values))
119 previousData[j].cumulatedCashFlows +=
120 exerciseData[j].exerciseValue;
121 else
122 previousData[j].cumulatedCashFlows +=
123 exerciseData[j].cumulatedCashFlows;
124 }
125 }
126 }
127
128 Real sum = 0.0;
129 const std::vector<NodeData>& initialData = simulationData.front();
130 for (const auto& i : initialData)
131 sum += i.cumulatedCashFlows;
132 return sum/initialData.size();
133 }
134
135}
136
137

source code of quantlib/ql/methods/montecarlo/parametricexercise.cpp