180 {
181
182 BOOST_TEST_MESSAGE("Testing CPI Swap Price...");
183
184
185 Date today(18, July, 2016);
186 Settings::instance().evaluationDate() = today;
187 QuantLib::ext::shared_ptr<TestMarket> market = QuantLib::ext::make_shared<TestMarket>();
188 Date marketDate = market->asofDate();
189 BOOST_CHECK_EQUAL(today, marketDate);
190 Settings::instance().evaluationDate() = marketDate;
191
192
193 Handle<YieldTermStructure> dts = market->discountCurve("GBP");
194 QL_REQUIRE(!dts.empty(), "GBP discount curve not found");
195 BOOST_CHECK_CLOSE(market->discountCurve("GBP")->discount(today + 1 * Years), 0.9914, 0.0001);
196
197
198 Handle<IborIndex> iis = market->iborIndex("GBP-LIBOR-6M");
199 QL_REQUIRE(!iis.empty(), "GBP LIBOR 6M ibor Index not found");
200 BOOST_TEST_MESSAGE(
201 "CPISwap: Projected Libor fixing: " << market->iborIndex("GBP-LIBOR-6M")->forecastFixing(today + 1 * Years));
202
203
204 Handle<ZeroInflationIndex> infidx = market->zeroInflationIndex("UKRPI");
205 QL_REQUIRE(!infidx.empty(), "UKRPI inflation index not found");
206 BOOST_TEST_MESSAGE("CPISwap: Projected UKRPI rate: " << infidx->fixing(today + 1 * Years));
207
208
210
211
212 Date startDate = today;
213 Date endDate = today + 5 * Years;
214
215
216 std::ostringstream oss;
217 oss << io::iso_date(startDate);
218 string start(oss.str());
219 oss.str("");
220 oss.clear();
221 oss << io::iso_date(endDate);
222 string end(oss.str());
223
224
225 string conv = "MF";
226 string rule = "Forward";
229
230
231 bool isInArrears = false;
232 string dc = "ACT/ACT";
233 vector<Real> notional(1, 10000000);
234 string paymentConvention = "F";
235
236
237 bool isPayerLibor = true;
238 string indexLibor = "GBP-LIBOR-6M";
239 vector<Real> spread(1, 0);
240 LegData legLibor(QuantLib::ext::make_shared<FloatingLegData>(indexLibor, 0, isInArrears, spread), isPayerLibor,
"GBP",
241 scheduleLibor, "A365F", notional, vector<string>(), paymentConvention);
242
243
244 bool isPayerCPI = false;
245 string indexCPI = "UKRPI";
246 Real baseCPI = 210.0;
247 string CPIlag = "2M";
248 std::vector<double> fixedRate(1, 0.02);
249 bool interpolated = false;
251 QuantLib::ext::make_shared<CPILegData>(indexCPI, start, baseCPI, CPIlag, (interpolated ? "Linear" : "Flat"), fixedRate),
252 isPayerCPI, "GBP", scheduleCPI, dc, notional, vector<string>(), paymentConvention, false, true);
253
254
255 QuantLib::ext::shared_ptr<Trade> CPIswap(
new ore::data::Swap(env, legLibor, legCPI));
256
257
258 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
259 engineData->model("Swap") = "DiscountedCashflows";
260 engineData->engine("Swap") = "DiscountingSwapEngine";
261 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
262
263
264 QuantLib::ext::shared_ptr<Portfolio> portfolio(
new Portfolio());
265 CPIswap->id() = "CPI_Swap";
266
267 portfolio->add(CPIswap);
268 portfolio->build(engineFactory);
269
270
271 Schedule floatSchedule(startDate, endDate, 6 * Months, UnitedKingdom(), ModifiedFollowing, ModifiedFollowing,
272 DateGeneration::Forward, false);
273 Schedule cpiSchedule(startDate, endDate, 1 * Years, UnitedKingdom(), ModifiedFollowing, ModifiedFollowing,
274 DateGeneration::Forward, false);
275 Leg floatLeg = IborLeg(floatSchedule, *market->hGBP).withNotionals(10000000.0);
276 Leg cpiLeg =
CPILeg(cpiSchedule, *market->hUKRPI, baseCPI, 2 * Months)
282 auto pricer = QuantLib::ext::make_shared<CPICouponPricer>(market->hGBP->forwardingTermStructure());
283 for (auto const& c : cpiLeg) {
284 if (auto cpn = QuantLib::ext::dynamic_pointer_cast<CPICoupon>(c))
285 cpn->setPricer(pricer);
286 }
287
289 auto dscEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(market->hGBP->forwardingTermStructure());
290 qlSwap.setPricingEngine(dscEngine);
291 BOOST_TEST_MESSAGE("Leg 1 NPV: ORE = "
292 << QuantLib::ext::static_pointer_cast<QuantLib::Swap>(CPIswap->instrument()->qlInstrument())->legNPV(0)
293 << " QL = " << qlSwap.legNPV(0));
294 BOOST_TEST_MESSAGE("Leg 2 NPV: ORE = "
295 << QuantLib::ext::static_pointer_cast<QuantLib::Swap>(CPIswap->instrument()->qlInstrument())->legNPV(1)
296 << " QL = " << qlSwap.legNPV(1));
297 BOOST_CHECK_CLOSE(CPIswap->instrument()->NPV(), qlSwap.NPV(), 1E-8);
298}
CPILeg & withNotionals(Real notional)
CPILeg & withPaymentAdjustment(BusinessDayConvention)
CPILeg & withFixedRates(Real fixedRate)
CPILeg & withPaymentDayCounter(const DayCounter &)
CPILeg & withObservationInterpolation(CPI::InterpolationType)
Serializable object holding generic trade data, reporting dimensions.
Serializable object holding leg data.
Serializable schedule data.
Serializable object holding schedule Rules data.
Serializable Swap, Single and Cross Currency.