28 : payments(numberOfTimes, 0.0),
29 exercises(numberOfTimes, 0.0),
30 states(numberOfTimes) {
39 const ext::shared_ptr<PathPayoff>&
payoff,
40 const std::vector<Size>& timePositions,
49 payoff->basisSystemDimension(), polynomialOrder, polynomialType)) {
55 "insufficient polynomial type");
69 for (
Size i = 0; i < numberOfTimes; ++i) {
71 for (
Size j = 0; j < numberOfAssets; ++j)
72 path[j][i] = multiPath[j][pos];
104 const bool canExercise = !states.
empty();
107 if (canExercise && exercise > 0.0)
112 for (
Integer i = len - 2; i >= 0; --i) {
113 price *=
dF_[i + 1] /
dF_[i];
127 const bool canExercise = !states.
empty();
130 if (
coeff_[i].size() ==
v_.size() + 1) {
137 Real continuationValue = 0.0;
138 for (
Size l = 0; l <
v_.size(); ++l) {
139 continuationValue +=
coeff_[i][l] *
v_[l](states);
142 if (continuationValue < exercise) {
152 return price *
dF_[0];
157 Array prices(
n, 0.0), exercise(
n, 0.0);
159 const Size basisDimension =
payoff_->basisSystemDimension();
168 for (
Size j = 0; j <
n; ++j) {
170 const Real exercise =
paths_[j].exercises[len - 1];
172 const bool canExercise = !states.
empty();
175 if (canExercise && exercise > 0.0)
176 prices[j] += exercise;
180 lowerBounds_[len - 1] = *std::min_element(prices.begin(), prices.end());
182 std::vector<bool> lsExercise(
n);
184 for (
Integer i = len - 2; i >= 0; --i) {
186 std::vector<Array> x;
189 const Real discountRatio =
dF_[i + 1] /
dF_[i];
190 prices *= discountRatio;
194 for (
Size j = 0; j <
n; ++j) {
195 exercise[j] =
paths_[j].exercises[i];
202 "Invalid size of basis system");
210 y.push_back(prices[j]);
214 if (
v_.size() <= x.size()) {
220 QL_TRACE(
"Not enough itm paths: default decision is NEVER");
229 Real sumOptimized = 0.0;
230 Real sumNoExercise = 0.0;
231 Real sumAlwaysExercise = 0.0;
233 for (
Size j = 0, k = 0; j <
n; ++j) {
234 sumNoExercise += prices[j];
235 lsExercise[j] =
false;
237 const bool canExercise = !
paths_[j].states[i].empty();
239 sumAlwaysExercise += exercise[j];
241 Real continuationValue = 0.0;
242 for (
Size l = 0; l <
v_.size(); ++l) {
243 continuationValue +=
coeff_[i][l] *
v_[l](x[k]);
246 if (continuationValue < exercise[j]) {
247 lsExercise[j] =
true;
253 sumAlwaysExercise += prices[j];
256 sumOptimized += lsExercise[j] ? exercise[j] : prices[j];
261 sumAlwaysExercise /=
n;
265 <<
", Optimum: " << sumOptimized
266 <<
", Continuation: " << sumNoExercise
267 <<
", Termination: " << sumAlwaysExercise);
269 if ( sumOptimized >= sumNoExercise
270 && sumOptimized >= sumAlwaysExercise) {
273 for (
Size j = 0; j <
n; ++j) {
275 prices[j] = lsExercise[j] ? exercise[j] : prices[j];
278 else if (sumAlwaysExercise > sumNoExercise) {
279 QL_TRACE(
"Overridden bad LS decision: ALWAYS");
280 for (
Size j = 0; j <
n; ++j) {
281 const bool canExercise = !
paths_[j].states[i].empty();
282 prices[j] = canExercise ? exercise[j] : prices[j];
288 QL_TRACE(
"Overridden bad LS decision: NEVER");
296 for (
Size j = 0; j <
n; ++j) {
301 lowerBounds_[i] = *std::min_element(prices.begin(), prices.end());
1-D array used in linear algebra.
bool empty() const
whether the array is empty
Size size() const
dimension of the array
general linear least squares regression
const Array & coefficients() const
Shared handle to an observable.
std::unique_ptr< Array[]> coeff_
const std::vector< Size > timePositions_
std::unique_ptr< Real[]> lowerBounds_
const std::vector< Handle< YieldTermStructure > > forwardTermStructures_
const std::vector< ext::function< Real(Array)> > v_
const ext::shared_ptr< PathPayoff > payoff_
std::vector< PathInfo > paths_
PathInfo transformPath(const MultiPath &path) const
Real operator()(const MultiPath &multiPath) const override
LongstaffSchwartzMultiPathPricer(const ext::shared_ptr< PathPayoff > &payoff, const std::vector< Size > &timePositions, std::vector< Handle< YieldTermStructure > > forwardTermStructure, Array discounts, Size polynomialOrder, LsmBasisSystem::PolynomialType polynomialType)
Matrix used in linear algebra.
Correlated multiple asset paths.
template class providing a null value for a given type.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
general linear least square regression
#define QL_TRACE(message)
output tracing information
QL_INTEGER Integer
integer number
std::size_t Size
size of a container
ext::shared_ptr< QuantLib::Payoff > payoff
std::vector< Array > states
PathInfo(Size numberOfTimes)