| 1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 | |
| 3 | /* |
| 4 | Copyright (C) 2006, 2007 Ferdinando Ametrano |
| 5 | Copyright (C) 2007 StatPro Italia srl |
| 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/instruments/makecapfloor.hpp> |
| 22 | #include <ql/cashflows/cashflows.hpp> |
| 23 | #include <ql/pricingengines/capfloor/blackcapfloorengine.hpp> |
| 24 | |
| 25 | namespace QuantLib { |
| 26 | |
| 27 | MakeCapFloor::MakeCapFloor(CapFloor::Type capFloorType, |
| 28 | const Period& tenor, |
| 29 | const ext::shared_ptr<IborIndex>& iborIndex, |
| 30 | Rate strike, |
| 31 | const Period& forwardStart) |
| 32 | : capFloorType_(capFloorType), strike_(strike), firstCapletExcluded_(forwardStart == 0 * Days), |
| 33 | // setting the fixed leg tenor avoids that MakeVanillaSwap throws |
| 34 | // because of an unknown fixed leg default tenor for a currency, |
| 35 | // notice that only the floating leg of the swap is used anyway |
| 36 | makeVanillaSwap_(MakeVanillaSwap(tenor, iborIndex, 0.0, forwardStart) |
| 37 | .withFixedLegTenor(t: 1 * Years) |
| 38 | .withFixedLegDayCount(dc: Actual365Fixed())) {} |
| 39 | |
| 40 | MakeCapFloor::operator CapFloor() const { |
| 41 | ext::shared_ptr<CapFloor> capfloor = *this; |
| 42 | return *capfloor; |
| 43 | } |
| 44 | |
| 45 | MakeCapFloor::operator ext::shared_ptr<CapFloor>() const { |
| 46 | |
| 47 | VanillaSwap swap = makeVanillaSwap_; |
| 48 | |
| 49 | Leg leg = swap.floatingLeg(); |
| 50 | if (firstCapletExcluded_) |
| 51 | leg.erase(position: leg.begin()); |
| 52 | |
| 53 | // only leaves the last coupon |
| 54 | if (asOptionlet_ && leg.size() > 1) { |
| 55 | auto end = leg.end(); // Sun Studio needs an lvalue |
| 56 | leg.erase(first: leg.begin(), last: --end); |
| 57 | } |
| 58 | |
| 59 | std::vector<Rate> strikeVector(1, strike_); |
| 60 | if (strike_ == Null<Rate>()) { |
| 61 | |
| 62 | // temporary patch... |
| 63 | // should be fixed for every CapFloor::Engine |
| 64 | ext::shared_ptr<BlackCapFloorEngine> temp = |
| 65 | ext::dynamic_pointer_cast<BlackCapFloorEngine>(r: engine_); |
| 66 | QL_REQUIRE(temp, |
| 67 | "cannot calculate ATM without a BlackCapFloorEngine" ); |
| 68 | Handle<YieldTermStructure> discountCurve = temp->termStructure(); |
| 69 | strikeVector[0] = CashFlows::atmRate(leg, |
| 70 | discountCurve: **discountCurve, |
| 71 | includeSettlementDateFlows: false, |
| 72 | settlementDate: discountCurve->referenceDate()); |
| 73 | } |
| 74 | |
| 75 | ext::shared_ptr<CapFloor> capFloor(new |
| 76 | CapFloor(capFloorType_, leg, strikeVector)); |
| 77 | capFloor->setPricingEngine(engine_); |
| 78 | return capFloor; |
| 79 | } |
| 80 | |
| 81 | MakeCapFloor& MakeCapFloor::withNominal(Real n) { |
| 82 | makeVanillaSwap_.withNominal(n); |
| 83 | return *this; |
| 84 | } |
| 85 | |
| 86 | MakeCapFloor& MakeCapFloor::withEffectiveDate(const Date& effectiveDate, |
| 87 | bool firstCapletExcluded) { |
| 88 | makeVanillaSwap_.withEffectiveDate(effectiveDate); |
| 89 | firstCapletExcluded_ = firstCapletExcluded; |
| 90 | return *this; |
| 91 | } |
| 92 | |
| 93 | MakeCapFloor& MakeCapFloor::withTenor(const Period& t) { |
| 94 | makeVanillaSwap_.withFloatingLegTenor(t); |
| 95 | return *this; |
| 96 | } |
| 97 | |
| 98 | |
| 99 | MakeCapFloor& MakeCapFloor::withCalendar(const Calendar& cal) { |
| 100 | makeVanillaSwap_.withFloatingLegCalendar(cal); |
| 101 | return *this; |
| 102 | } |
| 103 | |
| 104 | |
| 105 | MakeCapFloor& MakeCapFloor::withConvention(BusinessDayConvention bdc) { |
| 106 | makeVanillaSwap_.withFloatingLegConvention(bdc); |
| 107 | return *this; |
| 108 | } |
| 109 | |
| 110 | |
| 111 | MakeCapFloor& |
| 112 | MakeCapFloor::withTerminationDateConvention(BusinessDayConvention bdc) { |
| 113 | makeVanillaSwap_.withFloatingLegTerminationDateConvention(bdc); |
| 114 | return *this; |
| 115 | } |
| 116 | |
| 117 | |
| 118 | MakeCapFloor& MakeCapFloor::withRule(DateGeneration::Rule r) { |
| 119 | makeVanillaSwap_.withFloatingLegRule(r); |
| 120 | return *this; |
| 121 | } |
| 122 | |
| 123 | MakeCapFloor& MakeCapFloor::withEndOfMonth(bool flag) { |
| 124 | makeVanillaSwap_.withFloatingLegEndOfMonth(flag); |
| 125 | return *this; |
| 126 | } |
| 127 | |
| 128 | |
| 129 | MakeCapFloor& MakeCapFloor::withFirstDate(const Date& d) { |
| 130 | makeVanillaSwap_.withFloatingLegFirstDate(d); |
| 131 | return *this; |
| 132 | } |
| 133 | |
| 134 | MakeCapFloor& MakeCapFloor::withNextToLastDate(const Date& d) { |
| 135 | makeVanillaSwap_.withFloatingLegNextToLastDate(d); |
| 136 | return *this; |
| 137 | } |
| 138 | |
| 139 | MakeCapFloor& MakeCapFloor::withDayCount(const DayCounter& dc) { |
| 140 | makeVanillaSwap_.withFloatingLegDayCount(dc); |
| 141 | return *this; |
| 142 | } |
| 143 | |
| 144 | MakeCapFloor& MakeCapFloor::asOptionlet(bool b) { |
| 145 | asOptionlet_ = b; |
| 146 | return *this; |
| 147 | } |
| 148 | |
| 149 | MakeCapFloor& MakeCapFloor::withPricingEngine( |
| 150 | const ext::shared_ptr<PricingEngine>& engine) { |
| 151 | engine_ = engine; |
| 152 | return *this; |
| 153 | } |
| 154 | |
| 155 | } |
| 156 | |
| 157 | |