/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2002, 2003 Ferdinando Ametrano This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email . The license is also available online at . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #include #include #include #include namespace QuantLib { namespace { class CliquetOptionPathPricer : public PathPricer { public: CliquetOptionPathPricer( Option::Type type, Real moneyness, Real accruedCoupon, Real lastFixing, Real localCap, Real localFloor, Real globalCap, Real globalFloor, const std::vector& discounts, bool redemptionOnly) : type_(type), moneyness_(moneyness), accruedCoupon_(accruedCoupon), lastFixing_(lastFixing), localCap_(localCap), localFloor_(localFloor), globalCap_(globalCap), globalFloor_(globalFloor), discounts_(discounts), redemptionOnly_(redemptionOnly) { QL_REQUIRE(moneyness>0.0, "moneyness less/equal zero not allowed"); if (accruedCoupon == Null()) accruedCoupon_ = 0.0; if (localCap == Null()) localCap_ = QL_MAX_REAL; if (localFloor == Null()) localFloor_ = 0.0; if (globalCap == Null()) globalCap_ = QL_MAX_REAL; if (globalFloor == Null()) globalFloor_ = 0.0; } Real operator()(const Path& path) const { Size n = path.length(); QL_REQUIRE(n>1, "the path cannot be empty"); QL_REQUIRE(n==discounts_.size(), "discounts/options mismatch"); Real result, lastFixing, underlying, payoff; // start the simulation lastFixing = lastFixing_; underlying = path.front(); if (redemptionOnly_) result = accruedCoupon_; else result = 0.0; // step by step using the discretization of the path for (Size i=1; i()) { payoff = PlainVanillaPayoff(type_, moneyness_*lastFixing) (underlying) / lastFixing; payoff = std::max(payoff, localFloor_); payoff = std::min(payoff, localCap_); if (redemptionOnly_) result += payoff; else result += payoff * discounts_[i]; } // new fixing lastFixing = underlying; } if (redemptionOnly_) { result = std::max(result, globalFloor_); result = std::min(result, globalCap_); } if (redemptionOnly_) { return discounts_.back()*result; } else { return result; } } private: Option::Type type_; Real moneyness_, accruedCoupon_; Real lastFixing_, localCap_, localFloor_, globalCap_, globalFloor_; std::vector discounts_; bool redemptionOnly_; }; } McCliquetOption::McCliquetOption( Option::Type type, Real underlying, Real moneyness, const Handle& dividendYield, const Handle& riskFreeRate, const Handle& volatility, const std::vector