Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
NumericLgmBgsFlexiSwapEngine Class Reference

Numerical engine for balance guaranteed swaps using a flexi swap proxy in the LGM model. More...

#include <qle/pricingengines/numericlgmbgsflexiswapengine.hpp>

+ Inheritance diagram for NumericLgmBgsFlexiSwapEngine:
+ Collaboration diagram for NumericLgmBgsFlexiSwapEngine:

Public Member Functions

 NumericLgmBgsFlexiSwapEngine (const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > &model, const Real sy, const Size ny, const Real sx, const Size nx, const Handle< Quote > &minCpr, const Handle< Quote > &maxCpr, const Handle< YieldTermStructure > &discountCurve=Handle< YieldTermStructure >(), const Method method=Method::Automatic, const Real singleSwaptionThreshold=20.0)
 
- Public Member Functions inherited from NumericLgmFlexiSwapEngineBase
 NumericLgmFlexiSwapEngineBase (const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > &model, const Real sy, const Size ny, const Real sx, const Size nx, const Handle< YieldTermStructure > &discountCurve=Handle< YieldTermStructure >(), const Method method=Method::Automatic, const Real singleSwaptionThreshold=20.0)
 
- Public Member Functions inherited from LgmConvolutionSolver
 LgmConvolutionSolver (const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > &model, const Real sy, const Size ny, const Real sx, const Size nx)
 Numerical convolution solver for the LGM model. More...
 
Size gridSize () const
 
std::vector< Real > stateGrid (const Real t) const
 
template<typename ValueType = Real>
std::vector< ValueType > rollback (const std::vector< ValueType > &v, const Real t1, const Real t0, const ValueType zero=ValueType(0.0)) const
 
const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > & model () const
 

Private Member Functions

void calculate () const override
 

Private Attributes

const Handle< Quote > minCpr_
 
const Handle< Quote > maxCpr_
 

Additional Inherited Members

- Public Types inherited from NumericLgmFlexiSwapEngineBase
enum class  Method { SwaptionArray , SingleSwaptions , Automatic }
 
- Protected Member Functions inherited from NumericLgmFlexiSwapEngineBase
std::pair< Real, Real > calculate () const
 
Real underlyingValue (const Real, const Real, const Date &, const Size, const Size, const Real, const Real) const
 
- Protected Attributes inherited from NumericLgmFlexiSwapEngineBase
const Handle< YieldTermStructure > discountCurve_
 
const Method method_
 
const Real singleSwaptionThreshold_
 
QuantLib::ext::shared_ptr< IborIndex > iborModelIndex_
 
QuantLib::ext::shared_ptr< LgmImpliedYieldTermStructureiborModelCurve_
 
VanillaSwap::Type type
 
std::vector< Real > fixedNominal
 
std::vector< Real > floatingNominal
 
std::vector< Date > fixedResetDates
 
std::vector< Date > fixedPayDates
 
std::vector< Time > floatingAccrualTimes
 
std::vector< Date > floatingResetDates
 
std::vector< Date > floatingFixingDates
 
std::vector< Date > floatingPayDates
 
std::vector< Real > fixedCoupons
 
std::vector< Real > fixedRate
 
std::vector< Real > floatingGearings
 
std::vector< Real > floatingSpreads
 
std::vector< Real > cappedRate
 
std::vector< Real > flooredRate
 
std::vector< Real > floatingCoupons
 
QuantLib::ext::shared_ptr< IborIndex > iborIndex
 
std::vector< Real > lowerNotionalBound
 
QuantLib::Position::Type optionPosition
 
std::vector< boolnotionalCanBeDecreased
 

Detailed Description

Numerical engine for balance guaranteed swaps using a flexi swap proxy in the LGM model.

Two notional schedules are constructed using a simple prepayment model with rates minCpr and maxCpr. These two schedules define a lower / upper notional bounds of a flexi swap. The NPV of this flexi swap is by definition the NPV of the BGS itself.

The prepayment model assumes that prepayments amortise the tranches in the order of their seniority.

Notice that prepayments start in the first period of the tranche nominal schedule that has a start date that lies in the future. Therefore the tranche notionals in the BGS should contain past (known) prepayments already, only for future periods the notionals should be given under a zero CPR assumption.

Definition at line 42 of file numericlgmbgsflexiswapengine.hpp.

Constructor & Destructor Documentation

◆ NumericLgmBgsFlexiSwapEngine()

NumericLgmBgsFlexiSwapEngine ( const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > &  model,
const Real  sy,
const Size  ny,
const Real  sx,
const Size  nx,
const Handle< Quote > &  minCpr,
const Handle< Quote > &  maxCpr,
const Handle< YieldTermStructure > &  discountCurve = Handle<YieldTermStructure>(),
const Method  method = Method::Automatic,
const Real  singleSwaptionThreshold = 20.0 
)

Definition at line 25 of file numericlgmbgsflexiswapengine.cpp.

30 : NumericLgmFlexiSwapEngineBase(model, sy, ny, sx, nx, discountCurve, method, singleSwaptionThreshold),
31 minCpr_(minCpr), maxCpr_(maxCpr) {
32 registerWith(this->model());
33 registerWith(discountCurve_);
34 registerWith(minCpr_);
35 registerWith(maxCpr_);
36} // NumericLgmFlexiSwapEngine::NumericLgmFlexiSwapEngine
const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > & model() const
NumericLgmFlexiSwapEngineBase(const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > &model, const Real sy, const Size ny, const Real sx, const Size nx, const Handle< YieldTermStructure > &discountCurve=Handle< YieldTermStructure >(), const Method method=Method::Automatic, const Real singleSwaptionThreshold=20.0)
const Handle< YieldTermStructure > discountCurve_
+ Here is the call graph for this function:

Member Function Documentation

◆ calculate()

void calculate ( ) const
overrideprivate

Definition at line 50 of file numericlgmbgsflexiswapengine.cpp.

50 {
51 Date today = Settings::instance().evaluationDate();
52 // compute the lower and upper notionals bounds, in terms of the tranche notional schedule
53 Real currentLowerNotionalAfterPrepayment = 0.0, currentUpperNotionalAfterPrepayment = 0.0,
54 lastAggregatePrincipal = 0.0;
55 std::vector<Real> tmpLowerNotionalBound, tmpUpperNotionalBound;
56 Real effectiveMinCpr = minCpr_->value() / static_cast<Real>(arguments_.trancheNominalFrequency);
57 Real effectiveMaxCpr = maxCpr_->value() / static_cast<Real>(arguments_.trancheNominalFrequency);
58 for (Size i = 0; i < arguments_.trancheNominalDates.size() - 1; ++i) {
59 Real aggregatePrincipal = 0.0;
60 for (Size j = 0; j < arguments_.trancheNominals.size(); ++j)
61 aggregatePrincipal += arguments_.trancheNominals[j][i];
62 if (i == 0) {
63 // in the first period we do not have a prepayment
64 currentUpperNotionalAfterPrepayment = aggregatePrincipal;
65 currentLowerNotionalAfterPrepayment = aggregatePrincipal;
66 }
67 if (i > 0) {
68 // ratio of zero-cpr notionals
69 Real amortisationRate =
70 QuantLib::close_enough(aggregatePrincipal, 0.0) ? 0.0 : (aggregatePrincipal / lastAggregatePrincipal);
71 // we only prepay if the start date of the nominal is in the future
72 currentUpperNotionalAfterPrepayment =
73 currentUpperNotionalAfterPrepayment *
74 std::max(amortisationRate - (arguments_.trancheNominalDates[i] > today ? effectiveMinCpr : 0.0), 0.0);
75 currentLowerNotionalAfterPrepayment =
76 currentLowerNotionalAfterPrepayment *
77 std::max(amortisationRate - (arguments_.trancheNominalDates[i] > today ? effectiveMaxCpr : 0.0), 0.0);
78 }
79 // now that we have the current notional of the period we can determine the swap notional
80 // for this, we subtract the notionals of all tranches which are less senior...
81 Real subordinatedPrincipal = 0;
82 for (Size k = arguments_.trancheNominals.size() - 1; k > arguments_.referencedTranche; --k) {
83 subordinatedPrincipal += arguments_.trancheNominals[k][i];
84 }
85 // and then cap the result at the referenced tranche's volume and floor it at zero
86 tmpLowerNotionalBound.push_back(
87 std::min(std::max(currentLowerNotionalAfterPrepayment - subordinatedPrincipal, 0.0),
88 arguments_.trancheNominals[arguments_.referencedTranche][i]));
89 tmpUpperNotionalBound.push_back(
90 std::min(std::max(currentUpperNotionalAfterPrepayment - subordinatedPrincipal, 0.0),
91 arguments_.trancheNominals[arguments_.referencedTranche][i]));
92 // update the aggregate principal for the next period
93 lastAggregatePrincipal = aggregatePrincipal;
94 }
95
96 // convert the bounds to notional vectors for the fixed and floating schedule
97 std::vector<Real> lowerNotionalFixedBound, upperNotionalFixedBound, upperNotionalFloatingBound;
98 for (Size i = 0; i < arguments_.fixedResetDates.size(); ++i) {
99 lowerNotionalFixedBound.push_back(
100 getNotional(tmpLowerNotionalBound, arguments_.trancheNominalDates, arguments_.fixedResetDates[i]));
101 upperNotionalFixedBound.push_back(
102 getNotional(tmpUpperNotionalBound, arguments_.trancheNominalDates, arguments_.fixedResetDates[i]));
103 }
104 // derive floating nominal schedule from fixed to ensure they match
105 Size ratio =
106 arguments_.floatingResetDates.size() / arguments_.fixedResetDates.size(); // we know there is no remainder
107 upperNotionalFloatingBound.resize(upperNotionalFixedBound.size() * ratio);
108 Size i = 0; // remove in C++14 and instead write [i=0, &fixedNotional] in the capture below
109 std::generate(upperNotionalFloatingBound.begin(), upperNotionalFloatingBound.end(),
110 [i, &upperNotionalFixedBound, ratio]() mutable { return upperNotionalFixedBound[i++ / ratio]; });
111
112 // recalculate the fixed and floating coupons belonging to the upper Notional
113 std::vector<Real> upperFixedCoupons, upperFloatingCoupons;
114 for (Size i = 0; i < arguments_.fixedLeg.size(); ++i) {
115 auto cp = QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(arguments_.fixedLeg[i]);
116 upperFixedCoupons.push_back(cp->accrualPeriod() * cp->rate() * upperNotionalFixedBound[i]);
117 }
118 for (Size i = 0; i < arguments_.floatingLeg.size(); ++i) {
119 auto cp = QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(arguments_.floatingLeg[i]);
120 try {
121 upperFloatingCoupons.push_back(cp->accrualPeriod() * cp->rate() * upperNotionalFloatingBound[i]);
122 } catch (...) {
123 upperFloatingCoupons.push_back(Null<Real>());
124 }
125 }
126
127 // determine the option position, the holder is the payer of the structured (i.e. fixed) leg
128 QuantLib::Position::Type flexiOptionPosition =
129 arguments_.type == VanillaSwap::Payer ? QuantLib::Position::Long : QuantLib::Position::Short;
130
131 // set arguments in base engine
132 type = arguments_.type;
133 fixedNominal = upperNotionalFixedBound; // computed above
134 floatingNominal = upperNotionalFloatingBound; // computed above
135 fixedResetDates = arguments_.fixedResetDates;
136 fixedPayDates = arguments_.fixedPayDates;
137 floatingAccrualTimes = arguments_.floatingAccrualTimes;
138 floatingResetDates = arguments_.floatingResetDates;
139 floatingFixingDates = arguments_.floatingFixingDates;
140 floatingPayDates = arguments_.floatingPayDates;
141 fixedCoupons = upperFixedCoupons;
142 fixedRate = arguments_.fixedRate;
143 floatingGearings = arguments_.floatingGearings;
144 floatingSpreads = arguments_.floatingSpreads;
145 cappedRate = arguments_.cappedRate;
146 flooredRate = arguments_.flooredRate;
147 floatingCoupons = upperFloatingCoupons;
148 iborIndex = arguments_.iborIndex;
149 lowerNotionalBound = lowerNotionalFixedBound; // computed above
150 optionPosition = flexiOptionPosition; // computed above
152 std::vector<bool>(fixedNominal.size(), true); // each period is eligable for notional decrease
153
154 // calculate and set results
156 results_.value = result.first;
157 results_.additionalResults = getAdditionalResultsMap(model()->getCalibrationInfo());
158} // NumericLgmBgsFlexiSwapEngine::calculate
const Instrument::results * results_
Definition: cdsoption.cpp:81
QuantLib::ext::shared_ptr< IborIndex > iborIndex
std::map< std::string, boost::any > getAdditionalResultsMap(const LgmCalibrationInfo &info)
Swap::arguments * arguments_
+ Here is the call graph for this function:

Member Data Documentation

◆ minCpr_

const Handle<Quote> minCpr_
private

Definition at line 53 of file numericlgmbgsflexiswapengine.hpp.

◆ maxCpr_

const Handle<Quote> maxCpr_
private

Definition at line 53 of file numericlgmbgsflexiswapengine.hpp.