QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
tenorswaptionvts.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4Copyright (C) 2018 Sebastian Schlenkrich
5
6This file is part of QuantLib, a free-software/open-source library
7for financial quantitative analysts and developers - http://quantlib.org/
8
9QuantLib is free software: you can redistribute it and/or modify it
10under the terms of the QuantLib license. You should have received a
11copy 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
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20/*! \file tenorswaptionvts.cpp
21 \brief swaption volatility term structure based on volatility transformation
22*/
23
24
28#include <ql/exercise.hpp>
30#include <ql/math/rounding.hpp>
33
34
35namespace QuantLib {
36
38 const TenorSwaptionVTS& volTS, Time optionTime, Time swapLength)
39 : SmileSection(optionTime, volTS.baseVTS_->dayCounter(), Normal, 0.0) {
40 baseSmileSection_ = volTS.baseVTS_->smileSection(optionTime, swapLength, true);
41 // first we need the swap start and end date
42 Real oneDayAsYear =
43 volTS.dayCounter().yearFraction(volTS.referenceDate(), volTS.referenceDate() + 1);
45 volTS.referenceDate() + ((BigInteger)ClosestRounding(0)(optionTime / oneDayAsYear));
46 Date effectiveDate = volTS.baseIndex_->fixingCalendar().advance(
47 exerciseDate, volTS.baseIndex_->fixingDays() * Days);
48 Date maturityDate = volTS.baseIndex_->fixingCalendar().advance(
49 effectiveDate, ((BigInteger)swapLength * 12.0) * Months, Unadjusted, false);
50 // now we can set up the schedules
51 Schedule baseFixedSchedule(effectiveDate, maturityDate, volTS.baseFixedFreq_,
52 volTS.baseIndex_->fixingCalendar(), ModifiedFollowing,
54 Schedule finlFixedSchedule(effectiveDate, maturityDate, volTS.targFixedFreq_,
55 volTS.targIndex_->fixingCalendar(), ModifiedFollowing,
57 Schedule baseFloatSchedule(effectiveDate, maturityDate, volTS.baseIndex_->tenor(),
58 volTS.baseIndex_->fixingCalendar(), ModifiedFollowing,
60 Schedule targFloatSchedule(effectiveDate, maturityDate, volTS.targIndex_->tenor(),
61 volTS.baseIndex_->fixingCalendar(), ModifiedFollowing,
63 // and swaps
64 auto baseSwap = ext::make_shared<VanillaSwap>(
65 Swap::Payer, 1.0, baseFixedSchedule, 1.0, volTS.baseFixedDC_, baseFloatSchedule,
66 volTS.baseIndex_, 0.0, volTS.baseIndex_->dayCounter());
67 auto targSwap = ext::make_shared<VanillaSwap>(
68 Swap::Payer, 1.0, baseFixedSchedule, 1.0, volTS.baseFixedDC_, targFloatSchedule,
69 volTS.targIndex_, 0.0, volTS.targIndex_->dayCounter());
70 auto finlSwap = ext::make_shared<VanillaSwap>(
71 Swap::Payer, 1.0, finlFixedSchedule, 1.0, volTS.targFixedDC_, targFloatSchedule,
72 volTS.targIndex_, 0.0, volTS.targIndex_->dayCounter());
73 // adding engines
74 baseSwap->setPricingEngine(
75 ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(volTS.discountCurve_)));
76 targSwap->setPricingEngine(
77 ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(volTS.discountCurve_)));
78 finlSwap->setPricingEngine(
79 ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(volTS.discountCurve_)));
80 // swap rates
81 swapRateBase_ = baseSwap->fairRate();
82 swapRateTarg_ = targSwap->fairRate();
83 swapRateFinl_ = finlSwap->fairRate();
85 ext::make_shared<Swaption>(
86 baseSwap, ext::shared_ptr<Exercise>(new EuropeanExercise(exerciseDate))),
87 volTS.discountCurve_);
89 ext::make_shared<Swaption>(
90 targSwap, ext::shared_ptr<Exercise>(new EuropeanExercise(exerciseDate))),
91 volTS.discountCurve_);
92 // calculate affine TSR model u and v
93 // Sum tau_j (fixed leg)
94 Real sumTauj = 0.0;
95 for (Real k : cfs.annuityWeights())
96 sumTauj += k;
97 // Sum tau_j (T_M - T_j) (fixed leg)
98 Real sumTaujDeltaT = 0.0;
99 for (Size k = 0; k < cfs.annuityWeights().size(); ++k)
100 sumTaujDeltaT +=
101 cfs.annuityWeights()[k] * (cfs.fixedTimes().back() - cfs.fixedTimes()[k]);
102 // Sum w_i (float leg)
103 Real sumWi = 0.0;
104 for (Real k : cfs.floatWeights())
105 sumWi += k;
106 // Sum w_i (T_N - T_i) (float leg)
107 Real sumWiDeltaT = 0.0;
108 for (Size k = 0; k < cfs.floatWeights().size(); ++k)
109 sumWiDeltaT += cfs.floatWeights()[k] * (cfs.floatTimes().back() - cfs.floatTimes()[k]);
110 // assemble u, v and a(T_p)
111 Real den = sumTaujDeltaT * sumWi - sumWiDeltaT * sumTauj;
112 Real u = -sumTauj / den;
113 Real v = sumTaujDeltaT / den;
115 // a(T_p) = u (T_p - T_N) + v
116 Real T_N = cfs.fixedTimes().back();
117 Real sumBase = 0.0;
118 Real sumTarg = 0.0;
119 // we skip the first and last weight as they represent the notional flows
120 for (Size k = 1; k < cfs.floatWeights().size() - 1; ++k)
121 sumBase += cfs.floatWeights()[k] * (u * (T_N - cfs.floatTimes()[k]) + v);
122 for (Size k = 1; k < cf2.floatWeights().size() - 1; ++k)
123 sumTarg += cf2.floatWeights()[k] * (u * (T_N - cf2.floatTimes()[k]) + v);
124 lambda_ = sumTarg - sumBase;
125 // Annuity scaling
126 annuityScaling_ = targSwap->fixedLegBPS() / finlSwap->fixedLegBPS();
127 }
128
130 Real strikeBase = (strike - (swapRateTarg_ - (1.0 + lambda_) * swapRateBase_)) /
131 (1.0 + lambda_) / annuityScaling_;
132 Real volBase = baseSmileSection_->volatility(strikeBase, Normal, 0.0);
133 Real volTarg = annuityScaling_ * (1.0 + lambda_) * volBase;
134 return volTarg;
135 }
136
137
138}
Actual/365 (Fixed) day count convention.
Closest rounding.
Definition: rounding.hpp:106
Concrete date class.
Definition: date.hpp:125
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
Definition: daycounter.hpp:128
Discounting engine for swaps.
European exercise.
Definition: exercise.hpp:96
const std::vector< Real > & floatWeights() const
Definition: swaptioncfs.hpp:44
const std::vector< Real > & floatTimes() const
Definition: swaptioncfs.hpp:43
Payment schedule.
Definition: schedule.hpp:40
interest rate volatility smile section
virtual const Date & exerciseDate() const
const std::vector< Real > & fixedTimes() const
Definition: swaptioncfs.hpp:69
const std::vector< Real > & annuityWeights() const
Definition: swaptioncfs.hpp:71
Time swapLength(const Period &swapTenor) const
implements the conversion between swap tenor and swap (time) length
TenorSwaptionSmileSection(const TenorSwaptionVTS &volTS, Time optionTime, Time swapLength)
Volatility volatilityImpl(Rate strike) const override
Handle< YieldTermStructure > discountCurve_
Handle< SwaptionVolatilityStructure > baseVTS_
ext::shared_ptr< IborIndex > targIndex_
ext::shared_ptr< IborIndex > baseIndex_
virtual const Date & referenceDate() const
the date at which discount = 1.0 and/or variance = 0.0
virtual DayCounter dayCounter() const
the day counter used for date/time conversion
date generation rule
discounting swap engine
Option exercise classes and payoff function.
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
QL_BIG_INTEGER BigInteger
large integer number
Definition: types.hpp:39
Real Volatility
volatility
Definition: types.hpp:78
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
base class for Inter-Bank-Offered-Rate indexes
Definition: any.hpp:35
ext::shared_ptr< BlackVolTermStructure > v
Rounding implementation.
translate swaption into deterministic fixed and float cash flows
swaption volatility term structure based on volatility transformation
Simple fixed-rate vs Libor swap.