Coverage Report

Created: 2025-10-14 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/methods/montecarlo/parametricexercise.cpp
Line
Count
Source
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
 <https://www.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
24
namespace 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
0
            Array values(const Array&) const override {
35
0
                QL_FAIL("values method not implemented");
36
0
            }
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
0
        : simulationData_(simulationData), exercise_(exercise),
50
0
          exerciseIndex_(exerciseIndex),
51
0
          parameters_(exercise.numberOfParameters()[exerciseIndex]) {
52
0
            for (const auto& i : simulationData_) {
53
0
                if (i.isValid)
54
0
                    return;
55
0
            }
56
0
            QL_FAIL("no valid paths");
57
0
        }
58
59
0
        Real ValueEstimate::value(const Array& parameters) const {
60
0
            std::copy(parameters.begin(), parameters.end(),
61
0
                      parameters_.begin());
62
0
            Real sum = 0.0;
63
0
            Size n = 0;
64
0
            for (const auto& i : simulationData_) {
65
0
                if (i.isValid) {
66
0
                    ++n;
67
0
                    if (exercise_.exercise(exerciseIndex_, parameters_, i.values))
68
0
                        sum += i.exerciseValue;
69
0
                    else
70
0
                        sum += i.cumulatedCashFlows;
71
0
                }
72
0
            }
73
0
            return -sum/n;
74
0
        }
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
0
                          OptimizationMethod& method) {
86
87
0
        Size steps = simulationData.size();
88
0
        parameters.resize(steps-1);
89
90
0
        for (Size i=steps-1; i!=0; --i) {
91
0
            const std::vector<NodeData>& exerciseData = simulationData[i];
92
93
0
            parameters[i-1].resize(exercise.numberOfParameters()[i-1]);
94
95
96
            // optimize
97
0
            ValueEstimate f(exerciseData, exercise, i-1);
98
99
0
            Array guess(parameters[i-1].size());
100
0
            exercise.guess(i-1, parameters[i-1]);
101
0
            std::copy(parameters[i-1].begin(), parameters[i-1].end(),
102
0
                      guess.begin());
103
104
0
            NoConstraint c;
105
106
0
            Problem p(f, c, guess);
107
0
            method.minimize(p, endCriteria);
108
109
0
            Array result = p.currentValue();
110
0
            std::copy(result.begin(), result.end(),
111
0
                      parameters[i-1].begin());
112
113
0
            std::vector<NodeData>& previousData = simulationData[i-1];
114
0
            for (Size j=0; j<previousData.size(); ++j) {
115
0
                if (exerciseData[j].isValid) {
116
0
                    if (exercise.exercise(i-1,
117
0
                                          parameters[i-1],
118
0
                                          exerciseData[j].values))
119
0
                        previousData[j].cumulatedCashFlows +=
120
0
                            exerciseData[j].exerciseValue;
121
0
                    else
122
0
                        previousData[j].cumulatedCashFlows +=
123
0
                            exerciseData[j].cumulatedCashFlows;
124
0
                }
125
0
            }
126
0
        }
127
128
0
        Real sum = 0.0;
129
0
        const std::vector<NodeData>& initialData = simulationData.front();
130
0
        for (const auto& i : initialData)
131
0
            sum += i.cumulatedCashFlows;
132
0
        return sum/initialData.size();
133
0
    }
134
135
}
136