Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cappedflooredaveragebmacoupon.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2023 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
21
22#include <ql/cashflows/cashflowvectors.hpp>
23#include <ql/cashflows/couponpricer.hpp>
24#include <ql/cashflows/fixedratecoupon.hpp>
25#include <ql/termstructures/yieldtermstructure.hpp>
26#include <ql/utilities/vectors.hpp>
27
28using namespace QuantLib;
29
30namespace QuantExt {
31
33 LazyObject::alwaysForwardNotifications();
34 underlying_->alwaysForwardNotifications();
35}
36
38 update();
39 underlying_->deepUpdate();
40}
41
43 QL_REQUIRE(underlying_->pricer(), "pricer not set");
44 Rate swapletRate = nakedOption_ ? 0.0 : underlying_->rate();
45 if (floor_ != Null<Real>() || cap_ != Null<Real>())
46 pricer()->initialize(*this);
47 Rate floorletRate = 0.;
48 if (floor_ != Null<Real>())
49 floorletRate = pricer()->floorletRate(effectiveFloor());
50 Rate capletRate = 0.;
51 if (cap_ != Null<Real>())
52 capletRate = (nakedOption_ && floor_ == Null<Real>() ? -1.0 : 1.0) * pricer()->capletRate(effectiveCap());
53 rate_ = swapletRate + floorletRate - capletRate;
54 auto p = QuantLib::ext::dynamic_pointer_cast<CapFlooredAverageBMACouponPricer>(pricer());
55 QL_REQUIRE(p, "CapFlooredAverageBMACoupon::performCalculations(): internal error, could not cast to "
56 "CapFlooredAverageBMACouponPricer");
57 effectiveCapletVolatility_ = p->effectiveCapletVolatility();
58 effectiveFloorletVolatility_ = p->effectiveFloorletVolatility();
59}
60
61Rate CappedFlooredAverageBMACoupon::cap() const { return gearing_ > 0.0 ? cap_ : floor_; }
62
63Rate CappedFlooredAverageBMACoupon::floor() const { return gearing_ > 0.0 ? floor_ : cap_; }
64
66 calculate();
67 return rate_;
68}
69
70Rate CappedFlooredAverageBMACoupon::convexityAdjustment() const { return underlying_->convexityAdjustment(); }
71
73 if (cap_ == Null<Real>())
74 return Null<Real>();
75
76 if (includeSpread()) {
77 // A = \min \left( \max \left( \cdot \frac{\prod (1 + \tau_i(f_i + s)) - 1}{\tau}, F \right), C \right)
78 return (cap_ / gearing() - underlying_->spread());
79 } else {
80 // A = \min \left( \max \left( g \cdot \frac{\prod (1 + \tau_i f_i) - 1}{\tau} + s, F \right), C \right)
81 return (cap_ - underlying_->spread()) / gearing();
82 }
83}
84
86 if (floor_ == Null<Real>())
87 return Null<Real>();
88 if (includeSpread()) {
89 return (floor_ - underlying_->spread());
90 } else {
91 return (floor_ - underlying_->spread()) / gearing();
92 }
93}
94
96 calculate();
98}
99
101 calculate();
103}
104
106 Visitor<CappedFlooredAverageBMACoupon>* v1 = dynamic_cast<Visitor<CappedFlooredAverageBMACoupon>*>(&v);
107 if (v1 != 0)
108 v1->visit(*this);
109 else
110 FloatingRateCoupon::accept(v);
111}
112
113CappedFlooredAverageBMACoupon::CappedFlooredAverageBMACoupon(const ext::shared_ptr<AverageBMACoupon>& underlying,
114 Real cap, Real floor, bool nakedOption, bool includeSpread)
115 : FloatingRateCoupon(underlying->date(), underlying->nominal(), underlying->accrualStartDate(),
116 underlying->accrualEndDate(), underlying->fixingDays(), underlying->index(),
117 underlying->gearing(), underlying->spread(), underlying->referencePeriodStart(),
118 underlying->referencePeriodEnd(), underlying->dayCounter(), false),
119 underlying_(underlying), cap_(cap), floor_(floor), nakedOption_(nakedOption), includeSpread_(includeSpread) {
120 QL_REQUIRE(!includeSpread_ || close_enough(underlying_->gearing(), 1.0),
121 "CappedFlooredAverageBMACoupon: if include spread = true, only a gearing 1.0 is allowed - scale "
122 "the notional in this case instead.");
123 registerWith(underlying_);
124 if (nakedOption_)
125 underlying_->alwaysForwardNotifications();
126}
127
128// capped floored average on coupon pricer base class implementation
129
130CapFlooredAverageBMACouponPricer::CapFlooredAverageBMACouponPricer(const Handle<OptionletVolatilityStructure>& v,
131 const bool effectiveVolatilityInput)
132 : capletVol_(v), effectiveVolatilityInput_(effectiveVolatilityInput) {
133 registerWith(capletVol_);
134}
135
137
139
141
142Handle<OptionletVolatilityStructure> CapFlooredAverageBMACouponPricer::capletVolatility() const { return capletVol_; }
143
144} // namespace QuantExt
Pricer for average overnight indexed coupons.
coupon paying a capped / floored average bma rate
Handle< OptionletVolatilityStructure > capletVolatility() const
Handle< OptionletVolatilityStructure > capletVol_
CapFlooredAverageBMACouponPricer(const Handle< OptionletVolatilityStructure > &v, const bool effectiveVolatilityInput=false)
Real effectiveCapletVolatility() const
effective caplet volatility
ext::shared_ptr< AverageBMACoupon > underlying_
virtual void accept(AcyclicVisitor &) override
Real effectiveFloorletVolatility() const
effective floorlet volatility
CappedFlooredAverageBMACoupon(const ext::shared_ptr< AverageBMACoupon > &underlying, Real cap=Null< Real >(), Real floor=Null< Real >(), bool nakedOption=false, bool includeSpread=false)
Rate effectiveCap() const
effective cap of fixing
Rate effectiveFloor() const
effective floor of fixing
Filter close_enough(const RandomVariable &x, const RandomVariable &y)