116 {
117
118 BOOST_TEST_MESSAGE("Testing LGM BGS Flexi-Swap engine against LGM Flexi-Swap engine...");
119
120
121
122 Size nFixed = fixedSchedule.size() - 1, nFloat = floatingSchedule.size() - 1;
123
124 std::vector<std::vector<Real>> trancheNominals{
125 {1000.0, 900.0, 800.0, 700.0, 600.0, 500.0, 400.0, 300.0, 200.0, 100.0},
126 {300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0}};
127
128
129 QuantLib::ext::shared_ptr<BalanceGuaranteedSwap> bgs0 = QuantLib::ext::make_shared<BalanceGuaranteedSwap>(
130 VanillaSwap::Payer, trancheNominals, fixedSchedule, 0, fixedSchedule, std::vector<Real>(nFixed, strike),
131 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
132 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360());
133
134
135 QuantLib::ext::shared_ptr<BalanceGuaranteedSwap> bgs1 = QuantLib::ext::make_shared<BalanceGuaranteedSwap>(
136 VanillaSwap::Payer, trancheNominals, fixedSchedule, 1, fixedSchedule, std::vector<Real>(nFixed, strike),
137 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
138 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360());
139
140 Handle<Quote> minCpr(QuantLib::ext::make_shared<SimpleQuote>(0.05));
141 Handle<Quote> maxCpr(QuantLib::ext::make_shared<SimpleQuote>(0.25));
142
143 auto bgsEngine = QuantLib::ext::make_shared<NumericLgmBgsFlexiSwapEngine>(
145
146 bgs0->setPricingEngine(bgsEngine);
147 Real bgs0Npv = bgs0->NPV();
148 BOOST_TEST_MESSAGE("BGS Npv (tranche 0) = " << bgs0Npv);
149
150 bgs0->setPricingEngine(dscSwapEngine);
151 Real bgs0DscNpv = bgs0->NPV();
152 BOOST_TEST_MESSAGE("BGS discounting engine Npv (tranche 0) = " << bgs0DscNpv);
153
154 bgs1->setPricingEngine(bgsEngine);
155 Real bgs1Npv = bgs1->NPV();
156 BOOST_TEST_MESSAGE("BGS Npv (tranche 1) = " << bgs1Npv);
157
158 bgs1->setPricingEngine(dscSwapEngine);
159 Real bgs1DscNpv = bgs1->NPV();
160 BOOST_TEST_MESSAGE("BGS discounting engine Npv (tranche 1) = " << bgs1DscNpv);
161
162
163
164
165
166
167 std::vector<Real> fixedNotionals0{1000.0, 835.0, 683.6666667, 545.0590909, 418.3002273,
168 302.5740795, 197.1236156, 101.2497755, 14.31232412, 0.0};
169 std::vector<Real> floatNotionals0(2 * fixedNotionals0.size(), 0.0);
170 Size i = 0;
171 std::generate(floatNotionals0.begin(), floatNotionals0.end(),
172 [i, &fixedNotionals0]() mutable { return fixedNotionals0[i++ / 2]; });
173 std::vector<Real> lowerNotionals0{1000.0, 575.0, 283.3333333, 84.46969697, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
174
175
176 std::vector<Real> fixedNotionals1{300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 235.7342431};
177 std::vector<Real> floatNotionals1(2 * fixedNotionals1.size(), 0.0);
178 i = 0;
179 std::generate(floatNotionals1.begin(), floatNotionals1.end(),
180 [i, &fixedNotionals1]() mutable { return fixedNotionals1[i++ / 2]; });
181 std::vector<Real> lowerNotionals1{300.0, 300.0, 300.0, 300.0, 249.905303,
182 159.6617214, 99.78857586, 60.58592106, 35.34178728, 19.43798301};
183
184
185
186
187 std::vector<Real> fixedNotionals0ZeroCpr{1000.0, 900.0, 800.0, 700.0, 600.0, 500.0, 400.0, 300.0, 200.0, 100.0};
188 std::vector<Real> floatNotionals0ZeroCpr(2 * fixedNotionals0ZeroCpr.size(), 0.0);
189 i = 0;
190 std::generate(floatNotionals0ZeroCpr.begin(), floatNotionals0ZeroCpr.end(),
191 [i, &fixedNotionals0ZeroCpr]() mutable { return fixedNotionals0ZeroCpr[i++ / 2]; });
192 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap0 = QuantLib::ext::make_shared<FlexiSwap>(
193 VanillaSwap::Payer, fixedNotionals0, floatNotionals0, fixedSchedule, std::vector<Real>(nFixed, strike),
194 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
195 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals0,
196 Position::Long);
197 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap0MinCpr0 = QuantLib::ext::make_shared<FlexiSwap>(
198 VanillaSwap::Payer, fixedNotionals0ZeroCpr, floatNotionals0ZeroCpr, fixedSchedule,
199 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
200 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
201 std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals1, Position::Long);
202
203
204 std::vector<Real> fixedNotionals1ZeroCpr(10, 300.0);
205 std::vector<Real> floatNotionals1ZeroCpr(20, 300.0);
206 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap1 = QuantLib::ext::make_shared<FlexiSwap>(
207 VanillaSwap::Payer, fixedNotionals1, floatNotionals1, fixedSchedule, std::vector<Real>(nFixed, strike),
208 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
209 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals1,
210 Position::Long);
211 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap1MinCpr0 = QuantLib::ext::make_shared<FlexiSwap>(
212 VanillaSwap::Payer, fixedNotionals1ZeroCpr, floatNotionals1ZeroCpr, fixedSchedule,
213 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
214 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
215 std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals1, Position::Long);
216
217 auto flexiEngine = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
219
220 flexiSwap0->setPricingEngine(flexiEngine);
221 Real flexi0Npv = flexiSwap0->NPV();
222 BOOST_TEST_MESSAGE("Flexi-Swap Npv (tranche 0) = " << flexi0Npv);
223
224 flexiSwap0MinCpr0->setPricingEngine(dscSwapEngine);
225 Real flexi0DscNpv0 = flexiSwap0MinCpr0->NPV();
226 BOOST_TEST_MESSAGE("Flexi-Swap (tranche 0, minCPR=0), discounting engine Npv = " << flexi0DscNpv0);
227
228 flexiSwap1->setPricingEngine(flexiEngine);
229 Real flexi1Npv = flexiSwap1->NPV();
230 BOOST_TEST_MESSAGE("Flexi-Swap Npv (tranche 1) = " << flexi1Npv);
231
232 flexiSwap1MinCpr0->setPricingEngine(dscSwapEngine);
233 Real flexi1DscNpv0 = flexiSwap1MinCpr0->NPV();
234 BOOST_TEST_MESSAGE("Flexi-Swap (tranche 1, minCPR=0), discounting engine Npv = " << flexi1DscNpv0);
235
236 BOOST_CHECK_CLOSE(bgs0Npv, flexi0Npv, 1E-8);
237 BOOST_CHECK_CLOSE(bgs0DscNpv, flexi0DscNpv0, 1E-8);
238 BOOST_CHECK_CLOSE(bgs1Npv, flexi1Npv, 1E-8);
239 BOOST_CHECK_CLOSE(bgs1DscNpv, flexi1DscNpv0, 1E-8);
240
241}