QuantLib
A free/open-source library for quantitative finance
Fully annotated sources - version 1.22
blackswaptionengine.hpp
1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2007 Ferdinando Ametrano
5  Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb
6  Copyright (C) 2006 StatPro Italia srl
7  Copyright (C) 2015, 2016, 2017 Peter Caspers
8  Copyright (C) 2017 Paul Giltinan
9  Copyright (C) 2017 Werner Kuerzinger
10  Copyright (C) 2020 Marcin Rybacki
11 
12  This file is part of QuantLib, a free-software/open-source library
13  for financial quantitative analysts and developers - http://quantlib.org/
14 
15  QuantLib is free software: you can redistribute it and/or modify it
16  under the terms of the QuantLib license. You should have received a
17  copy of the license along with this program; if not, please email
18  <quantlib-dev@lists.sf.net>. The license is also available online at
19  <http://quantlib.org/license.shtml>.
20 
21  This program is distributed in the hope that it will be useful, but WITHOUT
22  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23  FOR A PARTICULAR PURPOSE. See the license for more details.
24 */
25 
30 #ifndef quantlib_pricers_black_swaption_hpp
31 #define quantlib_pricers_black_swaption_hpp
32 
33 #include <ql/cashflows/cashflows.hpp>
34 #include <ql/cashflows/fixedratecoupon.hpp>
35 #include <ql/exercise.hpp>
36 #include <ql/indexes/iborindex.hpp>
37 #include <ql/instruments/swaption.hpp>
38 #include <ql/pricingengines/blackformula.hpp>
39 #include <ql/pricingengines/swap/discountingswapengine.hpp>
40 #include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
41 #include <ql/termstructures/volatility/swaption/swaptionvolstructure.hpp>
42 #include <ql/time/calendars/nullcalendar.hpp>
43 #include <utility>
44 
45 namespace QuantLib {
46 
47  class Quote;
48 
49  namespace detail {
50 
53  template<class Spec>
55  public:
58  Volatility vol,
59  const DayCounter& dc = Actual365Fixed(),
60  Real displacement = 0.0,
63  const Handle<Quote>& vol,
64  const DayCounter& dc = Actual365Fixed(),
65  Real displacement = 0.0,
70  void calculate() const override;
73 
74  private:
78  };
79 
80  // shifted lognormal type engine
81  struct Black76Spec {
83  Real value(const Option::Type type, const Real strike,
84  const Real atmForward, const Real stdDev, const Real annuity,
85  const Real displacement) {
86  return blackFormula(type, strike, atmForward, stdDev, annuity,
87  displacement);
88  }
89  Real vega(const Real strike, const Real atmForward, const Real stdDev,
90  const Real exerciseTime, const Real annuity,
91  const Real displacement) {
92  return std::sqrt(exerciseTime) *
93  blackFormulaStdDevDerivative(strike, atmForward, stdDev,
94  annuity, displacement);
95  }
96  Real delta(const Option::Type type, const Real strike,
97  const Real atmForward, const Real stdDev, const Real annuity,
98  const Real displacement) {
99  return blackFormulaForwardDerivative(type, strike, atmForward, stdDev,
100  annuity, displacement);
101  }
102  };
103 
104  // normal type engine
105  struct BachelierSpec {
106  static const VolatilityType type = Normal;
107  Real value(const Option::Type type, const Real strike,
108  const Real atmForward, const Real stdDev, const Real annuity,
109  const Real) {
110  return bachelierBlackFormula(type, strike, atmForward, stdDev,
111  annuity);
112  }
113  Real vega(const Real strike, const Real atmForward, const Real stdDev,
114  const Real exerciseTime, const Real annuity, const Real) {
115  return std::sqrt(exerciseTime) *
117  strike, atmForward, stdDev, annuity);
118  }
119  Real delta(const Option::Type type, const Real strike,
120  const Real atmForward, const Real stdDev, const Real annuity,
121  const Real) {
123  type, strike, atmForward, stdDev, annuity);
124  }
125  };
126 
127  } // namespace detail
128 
130 
137  : public detail::BlackStyleSwaptionEngine<detail::Black76Spec> {
138  public:
139  BlackSwaptionEngine(const Handle<YieldTermStructure>& discountCurve,
140  Volatility vol,
141  const DayCounter& dc = Actual365Fixed(),
142  Real displacement = 0.0,
144  BlackSwaptionEngine(const Handle<YieldTermStructure>& discountCurve,
145  const Handle<Quote>& vol,
146  const DayCounter& dc = Actual365Fixed(),
147  Real displacement = 0.0,
149  BlackSwaptionEngine(const Handle<YieldTermStructure>& discountCurve,
152  };
153 
155 
162  : public detail::BlackStyleSwaptionEngine<detail::BachelierSpec> {
163  public:
165  Volatility vol,
166  const DayCounter& dc = Actual365Fixed(),
169  const Handle<Quote>& vol,
170  const DayCounter& dc = Actual365Fixed(),
175  };
176 
177  // implementation
178 
179  namespace detail {
180 
181  template <class Spec>
183  Handle<YieldTermStructure> discountCurve,
184  Volatility vol,
185  const DayCounter& dc,
186  Real displacement,
187  CashAnnuityModel model)
188  : discountCurve_(std::move(discountCurve)),
190  0, NullCalendar(), Following, vol, dc, Spec().type, displacement))),
191  model_(model) {
193  }
194 
195  template <class Spec>
197  Handle<YieldTermStructure> discountCurve,
198  const Handle<Quote>& vol,
199  const DayCounter& dc,
200  Real displacement,
201  CashAnnuityModel model)
202  : discountCurve_(std::move(discountCurve)),
204  0, NullCalendar(), Following, vol, dc, Spec().type, displacement))),
205  model_(model) {
208  }
209 
210  template <class Spec>
212  Handle<YieldTermStructure> discountCurve,
214  CashAnnuityModel model)
215  : discountCurve_(std::move(discountCurve)), vol_(std::move(volatility)), model_(model) {
218  }
219 
220  template<class Spec>
222  static const Spread basisPoint = 1.0e-4;
223 
224  Date exerciseDate = arguments_.exercise->date(0);
225 
226  // the part of the swap preceding exerciseDate should be truncated
227  // to avoid taking into account unwanted cashflows
228  // for the moment we add a check avoiding this situation
229  VanillaSwap swap = *arguments_.swap;
230  const Leg& fixedLeg = swap.fixedLeg();
231  ext::shared_ptr<FixedRateCoupon> firstCoupon =
232  ext::dynamic_pointer_cast<FixedRateCoupon>(fixedLeg[0]);
233  QL_REQUIRE(firstCoupon->accrualStartDate() >= exerciseDate,
234  "swap start (" << firstCoupon->accrualStartDate() << ") before exercise date ("
235  << exerciseDate << ") not supported in Black swaption engine");
236 
237  Rate strike = swap.fixedRate();
238 
239  // using the discounting curve
240  // swap.iborIndex() might be using a different forwarding curve
241  swap.setPricingEngine(ext::shared_ptr<PricingEngine>(new
242  DiscountingSwapEngine(discountCurve_, false)));
243  Rate atmForward = swap.fairRate();
244 
245  // Volatilities are quoted for zero-spreaded swaps.
246  // Therefore, any spread on the floating leg must be removed
247  // with a corresponding correction on the fixed leg.
248  if (swap.spread()!=0.0) {
249  Spread correction = swap.spread() *
250  std::fabs(swap.floatingLegBPS()/swap.fixedLegBPS());
251  strike -= correction;
252  atmForward -= correction;
253  results_.additionalResults["spreadCorrection"] = correction;
254  } else {
255  results_.additionalResults["spreadCorrection"] = 0.0;
256  }
257  results_.additionalResults["strike"] = strike;
258  results_.additionalResults["atmForward"] = atmForward;
259 
260  // using the discounting curve
261  swap.setPricingEngine(ext::shared_ptr<PricingEngine>(
262  new DiscountingSwapEngine(discountCurve_, false)));
263  Real annuity;
264  if (arguments_.settlementType == Settlement::Physical ||
265  (arguments_.settlementType == Settlement::Cash &&
266  arguments_.settlementMethod ==
268  annuity = std::fabs(swap.fixedLegBPS()) / basisPoint;
269  } else if (arguments_.settlementType == Settlement::Cash &&
270  arguments_.settlementMethod == Settlement::ParYieldCurve) {
271  DayCounter dayCount = firstCoupon->dayCounter();
272  // we assume that the cash settlement date is equal
273  // to the swap start date
274  Date discountDate = model_ == DiscountCurve
275  ? firstCoupon->accrualStartDate()
276  : discountCurve_->referenceDate();
277  Real fixedLegCashBPS = CashFlows::bps(
278  fixedLeg,
279  InterestRate(atmForward, dayCount, Compounded, Annual), false,
280  discountDate);
281  annuity = std::fabs(fixedLegCashBPS / basisPoint) *
282  discountCurve_->discount(discountDate);
283  } else {
284  QL_FAIL("invalid (settlementType, settlementMethod) pair");
285  }
286  results_.additionalResults["annuity"] = annuity;
287 
288  Time swapLength = vol_->swapLength(swap.floatingSchedule().dates().front(),
289  swap.floatingSchedule().dates().back());
290 
291  // swapLength is rounded to whole months. To ensure we can read a variance
292  // and a shift from vol_ we floor swapLength at 1/12 here therefore.
293  swapLength = std::max(swapLength, 1.0 / 12.0);
294  results_.additionalResults["swapLength"] = swapLength;
295 
296  Real variance = vol_->blackVariance(exerciseDate, swapLength, strike);
297 
298  Real displacement =
299  vol_->volatilityType() == ShiftedLognormal ?
300  vol_->shift(exerciseDate, swapLength) : 0.0;
301 
302  Real stdDev = std::sqrt(variance);
303  results_.additionalResults["stdDev"] = stdDev;
304  Option::Type w = (arguments_.type==VanillaSwap::Payer) ?
306  results_.value = Spec().value(w, strike, atmForward, stdDev, annuity, displacement);
307 
308  Time exerciseTime = vol_->timeFromReference(exerciseDate);
309  results_.additionalResults["vega"] = Spec().vega(
310  strike, atmForward, stdDev, exerciseTime, annuity, displacement);
311  results_.additionalResults["delta"] = Spec().delta(
312  w, strike, atmForward, stdDev, annuity, displacement);
313  results_.additionalResults["timeToExpiry"] = exerciseTime;
314  results_.additionalResults["impliedVolatility"] = stdDev / std::sqrt(exerciseTime);
315  }
316 
317  } // namespace detail
318 
319 }
320 
321 #endif
QuantLib::blackFormula
Real blackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)
Definition: blackformula.cpp:66
QuantLib::Handle< YieldTermStructure >
QuantLib::swap
void swap(Array &v, Array &w)
Definition: array.hpp:680
QuantLib::VanillaSwap::Payer
@ Payer
Definition: vanillaswap.hpp:67
QuantLib::Option::Put
@ Put
Definition: option.hpp:39
QuantLib::NullCalendar
Calendar for reproducing theoretical calculations.
Definition: nullcalendar.hpp:38
QuantLib::SwaptionVolatilityStructure
Swaption-volatility structure
Definition: swaptionvolstructure.hpp:41
QuantLib::detail::BachelierSpec::delta
Real delta(const Option::Type type, const Real strike, const Real atmForward, const Real stdDev, const Real annuity, const Real)
Definition: blackswaptionengine.hpp:119
QuantLib::detail::BlackStyleSwaptionEngine::SwapRate
@ SwapRate
Definition: blackswaptionengine.hpp:56
QuantLib::BlackSwaptionEngine::BlackSwaptionEngine
BlackSwaptionEngine(const Handle< YieldTermStructure > &discountCurve, Volatility vol, const DayCounter &dc=Actual365Fixed(), Real displacement=0.0, CashAnnuityModel model=DiscountCurve)
Definition: blackswaptionengine.cpp:30
QuantLib::Volatility
Real Volatility
volatility
Definition: types.hpp:78
QuantLib::detail::BachelierSpec::vega
Real vega(const Real strike, const Real atmForward, const Real stdDev, const Real exerciseTime, const Real annuity, const Real)
Definition: blackswaptionengine.hpp:113
QuantLib::Observer::registerWith
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:211
QuantLib::BlackSwaptionEngine
Shifted Lognormal Black-formula swaption engine.
Definition: blackswaptionengine.hpp:137
QuantLib::detail::Black76Spec::vega
Real vega(const Real strike, const Real atmForward, const Real stdDev, const Real exerciseTime, const Real annuity, const Real displacement)
Definition: blackswaptionengine.hpp:89
QuantLib::Spread
Real Spread
spreads on interest rates
Definition: types.hpp:74
QuantLib::InterpolatedDiscountCurve
YieldTermStructure based on interpolation of discount factors.
Definition: discountcurve.hpp:43
QuantLib::detail::Black76Spec::value
Real value(const Option::Type type, const Real strike, const Real atmForward, const Real stdDev, const Real annuity, const Real displacement)
Definition: blackswaptionengine.hpp:83
QuantLib::Actual365Fixed
Actual/365 (Fixed) day count convention.
Definition: actual365fixed.hpp:45
QuantLib::Leg
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:72
QuantLib::detail::BlackStyleSwaptionEngine::discountCurve_
Handle< YieldTermStructure > discountCurve_
Definition: blackswaptionengine.hpp:75
QuantLib::blackFormulaForwardDerivative
Real blackFormulaForwardDerivative(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)
Definition: blackformula.cpp:114
QuantLib::Option::Type
Type
Definition: option.hpp:39
QuantLib::detail::BlackStyleSwaptionEngine::vol_
Handle< SwaptionVolatilityStructure > vol_
Definition: blackswaptionengine.hpp:76
QuantLib::Following
@ Following
Definition: businessdayconvention.hpp:43
QuantLib::detail::BachelierSpec::value
Real value(const Option::Type type, const Real strike, const Real atmForward, const Real stdDev, const Real annuity, const Real)
Definition: blackswaptionengine.hpp:107
QuantLib::Normal
@ Normal
Definition: volatilitytype.hpp:32
QuantLib::detail::BlackStyleSwaptionEngine::BlackStyleSwaptionEngine
BlackStyleSwaptionEngine(Handle< YieldTermStructure > discountCurve, Handle< SwaptionVolatilityStructure > vol, CashAnnuityModel model=DiscountCurve)
Definition: blackswaptionengine.hpp:211
QuantLib::BachelierSwaptionEngine::BachelierSwaptionEngine
BachelierSwaptionEngine(const Handle< YieldTermStructure > &discountCurve, Volatility vol, const DayCounter &dc=Actual365Fixed(), CashAnnuityModel model=DiscountCurve)
Definition: blackswaptionengine.cpp:58
QuantLib::Settlement::ParYieldCurve
@ ParYieldCurve
Definition: swaption.hpp:46
QuantLib::bachelierBlackFormula
Real bachelierBlackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount)
Definition: blackformula.cpp:700
QuantLib::CashFlows::bps
static Real bps(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Basis-point sensitivity of the cash flows.
Definition: cashflows.cpp:450
QuantLib::io::volatility
detail::percent_holder volatility(Volatility)
output volatilities as percentages
Definition: dataformatters.hpp:133
QuantLib::detail::BlackStyleSwaptionEngine::calculate
void calculate() const override
Definition: blackswaptionengine.hpp:221
QuantLib::Annual
@ Annual
once a year
Definition: frequency.hpp:39
QuantLib::bachelierBlackFormulaStdDevDerivative
Real bachelierBlackFormulaStdDevDerivative(Rate strike, Rate forward, Real stdDev, Real discount)
Definition: blackformula.cpp:832
QuantLib::VolatilityType
VolatilityType
Definition: volatilitytype.hpp:32
QuantLib::detail::BlackStyleSwaptionEngine::BlackStyleSwaptionEngine
BlackStyleSwaptionEngine(Handle< YieldTermStructure > discountCurve, Volatility vol, const DayCounter &dc=Actual365Fixed(), Real displacement=0.0, CashAnnuityModel model=DiscountCurve)
Definition: blackswaptionengine.hpp:182
QuantLib::detail::BlackStyleSwaptionEngine< detail::BachelierSpec >::CashAnnuityModel
CashAnnuityModel
Definition: blackswaptionengine.hpp:56
QuantLib::bachelierBlackFormulaForwardDerivative
Real bachelierBlackFormulaForwardDerivative(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount)
Definition: blackformula.cpp:733
QuantLib::Settlement::Physical
@ Physical
Definition: swaption.hpp:41
QuantLib::Rate
Real Rate
interest rates
Definition: types.hpp:70
QuantLib::DiscountingSwapEngine
Definition: discountingswapengine.hpp:34
QuantLib::detail::Black76Spec::type
static const VolatilityType type
Definition: blackswaptionengine.hpp:82
QuantLib::detail::BlackStyleSwaptionEngine::volatility
Handle< SwaptionVolatilityStructure > volatility()
Definition: blackswaptionengine.hpp:72
QuantLib::detail::BlackStyleSwaptionEngine::BlackStyleSwaptionEngine
BlackStyleSwaptionEngine(Handle< YieldTermStructure > discountCurve, const Handle< Quote > &vol, const DayCounter &dc=Actual365Fixed(), Real displacement=0.0, CashAnnuityModel model=DiscountCurve)
Definition: blackswaptionengine.hpp:196
QuantLib::DayCounter
day counter class
Definition: daycounter.hpp:44
QuantLib::detail::BachelierSpec::type
static const VolatilityType type
Definition: blackswaptionengine.hpp:106
QuantLib::ShiftedLognormal
@ ShiftedLognormal
Definition: volatilitytype.hpp:32
QuantLib
Definition: cashflow.cpp:25
QuantLib::detail::BachelierSpec
Definition: blackswaptionengine.hpp:105
QuantLib::BachelierSwaptionEngine
Normal Bachelier-formula swaption engine.
Definition: blackswaptionengine.hpp:162
QuantLib::detail::BlackStyleSwaptionEngine
Definition: blackswaptionengine.hpp:54
QuantLib::detail::BlackStyleSwaptionEngine::termStructure
Handle< YieldTermStructure > termStructure()
Definition: blackswaptionengine.hpp:71
QuantLib::Compounded
@ Compounded
Definition: compounding.hpp:33
QuantLib::detail::Black76Spec
Definition: blackswaptionengine.hpp:81
QuantLib::Date
Concrete date class.
Definition: date.hpp:125
QuantLib::InterestRate
Concrete interest rate class.
Definition: interestrate.hpp:40
QuantLib::Settlement::CollateralizedCashPrice
@ CollateralizedCashPrice
Definition: swaption.hpp:45
QuantLib::Settlement::Cash
@ Cash
Definition: swaption.hpp:41
QuantLib::blackFormulaStdDevDerivative
Real blackFormulaStdDevDerivative(Rate strike, Rate forward, Real stdDev, Real discount, Real displacement)
Definition: blackformula.cpp:633
QuantLib::detail::BlackStyleSwaptionEngine::model_
CashAnnuityModel model_
Definition: blackswaptionengine.hpp:77
QuantLib::detail::Black76Spec::delta
Real delta(const Option::Type type, const Real strike, const Real atmForward, const Real stdDev, const Real annuity, const Real displacement)
Definition: blackswaptionengine.hpp:96
QuantLib::VanillaSwap
Plain-vanilla swap: fix vs floating leg.
Definition: vanillaswap.hpp:65
QuantLib::Option::Call
@ Call
Definition: option.hpp:40
QuantLib::Swaption::engine
base class for swaption engines
Definition: swaption.hpp:137
QuantLib::Time
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QuantLib::ConstantSwaptionVolatility
Constant swaption volatility, no time-strike dependence.
Definition: swaptionconstantvol.hpp:37
QuantLib::Real
QL_REAL Real
real number
Definition: types.hpp:50