Skip to content

Commit

Permalink
Merge pull request #1218.
Browse files Browse the repository at this point in the history
Remove Forward inheritance by ForwardRateAgreement
  • Loading branch information
lballabio authored Nov 16, 2021
2 parents 13a7f11 + 0df257a commit 223014f
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 99 deletions.
51 changes: 6 additions & 45 deletions Examples/FRA/FRA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ int main(int, char* []) {
euribor3m->businessDayConvention();
Position::Type fraFwdType = Position::Long;
Real fraNotional = 100.0;
const Integer FraTermMonths = 3;
Integer monthsToStart[] = { 1, 2, 3, 6, 9 };

euriborTermStructure.linkTo(fraTermStructure);
Expand All @@ -205,13 +204,9 @@ int main(int, char* []) {
settlementDate,monthsToStart[i],Months,
fraBusinessDayConvention);

Date fraMaturityDate = fraCalendar.advance(
fraValueDate,FraTermMonths,Months,
fraBusinessDayConvention);

Rate fraStrikeRate = threeMonthFraQuote[monthsToStart[i]];

ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
ForwardRateAgreement myFRA(fraValueDate,
fraFwdType,fraStrikeRate,
fraNotional, euribor3m,
discountingTermStructure);
Expand All @@ -228,23 +223,8 @@ int main(int, char* []) {
cout << "FRA market quote: "
<< io::rate(threeMonthFraQuote[monthsToStart[i]])
<< endl;
cout << "FRA spot value: "
<< myFRA.spotValue()
<< endl;
cout << "FRA forward value: "
<< myFRA.forwardValue()
<< endl;
cout << "FRA implied Yield: "
<< myFRA.impliedYield(myFRA.spotValue(),
myFRA.forwardValue(),
settlementDate,
Simple,
fraDayCounter)
<< endl;
cout << "market Zero Rate: "
<< discountingTermStructure->zeroRate(fraMaturityDate,
fraDayCounter,
Simple)
cout << "FRA amount [should be zero]: "
<< myFRA.amount()
<< endl;
cout << "FRA NPV [should be zero]: "
<< myFRA.NPV()
Expand Down Expand Up @@ -283,14 +263,10 @@ int main(int, char* []) {
settlementDate,monthsToStart[i],Months,
fraBusinessDayConvention);

Date fraMaturityDate = fraCalendar.advance(
fraValueDate,FraTermMonths,Months,
fraBusinessDayConvention);

Rate fraStrikeRate =
threeMonthFraQuote[monthsToStart[i]] - BpsShift;

ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
ForwardRateAgreement myFRA(fraValueDate,
fraFwdType, fraStrikeRate,
fraNotional, euribor3m,
discountingTermStructure);
Expand All @@ -307,23 +283,8 @@ int main(int, char* []) {
cout << "FRA market quote: "
<< io::rate(threeMonthFraQuote[monthsToStart[i]])
<< endl;
cout << "FRA spot value: "
<< myFRA.spotValue()
<< endl;
cout << "FRA forward value: "
<< myFRA.forwardValue()
<< endl;
cout << "FRA implied Yield: "
<< myFRA.impliedYield(myFRA.spotValue(),
myFRA.forwardValue(),
settlementDate,
Simple,
fraDayCounter)
<< endl;
cout << "market Zero Rate: "
<< discountingTermStructure->zeroRate(fraMaturityDate,
fraDayCounter,
Simple)
cout << "FRA amount [should be positive]: "
<< myFRA.amount()
<< endl;
cout << "FRA NPV [should be positive]: "
<< myFRA.NPV()
Expand Down
109 changes: 86 additions & 23 deletions ql/instruments/forwardrateagreement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,33 @@
FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <ql/instruments/forwardrateagreement.hpp>
#include <ql/indexes/iborindex.hpp>
#include <ql/event.hpp>
#include <ql/indexes/iborindex.hpp>
#include <ql/instruments/forwardrateagreement.hpp>
#include <utility>

namespace QuantLib {

ForwardRateAgreement::ForwardRateAgreement(
const Date& valueDate,
const Date& maturityDate,
Position::Type type,
Rate strikeForwardRate,
Real notionalAmount,
const ext::shared_ptr<IborIndex>& index,
const Handle<YieldTermStructure>& discountCurve,
bool useIndexedCoupon)
: Forward(index->dayCounter(), index->fixingCalendar(),
index->businessDayConvention(),
index->fixingDays(), ext::shared_ptr<Payoff>(),
valueDate, maturityDate, discountCurve),
fraType_(type), notionalAmount_(notionalAmount), index_(index),
useIndexedCoupon_(useIndexedCoupon) {
QL_DEPRECATED_DISABLE_WARNING

ForwardRateAgreement::ForwardRateAgreement(const Date& valueDate,
const Date& maturityDate,
Position::Type type,
Rate strikeForwardRate,
Real notionalAmount,
const ext::shared_ptr<IborIndex>& index,
Handle<YieldTermStructure> discountCurve,
bool useIndexedCoupon)
: fraType_(type), notionalAmount_(notionalAmount), index_(index),
useIndexedCoupon_(useIndexedCoupon), dayCounter_(index->dayCounter()),
calendar_(index->fixingCalendar()), businessDayConvention_(index->businessDayConvention()),
settlementDays_(index->fixingDays()), valueDate_(valueDate), maturityDate_(maturityDate),
discountCurve_(std::move(discountCurve)) {

maturityDate_ = calendar_.adjust(maturityDate_, businessDayConvention_);

registerWith(Settings::instance().evaluationDate());
registerWith(discountCurve_);

QL_REQUIRE(notionalAmount > 0.0, "notionalAmount must be positive");

Expand All @@ -47,27 +53,39 @@ namespace QuantLib {
Real strike = notionalAmount_ *
strikeForwardRate_.compoundFactor(valueDate_,
maturityDate_);

payoff_ = ext::shared_ptr<Payoff>(new ForwardTypePayoff(fraType_,
strike));
// incomeDiscountCurve_ is irrelevant to an FRA
incomeDiscountCurve_ = discountCurve_;
// income is irrelevant to FRA - set it to zero
underlyingIncome_ = 0.0;

registerWith(index_);
}

ForwardRateAgreement::ForwardRateAgreement(const Date& valueDate,
Position::Type type,
Rate strikeForwardRate,
Real notionalAmount,
const ext::shared_ptr<IborIndex>& index,
Handle<YieldTermStructure> discountCurve)
: ForwardRateAgreement(valueDate, index->maturityDate(valueDate), type, strikeForwardRate,
notionalAmount, index, std::move(discountCurve), true) {}

Date ForwardRateAgreement::settlementDate() const {
return calendar_.advance(Settings::instance().evaluationDate(),
settlementDays_, Days);
}

QL_DEPRECATED_ENABLE_WARNING

Date ForwardRateAgreement::fixingDate() const {
return calendar_.advance(valueDate_,
-static_cast<Integer>(settlementDays_), Days);
return index_->fixingDate(valueDate_);
}

bool ForwardRateAgreement::isExpired() const {
return detail::simple_event(valueDate_).hasOccurred(settlementDate());
return detail::simple_event(valueDate_).hasOccurred();
}

Real ForwardRateAgreement::spotIncome(
Expand All @@ -88,21 +106,34 @@ namespace QuantLib {
discountCurve_->discount(maturityDate_);
}

Real ForwardRateAgreement::amount() const {
calculate();
return amount_;
}

InterestRate ForwardRateAgreement::forwardRate() const {
calculate();
return forwardRate_;
}

void ForwardRateAgreement::setupExpired() const {
Forward::setupExpired();
Instrument::setupExpired();

calculateForwardRate();
}

void ForwardRateAgreement::performCalculations() const {
calculateForwardRate();
calculateAmount();

Handle<YieldTermStructure> discount =
discountCurve_.empty() ? index_->forwardingTermStructure() : discountCurve_;

NPV_ = amount_ * discount->discount(valueDate_);

QL_DEPRECATED_DISABLE_WARNING
underlyingSpotValue_ = spotValue();
underlyingIncome_ = 0.0;
Forward::performCalculations();
QL_DEPRECATED_ENABLE_WARNING
}

void ForwardRateAgreement::calculateForwardRate() const {
Expand All @@ -118,4 +149,36 @@ namespace QuantLib {
index_->dayCounter().yearFraction(valueDate_, maturityDate_),
index_->dayCounter(), Simple, Once);
}

void ForwardRateAgreement::calculateAmount() const {
calculateForwardRate();
Integer sign = fraType_ == Position::Long? 1 : -1;

Rate F = forwardRate_.rate();
Rate K = strikeForwardRate_.rate();
Time T = forwardRate_.dayCounter().yearFraction(valueDate_, maturityDate_);

amount_ = notionalAmount_ * sign * (F - K) * T / (1.0 + F * T);
}

QL_DEPRECATED_DISABLE_WARNING

Real ForwardRateAgreement::forwardValue() const {
calculate();
return (underlyingSpotValue_ - underlyingIncome_) / discountCurve_->discount(maturityDate_);
}

InterestRate ForwardRateAgreement::impliedYield(Real underlyingSpotValue,
Real forwardValue,
Date settlementDate,
Compounding comp,
const DayCounter& dayCounter) {

Time t = dayCounter.yearFraction(settlementDate, maturityDate_);
Real compoundingFactor =
forwardValue / (underlyingSpotValue - spotIncome(incomeDiscountCurve_));
return InterestRate::impliedRate(compoundingFactor, dayCounter, comp, Annual, t);
}

QL_DEPRECATED_ENABLE_WARNING
}
Loading

0 comments on commit 223014f

Please sign in to comment.