| 1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 | |
| 3 | /* |
| 4 | Copyright (C) 2006 Allen Kuo |
| 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/event.hpp> |
| 21 | #include <ql/indexes/iborindex.hpp> |
| 22 | #include <ql/instruments/forwardrateagreement.hpp> |
| 23 | #include <utility> |
| 24 | #include <iostream> |
| 25 | |
| 26 | namespace QuantLib { |
| 27 | |
| 28 | ForwardRateAgreement::ForwardRateAgreement(const Date& valueDate, |
| 29 | const Date& maturityDate, |
| 30 | Position::Type type, |
| 31 | Rate strikeForwardRate, |
| 32 | Real notionalAmount, |
| 33 | const ext::shared_ptr<IborIndex>& index, |
| 34 | Handle<YieldTermStructure> discountCurve, |
| 35 | bool useIndexedCoupon) |
| 36 | : ForwardRateAgreement(index, valueDate, maturityDate, type, strikeForwardRate, |
| 37 | notionalAmount, std::move(discountCurve)) { |
| 38 | useIndexedCoupon_ = useIndexedCoupon; |
| 39 | } |
| 40 | |
| 41 | ForwardRateAgreement::ForwardRateAgreement(const Date& valueDate, |
| 42 | Position::Type type, |
| 43 | Rate strikeForwardRate, |
| 44 | Real notionalAmount, |
| 45 | const ext::shared_ptr<IborIndex>& index, |
| 46 | Handle<YieldTermStructure> discountCurve) |
| 47 | : ForwardRateAgreement(index, valueDate, type, strikeForwardRate, |
| 48 | notionalAmount, std::move(discountCurve)) {} |
| 49 | |
| 50 | ForwardRateAgreement::ForwardRateAgreement(const ext::shared_ptr<IborIndex>& index, |
| 51 | const Date& valueDate, |
| 52 | Position::Type type, |
| 53 | Rate strikeForwardRate, |
| 54 | Real notionalAmount, |
| 55 | Handle<YieldTermStructure> discountCurve) |
| 56 | : ForwardRateAgreement(index, valueDate, index->maturityDate(valueDate), type, |
| 57 | strikeForwardRate, notionalAmount, std::move(discountCurve)) { |
| 58 | useIndexedCoupon_ = true; |
| 59 | } |
| 60 | |
| 61 | ForwardRateAgreement::ForwardRateAgreement(const ext::shared_ptr<IborIndex>& index, |
| 62 | const Date& valueDate, |
| 63 | const Date& maturityDate, |
| 64 | Position::Type type, |
| 65 | Rate strikeForwardRate, |
| 66 | Real notionalAmount, |
| 67 | Handle<YieldTermStructure> discountCurve) |
| 68 | : fraType_(type), notionalAmount_(notionalAmount), index_(index), |
| 69 | useIndexedCoupon_(false), dayCounter_(index->dayCounter()), |
| 70 | calendar_(index->fixingCalendar()), businessDayConvention_(index->businessDayConvention()), |
| 71 | valueDate_(valueDate), maturityDate_(maturityDate), |
| 72 | discountCurve_(std::move(discountCurve)) { |
| 73 | |
| 74 | maturityDate_ = calendar_.adjust(maturityDate_, convention: businessDayConvention_); |
| 75 | |
| 76 | registerWith(h: Settings::instance().evaluationDate()); |
| 77 | registerWith(h: discountCurve_); |
| 78 | |
| 79 | QL_REQUIRE(notionalAmount > 0.0, "notionalAmount must be positive" ); |
| 80 | QL_REQUIRE(valueDate_ < maturityDate_, "valueDate must be earlier than maturityDate" ); |
| 81 | |
| 82 | strikeForwardRate_ = InterestRate(strikeForwardRate, |
| 83 | index->dayCounter(), |
| 84 | Simple, Once); |
| 85 | registerWith(h: index_); |
| 86 | } |
| 87 | |
| 88 | Date ForwardRateAgreement::fixingDate() const { |
| 89 | return index_->fixingDate(valueDate: valueDate_); |
| 90 | } |
| 91 | |
| 92 | bool ForwardRateAgreement::isExpired() const { |
| 93 | return detail::simple_event(valueDate_).hasOccurred(); |
| 94 | } |
| 95 | |
| 96 | Real ForwardRateAgreement::amount() const { |
| 97 | calculate(); |
| 98 | return amount_; |
| 99 | } |
| 100 | |
| 101 | InterestRate ForwardRateAgreement::forwardRate() const { |
| 102 | calculate(); |
| 103 | return forwardRate_; |
| 104 | } |
| 105 | |
| 106 | void ForwardRateAgreement::setupExpired() const { |
| 107 | Instrument::setupExpired(); |
| 108 | calculateForwardRate(); |
| 109 | } |
| 110 | |
| 111 | void ForwardRateAgreement::performCalculations() const { |
| 112 | calculateAmount(); |
| 113 | Handle<YieldTermStructure> discount = |
| 114 | discountCurve_.empty() ? index_->forwardingTermStructure() : discountCurve_; |
| 115 | NPV_ = amount_ * discount->discount(d: valueDate_); |
| 116 | } |
| 117 | |
| 118 | void ForwardRateAgreement::calculateForwardRate() const { |
| 119 | if (useIndexedCoupon_) |
| 120 | forwardRate_ = |
| 121 | InterestRate(index_->fixing(fixingDate: fixingDate()), index_->dayCounter(), Simple, Once); |
| 122 | else |
| 123 | // par coupon approximation |
| 124 | forwardRate_ = |
| 125 | InterestRate((index_->forwardingTermStructure()->discount(d: valueDate_) / |
| 126 | index_->forwardingTermStructure()->discount(d: maturityDate_) - |
| 127 | 1.0) / |
| 128 | index_->dayCounter().yearFraction(d1: valueDate_, d2: maturityDate_), |
| 129 | index_->dayCounter(), Simple, Once); |
| 130 | } |
| 131 | |
| 132 | void ForwardRateAgreement::calculateAmount() const { |
| 133 | calculateForwardRate(); |
| 134 | Integer sign = fraType_ == Position::Long? 1 : -1; |
| 135 | Rate F = forwardRate_.rate(); |
| 136 | Rate K = strikeForwardRate_.rate(); |
| 137 | Time T = forwardRate_.dayCounter().yearFraction(d1: valueDate_, d2: maturityDate_); |
| 138 | amount_ = notionalAmount_ * sign * (F - K) * T / (1.0 + F * T); |
| 139 | } |
| 140 | |
| 141 | } |
| 142 | |