213 {
214
215 BOOST_TEST_MESSAGE("Testing commodity vol curve building with time dependent volatilities");
216
217
218 Date asof(5, Feb, 2016);
219
220
221 vector<string> quotes{"COMMODITY_OPTION/RATE_LNVOL/GOLD/USD/1Y/ATM/AtmFwd",
222 "COMMODITY_OPTION/RATE_LNVOL/GOLD/USD/2Y/ATM/AtmFwd",
223 "COMMODITY_OPTION/RATE_LNVOL/GOLD/USD/5Y/ATM/AtmFwd"};
224
225
226 vector<QuantLib::ext::shared_ptr<VolatilityConfig>> vcc;
227 vcc.push_back(QuantLib::ext::make_shared<VolatilityCurveConfig>(quotes, "Linear", "Flat"));
228
229
230 QuantLib::ext::shared_ptr<CommodityVolatilityConfig> curveConfig =
231 QuantLib::ext::make_shared<CommodityVolatilityConfig>("GOLD_USD_VOLS", "", "USD", vcc, "A365", "NullCalendar");
232
233
235 curveConfigs.add(CurveSpec::CurveType::CommodityVolatility,
"GOLD_USD_VOLS", curveConfig);
236
237
239
240
241 MockLoader loader;
242
243
245
246
247 QuantLib::ext::shared_ptr<CommodityVolCurve> curve;
248 BOOST_CHECK_NO_THROW(curve = QuantLib::ext::make_shared<CommodityVolCurve>(asof, curveSpec, loader,
curveConfigs));
249
250
251 QuantLib::ext::shared_ptr<BlackVolTermStructure> volatility = curve->volatility();
252 Real configuredVolatility;
253
254
255
256 configuredVolatility = 0.11;
257 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 1 * Years, 1000.0), configuredVolatility, testTolerance);
258 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 1 * Years, 1200.0), configuredVolatility, testTolerance);
259
260 configuredVolatility = 0.10;
261 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 2 * Years, 1000.0), configuredVolatility, testTolerance);
262 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 2 * Years, 1200.0), configuredVolatility, testTolerance);
263
264 configuredVolatility = 0.09;
265 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 5 * Years, 1000.0), configuredVolatility, testTolerance);
266 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 5 * Years, 1200.0), configuredVolatility, testTolerance);
267
268
269 Time t_s = volatility->dayCounter().yearFraction(asof, asof + 2 * Years);
270 Real v_s = 0.10;
271 Time t_e = volatility->dayCounter().yearFraction(asof, asof + 5 * Years);
272 Real v_e = 0.09;
273
274 Time t = volatility->dayCounter().yearFraction(asof, asof + 3 * Years);
275 Real v =
sqrt((v_s * v_s * t_s + (v_e * v_e * t_e - v_s * v_s * t_s) * (t - t_s) / (t_e - t_s)) / t);
276 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 3 * Years, 1000.0), v, testTolerance);
277 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 3 * Years, 1200.0), v, testTolerance);
278
279 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 6 * Years, 1000.0), v_e, testTolerance);
280 BOOST_CHECK_CLOSE(volatility->blackVol(asof + 6 * Years, 1200.0), v_e, testTolerance);
281}
RandomVariable sqrt(RandomVariable x)