19#include <boost/make_shared.hpp>
20#include <boost/test/unit_test.hpp>
28#include <oret/toplevelfixture.hpp>
29#include <ql/termstructures/yield/discountcurve.hpp>
30#include <ql/time/calendars/target.hpp>
31#include <ql/time/calendars/unitedstates.hpp>
32#include <ql/time/daycounters/actual360.hpp>
35using namespace boost::unit_test_framework;
45 asof_ = Date(22, Aug, 2016);
47 QuantLib::ext::shared_ptr<ore::data::Conventions> conventions = QuantLib::ext::make_shared<Conventions>();
48 conventions->add(QuantLib::ext::make_shared<ore::data::FXConvention>(
"EUR-USD-FX",
"0",
"EUR",
"USD",
"10000",
50 InstrumentConventions::instance().setConventions(conventions);
53 vector<Date> datesEUR = {
asof_,
72 vector<Date> datesUSD = {
asof_,
85 vector<DiscountFactor> dfsEUR = {1.0, 1.000972, 1.001138, 1.001309, 1.001452, 1.001663, 1.001826,
86 1.002005, 1.002196, 1.002369, 1.002554, 1.00275, 1.002918, 1.003114,
87 1.004134, 1.006005, 1.007114, 1.006773, 1.004282};
88 vector<DiscountFactor> dfsUSD = {1.0, 0.997872, 0.997147, 0.99499, 0.992416, 0.989948, 0.987405,
89 0.984774, 0.980358, 0.96908, 0.95704, 0.944041, 0.93004};
93 intDiscCurve(datesEUR, dfsEUR, Actual360(), TARGET());
95 intDiscCurve(datesUSD, dfsUSD, Actual360(), UnitedStates(UnitedStates::Settlement));
98 Handle<IborIndex> hEUR(
parseIborIndex(
"EUR-EURIBOR-6M", intDiscCurve(datesEUR, dfsEUR, Actual360(), TARGET())));
102 hEUR->addFixing(Date(18, Aug, 2016), -0.00191);
103 Handle<IborIndex> hUSD(
104 parseIborIndex(
"USD-LIBOR-3M", intDiscCurve(datesUSD, dfsUSD, Actual360(), UnitedStates(UnitedStates::Settlement))));
108 hUSD->addFixing(Date(18, Aug, 2016), 0.00811);
111 std::map<std::string, Handle<Quote>> quotes;
112 quotes[
"EURUSD"] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.1306));
113 fx_ = QuantLib::ext::make_shared<FXTriangulation>(quotes);
117 Handle<YieldTermStructure> intDiscCurve(vector<Date> dates, vector<DiscountFactor> dfs, DayCounter dc,
119 QuantLib::ext::shared_ptr<YieldTermStructure> idc(
120 new QuantLib::InterpolatedDiscountCurve<LogLinear>(dates, dfs, dc, cal));
121 return Handle<YieldTermStructure>(idc);
126BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
128BOOST_AUTO_TEST_SUITE(CcySwapWithResetsTest)
133 BOOST_TEST_MESSAGE(
"Testing CcySwapWithResets Price...");
136 Real npvCCYswap = -349.69;
137 Real npvCCYswapReset = 0;
140 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
141 Settings::instance().evaluationDate() = market->asofDate();
144 Date today = market->asofDate();
145 BOOST_CHECK_EQUAL(today, Date(22, Aug, 2016));
148 Handle<YieldTermStructure> dts = market->discountCurve(
"EUR");
149 QL_REQUIRE(!dts.empty(),
"EUR discount curve not found");
152 BOOST_CHECK_CLOSE(market->discountCurve(
"EUR")->discount(today + 3 * Years), 1.006005, 0.0001);
155 BOOST_CHECK_CLOSE(market->discountCurve(
"USD")->discount(today + 3 * Years), 0.96908, 0.0001);
158 BOOST_CHECK_EQUAL(market->fxSpot(
"EURUSD")->value(), 1.1306);
164 Date startDate = today;
165 Date endDate = today + 5 * Years;
168 std::ostringstream oss;
169 oss << io::iso_date(startDate);
170 string start(oss.str());
173 oss << io::iso_date(endDate);
174 string end(oss.str());
178 string rule =
"Forward";
183 bool isPayerEUR =
true;
184 string indexEUR =
"EUR-EURIBOR-6M";
185 bool isInArrears =
false;
187 vector<Real> spreadEUR(1, 0.000261);
188 string dc =
"ACT/360";
189 vector<Real> notionalEUR(1, 8833141.95);
190 string paymentConvention =
"F";
191 bool notionalInitialXNL =
true;
192 bool notionalFinalXNL =
true;
193 bool notionalAmortizingXNL =
false;
194 string foreignCCY =
"USD";
195 Real foreignAmount = 10000000;
196 string fxIndex =
"FX-ECB-EUR-USD";
197 auto legdataEUR = QuantLib::ext::make_shared<FloatingLegData>(indexEUR, days, isInArrears, spreadEUR);
198 LegData legEUR1(legdataEUR, isPayerEUR,
"EUR", scheduleEUR, dc, notionalEUR, vector<string>(), paymentConvention,
199 notionalInitialXNL, notionalFinalXNL, notionalAmortizingXNL, notionalFinalXNL, foreignCCY,
200 foreignAmount, fxIndex);
201 LegData legEUR2(legdataEUR, isPayerEUR,
"EUR", scheduleEUR, dc, notionalEUR, vector<string>(), paymentConvention,
202 notionalInitialXNL, notionalFinalXNL, notionalAmortizingXNL,
false, foreignCCY, foreignAmount,
206 bool isPayerUSD =
false;
207 string indexUSD =
"USD-LIBOR-3M";
208 vector<Real> spreadUSD(1, 0);
209 vector<Real> notionalUSD(1, 10000000);
210 auto legdataUSD = QuantLib::ext::make_shared<FloatingLegData>(indexUSD, days, isInArrears, spreadUSD);
211 LegData legUSD(legdataUSD, isPayerUSD,
"USD", scheduleUSD, dc, notionalUSD, vector<string>(), paymentConvention,
212 notionalInitialXNL, notionalFinalXNL, notionalAmortizingXNL);
215 QuantLib::ext::shared_ptr<Trade> swap1(
new ore::data::Swap(env, legUSD, legEUR1));
216 QuantLib::ext::shared_ptr<Trade> swap2(
new ore::data::Swap(env, legUSD, legEUR2));
219 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
220 engineData->model(
"CrossCurrencySwap") =
"DiscountedCashflows";
221 engineData->engine(
"CrossCurrencySwap") =
"DiscountingCrossCurrencySwapEngine";
222 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
225 QuantLib::ext::shared_ptr<Portfolio> portfolio(
new Portfolio());
226 swap1->id() =
"XCCY_Swap_EUR_USD";
227 swap2->id() =
"XCCY_Swap_EUR_USD_RESET";
229 portfolio->add(swap1);
230 portfolio->add(swap2);
231 portfolio->build(engineFactory);
234 BOOST_TEST_MESSAGE(
"CcySwap Price = " << swap1->instrument()->NPV() <<
" " << swap1->npvCurrency()
235 <<
". BBG Price = " << npvCCYswap <<
" USD");
237 BOOST_CHECK_CLOSE(std::abs(swap1->instrument()->NPV() - npvCCYswap), 250, 5);
240 BOOST_TEST_MESSAGE(
"CcySwapReset Price = " << swap2->instrument()->NPV() <<
" " << swap2->npvCurrency()
241 <<
". BBG Price = " << npvCCYswapReset <<
" USD");
243 BOOST_CHECK_CLOSE(std::abs(swap2->instrument()->NPV() - npvCCYswapReset), 250, 5);
247 const vector<Leg>& legs = swap2->legs();
248 for (Size i = 3; i < legs.size(); i++) {
249 const QuantLib::Leg& leg = legs[i];
250 for (Size j = 0; j < leg.size(); j++) {
251 QuantLib::ext::shared_ptr<QuantLib::CashFlow> ptrFlow = leg[j];
252 sumXNL += ptrFlow->amount();
255 BOOST_CHECK_EQUAL(sumXNL, 0);
258BOOST_AUTO_TEST_SUITE_END()
260BOOST_AUTO_TEST_SUITE_END()
Engine builder for Swaps.
BOOST_AUTO_TEST_CASE(testCcySwapWithResetsPrice)
Serializable object holding generic trade data, reporting dimensions.
Serializable object holding leg data.
static const string defaultConfiguration
Default configuration label.
QuantLib::ext::shared_ptr< FXTriangulation > fx_
map< tuple< string, YieldCurveType, string >, Handle< YieldTermStructure > > yieldCurves_
map< pair< string, string >, Handle< IborIndex > > iborIndices_
Serializable schedule data.
Serializable object holding schedule Rules data.
Serializable Swap, Single and Cross Currency.
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.
Classes and functions for log message handling.
An implementation of the Market class that stores the required objects in maps.
Swap trade data model and serialization.