1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb 5 Copyright (C) 2013 Peter Caspers 6 7 This file is part of QuantLib, a free-software/open-source library 8 for financial quantitative analysts and developers - http://quantlib.org/ 9 10 QuantLib is free software: you can redistribute it and/or modify it 11 under the terms of the QuantLib license. You should have received a 12 copy of the license along with this program; if not, please email 13 <quantlib-dev@lists.sf.net>. The license is also available online at 14 <http://quantlib.org/license.shtml>. 15 16 This program is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the license for more details. 19 */ 20 21 #include <ql/pricingengines/swaption/gaussian1djamshidianswaptionengine.hpp> 22 #include <ql/math/solvers1d/brent.hpp> 23 24 namespace QuantLib { 25 26 class Gaussian1dJamshidianSwaptionEngine::rStarFinder { 27 public: rStarFinder(const ext::shared_ptr<Gaussian1dModel> & model,Real nominal,const Date & maturityDate,const Date & valueDate,const std::vector<Date> & fixedPayDates,const std::vector<Real> & amounts,const Size startIndex)28 rStarFinder(const ext::shared_ptr<Gaussian1dModel> &model, 29 Real nominal, const Date &maturityDate, 30 const Date &valueDate, 31 const std::vector<Date> &fixedPayDates, 32 const std::vector<Real> &amounts, const Size startIndex) 33 : strike_(nominal), maturityDate_(maturityDate), 34 valueDate_(valueDate), startIndex_(startIndex), 35 times_(fixedPayDates), amounts_(amounts), model_(model) {} 36 operator ()(Rate y) const37 Real operator()(Rate y) const { 38 Real value = strike_; 39 Size size = times_.size(); 40 for (Size i = startIndex_; i < size; i++) { 41 Real dbValue = model_->zerobond(times_[i], maturityDate_, y) / 42 model_->zerobond(valueDate_, maturityDate_, y); 43 value -= amounts_[i] * dbValue; 44 } 45 return value; 46 } 47 48 private: 49 Real strike_; 50 Date maturityDate_, valueDate_; 51 Size startIndex_; 52 std::vector<Date> times_; 53 const std::vector<Real> &amounts_; 54 const ext::shared_ptr<Gaussian1dModel> &model_; 55 }; 56 calculate() const57 void Gaussian1dJamshidianSwaptionEngine::calculate() const { 58 59 QL_REQUIRE(arguments_.settlementMethod != Settlement::ParYieldCurve, 60 "cash settled (ParYieldCurve) swaptions not priced with " 61 "Gaussian1dJamshidianSwaptionEngine"); 62 63 QL_REQUIRE(arguments_.exercise->type() == Exercise::European, 64 "cannot use the Jamshidian decomposition " 65 "on exotic swaptions"); 66 67 QL_REQUIRE(arguments_.swap->spread() == 0.0, 68 "non zero spread (" << arguments_.swap->spread() 69 << ") not allowed"); // PC 70 71 Date referenceDate; 72 DayCounter dayCounter; 73 74 referenceDate = model_->termStructure()->referenceDate(); 75 dayCounter = model_->termStructure()->dayCounter(); 76 77 std::vector<Real> amounts(arguments_.fixedCoupons); 78 amounts.back() += arguments_.nominal; 79 80 Size startIndex = std::upper_bound(arguments_.fixedResetDates.begin(), 81 arguments_.fixedResetDates.end(), 82 arguments_.exercise->date(0) - 1) - 83 arguments_.fixedResetDates.begin(); 84 // only consider coupons with start date >= exercise dates 85 86 rStarFinder finder(*model_, arguments_.nominal, 87 arguments_.exercise->date(0), 88 arguments_.fixedResetDates[startIndex], 89 arguments_.fixedPayDates, amounts, startIndex); 90 Brent s1d; 91 Rate minStrike = -8.0; 92 Rate maxStrike = 8.0; 93 s1d.setMaxEvaluations(10000); 94 s1d.setLowerBound(minStrike); 95 s1d.setUpperBound(maxStrike); 96 Rate rStar = s1d.solve(finder, 1e-8, 0.00, minStrike, 97 maxStrike); // this is actually yStar 98 99 Option::Type w = 100 arguments_.type == VanillaSwap::Payer ? Option::Put : Option::Call; 101 Size size = arguments_.fixedCoupons.size(); 102 103 Real value = 0.0; 104 for (Size i = startIndex; i < size; i++) { 105 // Real fixedPayTime = 106 // dayCounter.yearFraction(referenceDate,arguments_.fixedPayDates[i]); 107 Real strike = 108 model_->zerobond(arguments_.fixedPayDates[i], 109 arguments_.exercise->date(0), rStar) / 110 model_->zerobond(arguments_.fixedResetDates[startIndex], 111 arguments_.exercise->date(0), rStar); 112 Real dboValue = 113 model_->zerobondOption(w, arguments_.exercise->date(0), 114 arguments_.fixedResetDates[startIndex], 115 arguments_.fixedPayDates[i], strike); 116 value += amounts[i] * dboValue; 117 } 118 results_.value = value; 119 } 120 } 121