#include"andreasenhugevolatilityinterpl.hpp"#include"utilities.hpp"#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusingnamespace QuantLib;usingnamespace boost::unit_test_framework;namespace andreasen_huge_volatility_interpl_test {structCalibrationData{const Handle<Quote> spot;Handle<YieldTermStructure> rTS, qTS;AndreasenHugeVolatilityInterpl::CalibrationSet calibrationSet;};structCalibrationResults{AndreasenHugeVolatilityInterpl::CalibrationType calibrationType;AndreasenHugeVolatilityInterpl::InterpolationType interpolationType;Real maxError, avgError;Real lvMaxError, lvAvgError;};CalibrationData AndreasenHugeExampleData(){// This is the example market data from the original paper// Andreasen J., Huge B., 2010. Volatility Interpolation// https://ssrn.com/abstract=1694972const Handle<Quote>spot(ext::make_shared<SimpleQuote>(2772.7));const Time maturityTimes[]={0.025,0.101,0.197,0.274,0.523,0.772,1.769,2.267,2.784,3.781,4.778,5.774};const Real raw[][13]={{0.5131,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.3366,0.3291,0.0000,0.0000},{0.5864,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.3178,0.3129,0.3008,0.0000},{0.6597,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.3019,0.2976,0.2975,0.0000},{0.7330,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.2863,0.2848,0.2848,0.0000},{0.7697,0.0000,0.0000,0.0000,0.3262,0.3079,0.3001,0.2843,0.0000,0.0000,0.0000,0.0000,0.0000},{0.8063,0.0000,0.0000,0.0000,0.3058,0.2936,0.2876,0.2753,0.2713,0.2711,0.2711,0.2722,0.2809},{0.8430,0.0000,0.0000,0.0000,0.2887,0.2798,0.2750,0.2666,0.0000,0.0000,0.0000,0.0000,0.0000},{0.8613,0.3365,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{0.8796,0.3216,0.2906,0.2764,0.2717,0.2663,0.2637,0.2575,0.2555,0.2580,0.2585,0.2611,0.2693},{0.8979,0.3043,0.2797,0.2672,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{0.9163,0.2880,0.2690,0.2578,0.2557,0.2531,0.2519,0.2497,0.0000,0.0000,0.0000,0.0000,0.0000},{0.9346,0.2724,0.2590,0.2489,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{0.9529,0.2586,0.2488,0.2405,0.2407,0.2404,0.2411,0.2418,0.2410,0.2448,0.2469,0.2501,0.2584},{0.9712,0.2466,0.2390,0.2329,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{0.9896,0.2358,0.2300,0.2253,0.2269,0.2284,0.2299,0.2347,0.0000,0.0000,0.0000,0.0000,0.0000},{1.0079,0.2247,0.2213,0.2184,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{1.0262,0.2159,0.2140,0.2123,0.2142,0.2173,0.2198,0.2283,0.2275,0.2322,0.2384,0.2392,0.2486},{1.0445,0.2091,0.2076,0.2069,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{1.0629,0.2056,0.2024,0.2025,0.2039,0.2074,0.2104,0.2213,0.0000,0.0000,0.0000,0.0000,0.0000},{1.0812,0.2045,0.1982,0.1984,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{1.0995,0.2025,0.1959,0.1944,0.1962,0.1988,0.2022,0.2151,0.2161,0.2219,0.2269,0.2305,0.2399},{1.1178,0.1933,0.1929,0.1920,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000},{1.1362,0.0000,0.0000,0.0000,0.1902,0.1914,0.1950,0.2091,0.0000,0.0000,0.0000,0.0000,0.0000},{1.1728,0.0000,0.0000,0.0000,0.1885,0.1854,0.1888,0.2039,0.2058,0.2122,0.2186,0.2223,0.2321},{1.2095,0.0000,0.0000,0.0000,0.1867,0.1811,0.1839,0.1990,0.0000,0.0000,0.0000,0.0000,0.0000},{1.2461,0.0000,0.0000,0.0000,0.1871,0.1785,0.1793,0.1945,0.0000,0.2054,0.2103,0.2164,0.2251},{1.3194,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.1988,0.2054,0.2105,0.2190},{1.3927,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.1930,0.2002,0.2054,0.2135},{1.4660,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.1849,0.1964,0.2012,0.0000}};const DayCounter dc =Actual365Fixed();const Date today =Date(1, March,2010);const Handle<YieldTermStructure>rTS(flatRate(today,0.0, dc));const Handle<YieldTermStructure>qTS(flatRate(today,0.0, dc));const Size nStrikes =LENGTH(raw);const Size nMaturities =LENGTH(maturityTimes);QL_REQUIRE(nMaturities ==LENGTH(raw[1])-1,"check raw data");AndreasenHugeVolatilityInterpl::CalibrationSet calibrationSet;calibrationSet.reserve(std::count_if(&raw[0][0],&raw[nStrikes-1][nMaturities]+1,[](Real x){return x !=0.0;})- nStrikes);for(constauto& i : raw){const Real strike = spot->value()*i[0];for(Size j=1; j <LENGTH(i);++j){if(i[j]> QL_EPSILON){const Date maturity= today +Period(Size(365*maturityTimes[j-1]), Days);const Volatility