Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
zerocouponswap.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <boost/make_shared.hpp>
20#include <boost/test/unit_test.hpp>
28#include <oret/toplevelfixture.hpp>
29#include <ql/cashflows/iborcoupon.hpp>
30#include <ql/indexes/inflation/ukrpi.hpp>
31#include <ql/termstructures/yield/discountcurve.hpp>
32#include <ql/time/calendars/unitedkingdom.hpp>
33#include <ql/time/daycounters/actual365fixed.hpp>
34#include <ql/time/daycounters/actualactual.hpp>
36
37using namespace QuantLib;
38using namespace boost::unit_test_framework;
39using namespace ore::data;
40using std::vector;
41
42// Inflation CPI Swap paying fixed * CPI(t)/baseCPI * N
43// with last XNL N * (CPI(T)/baseCPI - 1)
44
45namespace {
46
47class TestMarket : public MarketImpl {
48public:
49 TestMarket() : MarketImpl(false) {
50 // valuation date
51 asof_ = Date(28, August, 2018);
52
53 // build vectors with dates and discount factors for GBP
54 vector<Date> datesGBP = {asof_,
55 asof_ + 6 * Months,
56 asof_ + 7 * Months,
57 asof_ + 8 * Months,
58 asof_ + 9 * Months,
59 asof_ + 10 * Months,
60 asof_ + 11 * Months,
61 asof_ + 12 * Months,
62 asof_ + 13 * Months,
63 asof_ + 14 * Months,
64 asof_ + 15 * Months,
65 asof_ + 16 * Months,
66 asof_ + 17 * Months,
67 asof_ + 18 * Months,
68 asof_ + 19 * Months,
69 asof_ + 20 * Months,
70 asof_ + 21 * Months,
71 asof_ + 22 * Months,
72 asof_ + 23 * Months,
73 asof_ + 2 * Years,
74 asof_ + 3 * Years,
75 asof_ + 4 * Years,
76 asof_ + 5 * Years,
77 asof_ + 6 * Years,
78 asof_ + 7 * Years,
79 asof_ + 8 * Years,
80 asof_ + 9 * Years,
81 asof_ + 10 * Years,
82 asof_ + 15 * Years,
83 asof_ + 20 * Years};
84
85 vector<DiscountFactor> dfsGBP = {1, 0.9955, 0.9953, 0.9947, 0.9941, 0.9933, 0.9924, 0.9914,
86 0.9908, 0.9901, 0.9895, 0.9888, 0.9881, 0.9874, 0.9868, 0.9862,
87 0.9855, 0.9849, 0.9842, 0.9836, 0.9743, 0.9634, 0.9510, 0.9361,
88 0.9192, 0.9011, 0.8822, 0.8637, 0.7792, 0.7079};
89
90 // build GBP discount curve
91 yieldCurves_[make_tuple(Market::defaultConfiguration, YieldCurveType::Discount, "GBP")] =
92 intDiscCurve(datesGBP, dfsGBP, ActualActual(ActualActual::ISDA), UnitedKingdom());
93
94 // build GBP Libor index
95 Handle<IborIndex> hGBP = Handle<IborIndex>(
96 parseIborIndex("GBP-LIBOR-6M", intDiscCurve(datesGBP, dfsGBP, ActualActual(ActualActual::ISDA), UnitedKingdom())));
97 iborIndices_[make_pair(Market::defaultConfiguration, "GBP-LIBOR-6M")] = hGBP;
98 }
99
100private:
101 Handle<YieldTermStructure> intDiscCurve(vector<Date> dates, vector<DiscountFactor> dfs, DayCounter dc,
102 Calendar cal) {
103 QuantLib::ext::shared_ptr<YieldTermStructure> idc(
104 new QuantLib::InterpolatedDiscountCurve<LogLinear>(dates, dfs, dc, cal));
105 return Handle<YieldTermStructure>(idc);
106 }
107};
108} // namespace
109
110BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
111
112BOOST_AUTO_TEST_SUITE(ZeroCouponSwapTests)
113
114BOOST_AUTO_TEST_CASE(testZeroCouponSwapPrice) {
115
116 BOOST_TEST_MESSAGE("Testing Zero Coupon Swap Price...");
117
118 // build market
119 Date today(28, August, 2018);
120 Settings::instance().evaluationDate() = today;
121 QuantLib::ext::shared_ptr<TestMarket> market = QuantLib::ext::make_shared<TestMarket>();
122 Date marketDate = market->asofDate();
123 BOOST_CHECK_EQUAL(today, marketDate);
124 Settings::instance().evaluationDate() = marketDate;
125
126 // Test if GBP discount curve is empty
127 Handle<YieldTermStructure> dts = market->discountCurve("GBP");
128 QL_REQUIRE(!dts.empty(), "GBP discount curve not found");
129 BOOST_CHECK_CLOSE(market->discountCurve("GBP")->discount(today + 1 * Years), 0.9914, 0.0001);
130
131 // Test if GBP Libor curve is empty
132 Handle<IborIndex> iis = market->iborIndex("GBP-LIBOR-6M");
133 QL_REQUIRE(!iis.empty(), "GBP LIBOR 6M ibor Index not found");
134 BOOST_TEST_MESSAGE(
135 "CPISwap: Projected Libor fixing: " << market->iborIndex("GBP-LIBOR-6M")->forecastFixing(today + 1 * Years));
136
137 // envelope
138 Envelope env("CP");
139
140 // Start/End date
141 Size years = 5;
142 Date startDate = today;
143 Date endDate = today + years * Years;
144
145 // date 2 string
146 std::ostringstream oss;
147 oss << io::iso_date(startDate);
148 string start(oss.str());
149 oss.str("");
150 oss.clear();
151 oss << io::iso_date(endDate);
152 string end(oss.str());
153
154 // Leg variables
155 vector<Real> notional(1, 1000000);
156 string paymentConvention = "MF";
157 Real rate = 0.02;
158 vector<Real> rates;
159 rates.push_back(rate);
160
161 // Schedule
162 string conv = "MF";
163 string rule = "Zero";
164 ScheduleData scheduleData(ScheduleRules(start, end, "5y", "UK", conv, conv, rule));
165 Schedule schedule = makeSchedule(scheduleData);
166 BOOST_CHECK_EQUAL(schedule.dates().size(), 2);
167
168 // GBP Libor Leg
169 bool isPayerLibor = true;
170 string indexLibor = "GBP-LIBOR-6M";
171 LegData leg(QuantLib::ext::make_shared<ZeroCouponFixedLegData>(rates), isPayerLibor, "GBP", scheduleData, "Year", notional,
172 vector<string>(), paymentConvention);
173
174 // Build swap trades
175 vector<LegData> legData;
176 legData.push_back(leg);
177 QuantLib::ext::shared_ptr<Trade> swap(new ore::data::Swap(env, legData));
178
179 // engine data and factory
180 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
181 engineData->model("Swap") = "DiscountedCashflows";
182 engineData->engine("Swap") = "DiscountingSwapEngine";
183 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
184
185 // build swaps and portfolio
186 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
187 swap->id() = "Swap";
188
189 portfolio->add(swap);
190 portfolio->build(engineFactory);
191
192 Date maturity = schedule.endDate();
193 Date fixedPayDate = schedule.calendar().adjust(maturity, parseBusinessDayConvention(paymentConvention));
194 Real df = market->discountCurve("GBP")->discount(fixedPayDate);
195 Real expectedNPV = -1 * notional.back() * (pow(1.0 + rate, years) - 1.0) * df;
196 BOOST_CHECK_CLOSE(swap->instrument()->NPV(), expectedNPV, 1E-8); // this is 1E-10 rel diff
197}
198
199BOOST_AUTO_TEST_SUITE_END()
200
201BOOST_AUTO_TEST_SUITE_END()
Engine builder for Swaps.
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Serializable object holding leg data.
Definition: legdata.hpp:844
static const string defaultConfiguration
Default configuration label.
Definition: market.hpp:296
Market Implementation.
Definition: marketimpl.hpp:53
map< tuple< string, YieldCurveType, string >, Handle< YieldTermStructure > > yieldCurves_
Definition: marketimpl.hpp:208
map< pair< string, string >, Handle< IborIndex > > iborIndices_
Definition: marketimpl.hpp:209
Serializable portfolio.
Definition: portfolio.hpp:43
Serializable schedule data.
Definition: schedule.hpp:202
Serializable object holding schedule Rules data.
Definition: schedule.hpp:37
Serializable Swap, Single and Cross Currency.
Definition: swap.hpp:36
A class to hold pricing engine parameters.
QuantLib::ext::shared_ptr< IborIndex > parseIborIndex(const string &s, const Handle< YieldTermStructure > &h)
Convert std::string to QuantLib::IborIndex.
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Definition: parsers.cpp:173
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
An implementation of the Market class that stores the required objects in maps.
Time maturity
Definition: utilities.cpp:66
RandomVariable pow(RandomVariable x, const RandomVariable &y)
Schedule makeSchedule(const ScheduleDates &data)
Definition: schedule.cpp:263
Portfolio class.
Swap trade data model and serialization.
BOOST_AUTO_TEST_CASE(testZeroCouponSwapPrice)