QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
tenorswaptionvts.cpp
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
25#include <ql/experimental/basismodels/tenorswaptionvts.hpp>
26#include <ql/experimental/basismodels/swaptioncfs.hpp>
27#include <ql/exercise.hpp>
28#include <ql/indexes/iborindex.hpp>
29#include <ql/math/rounding.hpp>
30#include <ql/pricingengines/swap/discountingswapengine.hpp>
31#include <ql/time/dategenerationrule.hpp>
32
33
34namespace QuantLib {
35
37 const TenorSwaptionVTS& volTS, Time optionTime, Time swapLength)
38 : SmileSection(optionTime, volTS.baseVTS_->dayCounter(), Normal, 0.0) {
39 baseSmileSection_ = volTS.baseVTS_->smileSection(optionTime, swapLength, true);
40 // first we need the swap start and end date
41 Real oneDayAsYear =
42 volTS.dayCounter().yearFraction(volTS.referenceDate(), volTS.referenceDate() + 1);
44 volTS.referenceDate() + ((BigInteger)ClosestRounding(0)(optionTime / oneDayAsYear));
45 Date effectiveDate = volTS.baseIndex_->fixingCalendar().advance(
46 exerciseDate, volTS.baseIndex_->fixingDays() * Days);
47 Date maturityDate = volTS.baseIndex_->fixingCalendar().advance(
48 effectiveDate, ((BigInteger)swapLength * 12.0) * Months, Unadjusted, false);
49 // now we can set up the schedules
50 Schedule baseFixedSchedule(effectiveDate, maturityDate, volTS.baseFixedFreq_,
51 volTS.baseIndex_->fixingCalendar(), ModifiedFollowing,
53 Schedule finlFixedSchedule(effectiveDate, maturityDate, volTS.targFixedFreq_,
54 volTS.targIndex_->fixingCalendar(), ModifiedFollowing,
56 Schedule baseFloatSchedule(effectiveDate, maturityDate, volTS.baseIndex_->tenor(),
57 volTS.baseIndex_->fixingCalendar(), ModifiedFollowing,
59 Schedule targFloatSchedule(effectiveDate, maturityDate, volTS.targIndex_->tenor(),
60 volTS.baseIndex_->fixingCalendar(), ModifiedFollowing,
62 // and swaps
63 ext::shared_ptr<VanillaSwap> baseSwap(new VanillaSwap(
64 Swap::Payer, 1.0, baseFixedSchedule, 1.0, volTS.baseFixedDC_, baseFloatSchedule,
65 volTS.baseIndex_, 0.0, volTS.baseIndex_->dayCounter()));
66 ext::shared_ptr<VanillaSwap> targSwap(new VanillaSwap(
67 Swap::Payer, 1.0, baseFixedSchedule, 1.0, volTS.baseFixedDC_, targFloatSchedule,
68 volTS.targIndex_, 0.0, volTS.targIndex_->dayCounter()));
69 ext::shared_ptr<VanillaSwap> finlSwap(new VanillaSwap(
70 Swap::Payer, 1.0, finlFixedSchedule, 1.0, volTS.targFixedDC_, targFloatSchedule,
71 volTS.targIndex_, 0.0, volTS.targIndex_->dayCounter()));
72 // adding engines
73 baseSwap->setPricingEngine(
74 ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(volTS.discountCurve_)));
75 targSwap->setPricingEngine(
76 ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(volTS.discountCurve_)));
77 finlSwap->setPricingEngine(
78 ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(volTS.discountCurve_)));
79 // swap rates
80 swapRateBase_ = baseSwap->fairRate();
81 swapRateTarg_ = targSwap->fairRate();
82 swapRateFinl_ = finlSwap->fairRate();
84 ext::make_shared<Swaption>(
85 baseSwap, ext::shared_ptr<Exercise>(new EuropeanExercise(exerciseDate))),
86 volTS.discountCurve_);
88 ext::make_shared<Swaption>(
89 targSwap, ext::shared_ptr<Exercise>(new EuropeanExercise(exerciseDate))),
90 volTS.discountCurve_);
91 // calculate affine TSR model u and v
92 // Sum tau_j (fixed leg)
93 Real sumTauj = 0.0;
94 for (Real k : cfs.annuityWeights())
95 sumTauj += k;
96 // Sum tau_j (T_M - T_j) (fixed leg)
97 Real sumTaujDeltaT = 0.0;
98 for (Size k = 0; k < cfs.annuityWeights().size(); ++k)
99 sumTaujDeltaT +=
100 cfs.annuityWeights()[k] * (cfs.fixedTimes().back() - cfs.fixedTimes()[k]);
101 // Sum w_i (float leg)
102 Real sumWi = 0.0;
103 for (Real k : cfs.floatWeights())
104 sumWi += k;
105 // Sum w_i (T_N - T_i) (float leg)
106 Real sumWiDeltaT = 0.0;
107 for (Size k = 0; k < cfs.floatWeights().size(); ++k)
108 sumWiDeltaT += cfs.floatWeights()[k] * (cfs.floatTimes().back() - cfs.floatTimes()[k]);
109 // assemble u, v and a(T_p)
110 Real den = sumTaujDeltaT * sumWi - sumWiDeltaT * sumTauj;
111 Real u = -sumTauj / den;
112 Real v = sumTaujDeltaT / den;
114 // a(T_p) = u (T_p - T_N) + v
115 Real T_N = cfs.fixedTimes().back();
116 Real sumBase = 0.0;
117 Real sumTarg = 0.0;
118 // we skip the first and last weight as they represent the notional flows
119 for (Size k = 1; k < cfs.floatWeights().size() - 1; ++k)
120 sumBase += cfs.floatWeights()[k] * (u * (T_N - cfs.floatTimes()[k]) + v);
121 for (Size k = 1; k < cf2.floatWeights().size() - 1; ++k)
122 sumTarg += cf2.floatWeights()[k] * (u * (T_N - cf2.floatTimes()[k]) + v);
123 lambda_ = sumTarg - sumBase;
124 // Annuity scaling
125 annuityScaling_ = targSwap->fixedLegBPS() / finlSwap->fixedLegBPS();
126 }
127
129 Real strikeBase = (strike - (swapRateTarg_ - (1.0 + lambda_) * swapRateBase_)) /
130 (1.0 + lambda_) / annuityScaling_;
131 Real volBase = baseSmileSection_->volatility(strikeBase, Normal, 0.0);
132 Real volTarg = annuityScaling_ * (1.0 + lambda_) * volBase;
133 return volTarg;
134 }
135
136
137}
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
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
Plain-vanilla swap: fix vs ibor leg.
Definition: vanillaswap.hpp:65
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
Definition: any.hpp:35