Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
swaption.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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/termstructures/volatility/swaption/swaptionconstantvol.hpp>
30#include <ql/termstructures/yield/flatforward.hpp>
31#include <ql/time/calendars/target.hpp>
32#include <ql/time/daycounters/actualactual.hpp>
33
34using namespace QuantLib;
35using namespace boost::unit_test_framework;
36using namespace std;
37using namespace ore::data;
38
39namespace {
40
41class TestMarket : public MarketImpl {
42public:
43 TestMarket() : MarketImpl(false) {
44 asof_ = Date(2, January, 2017);
45
46 // build discount
47 yieldCurves_[make_tuple(Market::defaultConfiguration, YieldCurveType::Discount, "EUR")] = flatRateYts(0.03);
48
49 // build swaption vols
50 swaptionCurves_[make_pair(Market::defaultConfiguration, "EUR")] = flatSwaptionVol(0.30);
51
52 Handle<IborIndex> h(parseIborIndex("EUR-EURIBOR-6M", flatRateYts(0.03)));
53 iborIndices_[make_pair(Market::defaultConfiguration, "EUR-EURIBOR-6M")] = h;
54 }
55
56private:
57 Handle<YieldTermStructure> flatRateYts(Real forward) {
58 QuantLib::ext::shared_ptr<YieldTermStructure> yts(new FlatForward(0, NullCalendar(), forward, ActualActual(ActualActual::ISDA)));
59 return Handle<YieldTermStructure>(yts);
60 }
61 Handle<QuantLib::SwaptionVolatilityStructure>
62 flatSwaptionVol(Volatility forward, VolatilityType type = ShiftedLognormal, Real shift = 0.0) {
63 QuantLib::ext::shared_ptr<QuantLib::SwaptionVolatilityStructure> svs(
64 new QuantLib::ConstantSwaptionVolatility(Settings::instance().evaluationDate(), NullCalendar(),
65 ModifiedFollowing, forward, ActualActual(ActualActual::ISDA), type, shift));
66 return Handle<QuantLib::SwaptionVolatilityStructure>(svs);
67 }
68};
69} // namespace
70
71BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
72
73BOOST_AUTO_TEST_SUITE(EuropeanSwaptionTests)
74
75BOOST_AUTO_TEST_CASE(testEuropeanSwaptionPrice) {
76
77 BOOST_TEST_MESSAGE("Testing Swaption Price...");
78
79 Date today(3, Dec, 2018);
80 Settings::instance().evaluationDate() = today;
81
82 // build market
83 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
84 Settings::instance().evaluationDate() = market->asofDate();
85
86 // build Swaptions - expiry 5Y, term 10Y
87
88 Calendar calendar = TARGET();
89 Date qlStartDate = calendar.adjust(today + 5 * Years);
90 Date qlEndDate = calendar.adjust(qlStartDate + 10 * Years);
91 string startDate = ore::data::to_string(qlStartDate);
92 string endDate = ore::data::to_string(qlEndDate);
93
94 // schedules
95 ScheduleData floatSchedule(ScheduleRules(startDate, endDate, "6M", "TARGET", "MF", "MF", "Forward"));
96 ScheduleData fixedSchedule(ScheduleRules(startDate, endDate, "1Y", "TARGET", "MF", "MF", "Forward"));
97 // fixed leg
98 LegData fixedLeg(QuantLib::ext::make_shared<FixedLegData>(std::vector<Real>(1, 0.03)), true, "EUR", fixedSchedule, "30/360",
99 std::vector<Real>(1, 10000.0));
100 // float leg
101 LegData floatingLeg(QuantLib::ext::make_shared<FloatingLegData>("EUR-EURIBOR-6M", 2, false, std::vector<Real>(1, 0.0)),
102 false, "EUR", floatSchedule, "A360", std::vector<Real>(1, 10000.0));
103 // leg vector
104 vector<LegData> legs;
105 legs.push_back(fixedLeg);
106 legs.push_back(floatingLeg);
107
108 Envelope env("CP1");
109 OptionData optionData("Long", "Call", "European", true, vector<string>(1, startDate), "Cash");
110 OptionData optionDataPhysical("Long", "Call", "European", true, vector<string>(1, startDate), "Physical");
111 Real premium = 700.0;
112 OptionData optionDataPremium("Long", "Call", "European", true, vector<string>(1, startDate), "Cash", "",
113 PremiumData(premium, "EUR", qlStartDate));
114 ore::data::Swaption swaptionCash(env, optionData, legs);
115 ore::data::Swaption swaptionPhysical(env, optionDataPhysical, legs);
116 ore::data::Swaption swaptionPremium(env, optionDataPremium, legs);
117
118 Real expectedNpvCash = 565.19;
119 Real premiumNpv = premium * market->discountCurve("EUR")->discount(calendar.adjust(qlStartDate));
120 Real expectedNpvPremium = expectedNpvCash - premiumNpv;
121
122 // Build and price
123 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
124 engineData->model("EuropeanSwaption") = "BlackBachelier";
125 engineData->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
126 engineData->model("Swap") = "DiscountedCashflows";
127 engineData->engine("Swap") = "DiscountingSwapEngine";
128 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
129
130 swaptionCash.build(engineFactory);
131 swaptionPhysical.build(engineFactory);
132 swaptionPremium.build(engineFactory);
133
134 Real npvCash = swaptionCash.instrument()->NPV();
135 Real npvPhysical = swaptionPhysical.instrument()->NPV();
136 Real npvPremium = swaptionPremium.instrument()->NPV();
137
138 BOOST_TEST_MESSAGE("Swaption, NPV Currency " << swaptionCash.npvCurrency());
139 BOOST_TEST_MESSAGE("NPV Cash = " << npvCash);
140 BOOST_TEST_MESSAGE("NPV Physical = " << npvPhysical);
141 BOOST_TEST_MESSAGE("NPV Cash with premium = " << npvPremium);
142
143 BOOST_CHECK_SMALL(npvCash - expectedNpvCash, 0.01);
144 BOOST_CHECK_SMALL(npvPremium - expectedNpvPremium, 0.01);
145}
146
147BOOST_AUTO_TEST_SUITE_END()
148
149BOOST_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
map< pair< string, string >, Handle< QuantLib::SwaptionVolatilityStructure > > swaptionCurves_
Definition: marketimpl.hpp:211
Serializable object holding option data.
Definition: optiondata.hpp:42
Serializable object holding premium data.
Definition: premiumdata.hpp:37
Serializable schedule data.
Definition: schedule.hpp:202
Serializable object holding schedule Rules data.
Definition: schedule.hpp:37
Serializable Swaption.
Definition: swaption.hpp:39
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Definition: swaption.cpp:62
const QuantLib::ext::shared_ptr< InstrumentWrapper > & instrument() const
Definition: trade.hpp:141
const string & npvCurrency() const
Definition: trade.hpp:149
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.
Map text representations to QuantLib/QuantExt types.
An implementation of the Market class that stores the required objects in maps.
Calendar calendar
Definition: utilities.cpp:441
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Swaption data model and serialization.
BOOST_AUTO_TEST_CASE(testEuropeanSwaptionPrice)
Definition: swaption.cpp:75
string conversion utilities