20#include <boost/make_shared.hpp>
21#include <boost/test/unit_test.hpp>
22#include <ql/currencies/all.hpp>
23#include <ql/indexes/ibor/usdlibor.hpp>
24#include <ql/quotes/simplequote.hpp>
25#include <ql/termstructures/yield/discountcurve.hpp>
26#include <ql/termstructures/yield/flatforward.hpp>
27#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
28#include <ql/time/calendars/all.hpp>
29#include <ql/time/daycounters/actual360.hpp>
30#include <ql/types.hpp>
35using namespace boost::unit_test_framework;
44 Natural settlementDays;
46 BusinessDayConvention payConvention;
49 Currency fixedCurrency;
50 Frequency fixedFrequency;
51 DayCounter fixedDayCount;
57 QuantLib::ext::shared_ptr<SimpleQuote> spotFx;
59 QuantLib::ext::shared_ptr<SimpleQuote> spread;
61 Handle<YieldTermStructure> liborProjCurve;
63 QuantLib::ext::shared_ptr<IborIndex> index;
65 Handle<YieldTermStructure> usdDiscCurve;
68 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwapHelper>
helper;
71 asof = Date(11, Sep, 2018);
73 payCalendar = JointCalendar(UnitedStates(UnitedStates::Settlement), UnitedKingdom(), Turkey());
74 payConvention = Following;
77 fixedCurrency = TRYCurrency();
78 fixedFrequency = Annual;
79 fixedDayCount = Actual360();
80 usdNominal = 10000000.0;
82 rate = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.25));
83 spotFx = QuantLib::ext::make_shared<SimpleQuote>(6.4304);
84 spread = QuantLib::ext::make_shared<SimpleQuote>(0.0);
86 Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.029773, Actual365Fixed()));
87 index = QuantLib::ext::make_shared<USDLibor>(3 * Months, liborProjCurve);
89 Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.026727, Actual365Fixed()));
93QuantLib::ext::shared_ptr<CrossCcyFixFloatSwap> makeTestSwap(
const CommonVars& vars,
94 const Handle<YieldTermStructure>& discCurve) {
97 Date referenceDate = Settings::instance().evaluationDate();
98 referenceDate = vars.payCalendar.adjust(referenceDate);
99 Date start = vars.payCalendar.advance(referenceDate, vars.settlementDays * Days);
100 Date end = start + vars.tenor;
103 Schedule fixedSchedule(start, end, Period(vars.fixedFrequency), vars.payCalendar, vars.payConvention,
104 vars.payConvention, DateGeneration::Backward,
false);
107 Schedule floatSchedule(start, end, vars.index->tenor(), vars.payCalendar, vars.payConvention, vars.payConvention,
108 DateGeneration::Backward,
false);
113 vars.rate->value(), vars.fixedDayCount, vars.payConvention, vars.payLag, vars.payCalendar, vars.usdNominal,
114 vars.index->currency(), floatSchedule, vars.index, vars.spread->value(), vars.payConvention, vars.payLag,
118 QuantLib::ext::shared_ptr<PricingEngine> engine = QuantLib::ext::make_shared<CrossCcySwapEngine>(
119 vars.fixedCurrency, discCurve, vars.index->currency(), vars.usdDiscCurve, Handle<Quote>(vars.spotFx));
120 swap->setPricingEngine(engine);
126Handle<YieldTermStructure> bootstrappedCurve(CommonVars& vars) {
129 vector<QuantLib::ext::shared_ptr<RateHelper> > helpers(1);
131 vars.rate, Handle<Quote>(vars.spotFx), vars.settlementDays, vars.payCalendar, vars.payConvention, vars.tenor,
132 vars.fixedCurrency, vars.fixedFrequency, vars.payConvention, vars.fixedDayCount, vars.index, vars.usdDiscCurve,
133 Handle<Quote>(vars.spread)));
134 helpers[0] = vars.helper;
137 return Handle<YieldTermStructure>(
138 QuantLib::ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear> >(0, NullCalendar(), helpers, Actual365Fixed()));
145BOOST_AUTO_TEST_SUITE(CrossCurrencyFixFloatSwapHelperTest)
149 BOOST_TEST_MESSAGE(
"Test simple bootstrap against cross currency fix float swap");
151 SavedSettings backup;
155 Settings::instance().evaluationDate() = vars.asof;
158 Handle<YieldTermStructure> tryDiscCurve = bootstrappedCurve(vars);
161 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwap> swap = makeTestSwap(vars, tryDiscCurve);
165 BOOST_CHECK_SMALL(swap->NPV(), absTol);
169 BOOST_CHECK_CLOSE(vars.rate->value(), swap->fairFixedRate(), relTol);
172 DiscountFactor expDisc = 0.3299260408883904;
173 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
178 BOOST_TEST_MESSAGE(
"Test rebootstrap under spot FX change");
180 SavedSettings backup;
184 Settings::instance().evaluationDate() = vars.asof;
187 Handle<YieldTermStructure> tryDiscCurve = bootstrappedCurve(vars);
190 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwap> swap = makeTestSwap(vars, tryDiscCurve);
194 BOOST_CHECK_SMALL(swap->NPV(), absTol);
198 DiscountFactor expDisc = 0.3299260408883904;
199 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
202 BOOST_CHECK_CLOSE(vars.spotFx->value(), vars.helper->swap()->fixedNominal(), relTol);
205 vars.spotFx->setValue(vars.spotFx->value() * 1.1);
208 swap = makeTestSwap(vars, tryDiscCurve);
211 BOOST_CHECK_SMALL(swap->NPV(), absTol);
214 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
217 BOOST_CHECK_CLOSE(vars.spotFx->value(), vars.helper->swap()->fixedNominal(), relTol);
222 BOOST_TEST_MESSAGE(
"Test rebootstrap under helper spread change");
224 SavedSettings backup;
228 Settings::instance().evaluationDate() = vars.asof;
231 Handle<YieldTermStructure> tryDiscCurve = bootstrappedCurve(vars);
234 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwap> swap = makeTestSwap(vars, tryDiscCurve);
238 BOOST_CHECK_SMALL(swap->NPV(), absTol);
242 DiscountFactor expDisc = 0.3299260408883904;
243 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
246 BOOST_CHECK_CLOSE(vars.spread->value(), vars.helper->swap()->floatSpread(), relTol);
249 vars.spread->setValue(0.0010);
252 swap = makeTestSwap(vars, tryDiscCurve);
255 BOOST_CHECK_SMALL(swap->NPV(), absTol);
258 expDisc = 0.3322218009717460;
259 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
262 BOOST_CHECK_CLOSE(vars.spread->value(), vars.helper->swap()->floatSpread(), relTol);
267 BOOST_TEST_MESSAGE(
"Test rebootstrap after moving evaluation date");
269 SavedSettings backup;
273 Settings::instance().evaluationDate() = vars.asof;
276 Handle<YieldTermStructure> tryDiscCurve = bootstrappedCurve(vars);
279 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwap> swap = makeTestSwap(vars, tryDiscCurve);
283 BOOST_CHECK_SMALL(swap->NPV(), absTol);
287 DiscountFactor expDisc = 0.3299260408883904;
288 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
291 BOOST_CHECK_EQUAL(swap->startDate(), vars.helper->swap()->startDate());
294 vars.asof = vars.asof + 1 * Days;
295 Settings::instance().evaluationDate() = vars.asof;
298 swap = makeTestSwap(vars, tryDiscCurve);
301 BOOST_CHECK_SMALL(swap->NPV(), absTol);
304 expDisc = 0.3299334970640459;
305 BOOST_CHECK_CLOSE(expDisc, tryDiscCurve->discount(vars.asof + 5 * Years), relTol);
308 BOOST_CHECK_EQUAL(swap->startDate(), vars.helper->swap()->startDate());
311BOOST_AUTO_TEST_SUITE_END()
313BOOST_AUTO_TEST_SUITE_END()
Cross currency fix vs. float swap helper.
Cross currency fixed vs. float swap helper.
Cross currency swap engine.
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
BOOST_AUTO_TEST_CASE(testBootstrap)
Fixture that can be used at top level.