Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
mxnircurves.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>
29#include <oret/datapaths.hpp>
30#include <oret/toplevelfixture.hpp>
31
32#include <ql/cashflows/cashflows.hpp>
33#include <ql/cashflows/couponpricer.hpp>
34#include <ql/instruments/capfloor.hpp>
35#include <ql/pricingengines/capfloor/blackcapfloorengine.hpp>
36#include <ql/termstructures/volatility/optionlet/constantoptionletvol.hpp>
37#include <ql/time/calendar.hpp>
38#include <ql/time/daycounter.hpp>
39
40using namespace ore::data;
41using namespace QuantLib;
42using namespace boost::unit_test_framework;
43
44using ore::test::TopLevelFixture;
45using std::ostream;
46
47BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, TopLevelFixture)
48
49BOOST_AUTO_TEST_SUITE(MXNIrCurvesTest)
50
51// Test in-currency yield curve bootstrap
52BOOST_AUTO_TEST_CASE(testSingleCurrencyYieldCurveBootstrap) {
53
54 // Evaluation date
55 Date asof(17, Apr, 2019);
56 Settings::instance().evaluationDate() = asof;
57
58 // Market
59 auto conventions = QuantLib::ext::make_shared<Conventions>();
60 conventions->fromFile(TEST_INPUT_FILE("conventions_01.xml"));
61 InstrumentConventions::instance().setConventions(conventions);
62
63 auto todaysMarketParams = QuantLib::ext::make_shared<TodaysMarketParameters>();
64 todaysMarketParams->fromFile(TEST_INPUT_FILE("todaysmarket_01.xml"));
65 auto curveConfigs = QuantLib::ext::make_shared<CurveConfigurations>();
66 curveConfigs->fromFile(TEST_INPUT_FILE("curveconfig_01.xml"));
67 auto loader =
68 QuantLib::ext::make_shared<CSVLoader>(TEST_INPUT_FILE("market_01.txt"), TEST_INPUT_FILE("fixings.txt"), false);
69 QuantLib::ext::shared_ptr<TodaysMarket> market =
70 QuantLib::ext::make_shared<TodaysMarket>(asof, todaysMarketParams, loader, curveConfigs, false);
71
72 // Portfolio to test market
73 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
74 engineData->fromFile(TEST_INPUT_FILE("pricingengine_01.xml"));
75 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
76 QuantLib::ext::shared_ptr<Portfolio> portfolio = QuantLib::ext::make_shared<Portfolio>();
77 portfolio->fromFile(TEST_INPUT_FILE("mxn_ir_swap.xml"));
78 portfolio->build(factory);
79
80 // The single trade in the portfolio is a MXN 10Y swap, i.e. 10 x 13 28D coupons, with nominal 100 million. The
81 // rate on the swap is equal to the 10Y rate in the market file 'market_01.txt' so we should get an NPV of 0.
82 BOOST_CHECK_EQUAL(portfolio->size(), 1);
83 BOOST_CHECK_SMALL(portfolio->trades().begin()->second->instrument()->NPV(), 0.01);
84}
85
86// Test cross-currency yield curve bootstrap
87BOOST_AUTO_TEST_CASE(testCrossCurrencyYieldCurveBootstrap) {
88
89 // Evaluation date
90 Date asof(17, Apr, 2019);
91 Settings::instance().evaluationDate() = asof;
92
93 // Market
94 auto conventions = QuantLib::ext::make_shared<Conventions>();
95 conventions->fromFile(TEST_INPUT_FILE("conventions_02.xml"));
96 InstrumentConventions::instance().setConventions(conventions);
97
98 auto todaysMarketParams = QuantLib::ext::make_shared<TodaysMarketParameters>();
99 todaysMarketParams->fromFile(TEST_INPUT_FILE("todaysmarket_02.xml"));
100 auto curveConfigs = QuantLib::ext::make_shared<CurveConfigurations>();
101 curveConfigs->fromFile(TEST_INPUT_FILE("curveconfig_02.xml"));
102 auto loader =
103 QuantLib::ext::make_shared<CSVLoader>(TEST_INPUT_FILE("market_02.txt"), TEST_INPUT_FILE("fixings.txt"), false);
104 QuantLib::ext::shared_ptr<TodaysMarket> market =
105 QuantLib::ext::make_shared<TodaysMarket>(asof, todaysMarketParams, loader, curveConfigs, false);
106
107 // Portfolio to test market
108 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
109 engineData->fromFile(TEST_INPUT_FILE("pricingengine_02.xml"));
110 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
111 QuantLib::ext::shared_ptr<Portfolio> portfolio = QuantLib::ext::make_shared<Portfolio>();
112 portfolio->fromFile(TEST_INPUT_FILE("mxn_usd_xccy_swap.xml"));
113 portfolio->build(factory);
114
115 // The single trade in the portfolio is a USD/MXN 10Y cross currency basis swap, i.e. 10 x 13 28D coupons, with
116 // nominal USD 100 million. The spread on the swap is equal to the 10Y basis spread in the market file
117 // 'market_02.txt' so we should get an NPV of 0.
118 BOOST_CHECK_EQUAL(portfolio->size(), 1);
119 BOOST_CHECK_SMALL(portfolio->trades().begin()->second->instrument()->NPV(), 0.01);
120}
121
122// Test cap floor strip
123BOOST_AUTO_TEST_CASE(testCapFloorStrip) {
124
125 // Evaluation date
126 Date asof(17, Apr, 2019);
127 Settings::instance().evaluationDate() = asof;
128
129 // Market
130 auto conventions = QuantLib::ext::make_shared<Conventions>();
131 conventions->fromFile(TEST_INPUT_FILE("conventions_03.xml"));
132 InstrumentConventions::instance().setConventions(conventions);
133
134 auto todaysMarketParams = QuantLib::ext::make_shared<TodaysMarketParameters>();
135 todaysMarketParams->fromFile(TEST_INPUT_FILE("todaysmarket_03.xml"));
136 auto curveConfigs = QuantLib::ext::make_shared<CurveConfigurations>();
137 curveConfigs->fromFile(TEST_INPUT_FILE("curveconfig_03.xml"));
138 auto loader =
139 QuantLib::ext::make_shared<CSVLoader>(TEST_INPUT_FILE("market_03.txt"), TEST_INPUT_FILE("fixings.txt"), false);
140 QuantLib::ext::shared_ptr<TodaysMarket> market =
141 QuantLib::ext::make_shared<TodaysMarket>(asof, todaysMarketParams, loader, curveConfigs, false);
142
143 // Portfolio to test market
144 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
145 engineData->fromFile(TEST_INPUT_FILE("pricingengine_03.xml"));
146 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
147 QuantLib::ext::shared_ptr<Portfolio> portfolio = QuantLib::ext::make_shared<Portfolio>();
148 portfolio->fromFile(TEST_INPUT_FILE("mxn_ir_cap.xml"));
149 portfolio->build(factory);
150
151 // The single trade in the portfolio is a MXN 10Y cap, i.e. 10 x 13 28D coupons (without first caplet), with
152 // nominal USD 100 million.
153 BOOST_CHECK_EQUAL(portfolio->size(), 1);
154
155 // Get the npv of the trade using the market i.e. the stripped optionlet surface from TodaysMarket
156 Real npvTodaysMarket = portfolio->trades().begin()->second->instrument()->NPV();
157 BOOST_TEST_MESSAGE("NPV using TodaysMarket is: " << npvTodaysMarket);
158
159 // Price the same cap using the constant volatility from the market
160 auto trade = portfolio->trades().begin()->second;
161 BOOST_REQUIRE(trade);
162 BOOST_REQUIRE(trade->legs().size() == 1);
163 auto pricer = QuantLib::ext::make_shared<BlackIborCouponPricer>(Handle<OptionletVolatilityStructure>(
164 QuantLib::ext::make_shared<ConstantOptionletVolatility>(0, NullCalendar(), Unadjusted, 0.20320, Actual365Fixed())));
165 Leg leg = trade->legs().front();
166 setCouponPricer(leg, pricer);
167 Real npvMarketVol = CashFlows::npv(leg, **market->discountCurve("MXN"), false);
168 BOOST_TEST_MESSAGE("NPV using the constant market volatility is: " << npvMarketVol);
169
170 // Check the difference in the NPVs. Should be small if the stripping is working correctly.
171 BOOST_CHECK_SMALL(fabs(npvTodaysMarket - npvMarketVol), 0.01);
172}
173
174BOOST_AUTO_TEST_SUITE_END()
175
176BOOST_AUTO_TEST_SUITE_END()
Currency and instrument specific conventions/defaults.
Market Datum Loader Implementation.
Curve configuration repository.
Pricing Engine Factory.
void setCouponPricer(const Leg &leg, const boost::shared_ptr< FloatingRateCouponPricer > &)
BOOST_AUTO_TEST_CASE(testSingleCurrencyYieldCurveBootstrap)
Definition: mxnircurves.cpp:52
Portfolio class.
vector< string > curveConfigs
An concrete implementation of the Market class that loads todays market and builds the required curve...
A class to hold todays market configuration(s)
base trade data model and serialization