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 <ql/pricingengines/lookback/mclookbackengine.hpp>
21#include <algorithm>
22
23namespace QuantLib {
24
25 class LookbackFixedPathPricer : public PathPricer<Path> {
26 public:
27 LookbackFixedPathPricer(Option::Type type,
28 Real strike,
29 DiscountFactor discount);
30 Real operator()(const Path& path) const override;
31
32 private:
33 PlainVanillaPayoff payoff_;
34 DiscountFactor discount_;
35 };
36
37 class LookbackPartialFixedPathPricer : public PathPricer<Path> {
38 public:
39 LookbackPartialFixedPathPricer(Time lookbackStart,
40 Option::Type type,
41 Real strike,
42 DiscountFactor discount);
43 Real operator()(const Path& path) const override;
44
45 private:
46 Time lookbackStart_;
47 PlainVanillaPayoff payoff_;
48 DiscountFactor discount_;
49 };
50
51 class LookbackFloatingPathPricer : public PathPricer<Path> {
52 public:
53 LookbackFloatingPathPricer(Option::Type type,
54 DiscountFactor discount);
55 Real operator()(const Path& path) const override;
56
57 private:
58 FloatingTypePayoff payoff_;
59 DiscountFactor discount_;
60 };
61
62 class LookbackPartialFloatingPathPricer : public PathPricer<Path> {
63 public:
64 LookbackPartialFloatingPathPricer(Time lookbackEnd,
65 Option::Type type,
66 DiscountFactor discount);
67 Real operator()(const Path& path) const override;
68
69 private:
70 Time lookbackEnd_;
71 FloatingTypePayoff payoff_;
72 DiscountFactor discount_;
73 };
74
75 namespace detail {
76
77 ext::shared_ptr<PathPricer<Path> >
78 mc_lookback_path_pricer(
79 const ContinuousFixedLookbackOption::arguments& args,
80 const GeneralizedBlackScholesProcess& process,
81 DiscountFactor discount) {
82 ext::shared_ptr<PlainVanillaPayoff> payoff =
83 ext::dynamic_pointer_cast<PlainVanillaPayoff>(r: args.payoff);
84 QL_REQUIRE(payoff, "non-plain payoff given");
85
86 return ext::shared_ptr<PathPricer<Path> >(
87 new LookbackFixedPathPricer(payoff->optionType(),
88 payoff->strike(),
89 discount));
90 }
91
92 ext::shared_ptr<PathPricer<Path> >
93 mc_lookback_path_pricer(
94 const ContinuousPartialFixedLookbackOption::arguments& args,
95 const GeneralizedBlackScholesProcess& process,
96 DiscountFactor discount) {
97 ext::shared_ptr<PlainVanillaPayoff> payoff =
98 ext::dynamic_pointer_cast<PlainVanillaPayoff>(r: args.payoff);
99 QL_REQUIRE(payoff, "non-plain payoff given");
100
101 Time lookbackStart = process.time(args.lookbackPeriodStart);
102
103 return ext::shared_ptr<PathPricer<Path> >(
104 new LookbackPartialFixedPathPricer(lookbackStart,
105 payoff->optionType(),
106 payoff->strike(),
107 discount));
108 }
109
110 ext::shared_ptr<PathPricer<Path> >
111 mc_lookback_path_pricer(
112 const ContinuousFloatingLookbackOption::arguments& args,
113 const GeneralizedBlackScholesProcess& process,
114 DiscountFactor discount) {
115 ext::shared_ptr<FloatingTypePayoff> payoff =
116 ext::dynamic_pointer_cast<FloatingTypePayoff>(r: args.payoff);
117 QL_REQUIRE(payoff, "non-floating payoff given");
118
119 return ext::shared_ptr<PathPricer<Path> >(
120 new LookbackFloatingPathPricer(payoff->optionType(),
121 discount));
122 }
123
124 ext::shared_ptr<PathPricer<Path> >
125 mc_lookback_path_pricer(
126 const ContinuousPartialFloatingLookbackOption::arguments& args,
127 const GeneralizedBlackScholesProcess& process,
128 DiscountFactor discount) {
129 ext::shared_ptr<FloatingTypePayoff> payoff =
130 ext::dynamic_pointer_cast<FloatingTypePayoff>(r: args.payoff);
131 QL_REQUIRE(payoff, "non-floating payoff given");
132
133 Time lookbackEnd = process.time(args.lookbackPeriodEnd);
134
135 return ext::shared_ptr<PathPricer<Path> >(
136 new LookbackPartialFloatingPathPricer(lookbackEnd,
137 payoff->optionType(),
138 discount));
139 }
140
141 }
142
143
144 LookbackFixedPathPricer::LookbackFixedPathPricer(
145 Option::Type type,
146 Real strike,
147 DiscountFactor discount)
148 : payoff_(type, strike), discount_(discount) {
149 QL_REQUIRE(strike>=0.0,
150 "strike less than zero not allowed");
151 }
152
153 Real LookbackFixedPathPricer::operator()(const Path& path) const {
154 QL_REQUIRE(!path.empty(), "the path cannot be empty");
155
156 Real underlying;
157 switch (payoff_.optionType()) {
158 case Option::Put:
159 underlying = *std::min_element(first: path.begin()+1, last: path.end());
160 break;
161 case Option::Call:
162 underlying = *std::max_element(first: path.begin()+1, last: path.end());
163 break;
164 default:
165 QL_FAIL("unknown option type");
166 }
167
168 return payoff_(underlying) * discount_;
169 }
170
171
172 LookbackPartialFixedPathPricer::LookbackPartialFixedPathPricer(
173 Time lookbackStart,
174 Option::Type type,
175 Real strike,
176 const DiscountFactor discount)
177 : lookbackStart_(lookbackStart), payoff_(type, strike), discount_(discount) {
178 QL_REQUIRE(strike>=0.0,
179 "strike less than zero not allowed");
180 }
181
182 Real LookbackPartialFixedPathPricer::operator()(const Path& path) const {
183 QL_REQUIRE(!path.empty(), "the path cannot be empty");
184
185 const TimeGrid& timeGrid = path.timeGrid();
186 Size startIndex = timeGrid.closestIndex(t: lookbackStart_);
187 Real underlying;
188 switch (payoff_.optionType()) {
189 case Option::Put:
190 underlying = *std::min_element(first: path.begin()+startIndex+1, last: path.end());
191 break;
192 case Option::Call:
193 underlying = *std::max_element(first: path.begin()+startIndex+1, last: path.end());
194 break;
195 default:
196 QL_FAIL("unknown option type");
197 }
198
199 return payoff_(underlying) * discount_;
200 }
201
202
203 LookbackFloatingPathPricer::LookbackFloatingPathPricer(
204 Option::Type type,
205 const DiscountFactor discount)
206 : payoff_(type), discount_(discount) {}
207
208 Real LookbackFloatingPathPricer::operator()(const Path& path) const {
209 QL_REQUIRE(!path.empty(), "the path cannot be empty");
210
211 Real terminalPrice = path.back();
212 Real strike;
213 switch (payoff_.optionType()) {
214 case Option::Call:
215 strike = *std::min_element(first: path.begin()+1, last: path.end());
216 break;
217 case Option::Put:
218 strike = *std::max_element(first: path.begin()+1, last: path.end());
219 break;
220 default:
221 QL_FAIL("unknown option type");
222 }
223
224 return payoff_(terminalPrice, strike) * discount_;
225 }
226
227
228 LookbackPartialFloatingPathPricer::LookbackPartialFloatingPathPricer(
229 Time lookbackEnd,
230 Option::Type type,
231 DiscountFactor discount)
232 : lookbackEnd_(lookbackEnd), payoff_(type), discount_(discount) {}
233
234 Real LookbackPartialFloatingPathPricer::operator()(const Path& path) const {
235 QL_REQUIRE(!path.empty(), "the path cannot be empty");
236
237 const TimeGrid& timeGrid = path.timeGrid();
238 Size endIndex = timeGrid.closestIndex(t: lookbackEnd_);
239 Real terminalPrice = path.back();
240 Real strike;
241
242 switch (payoff_.optionType()) {
243 case Option::Call:
244 strike = *std::min_element(first: path.begin()+1, last: path.begin()+endIndex+1);
245 break;
246 case Option::Put:
247 strike = *std::max_element(first: path.begin()+1, last: path.begin()+endIndex+1);
248 break;
249 default:
250 QL_FAIL("unknown option type");
251 }
252
253 return payoff_(terminalPrice, strike) * discount_;
254 }
255
256}
257

source code of quantlib/ql/pricingengines/lookback/mclookbackengine.cpp