public void testCachedHullWhite() { //("Testing Hull-White calibration against cached values..."); Date today=new Date(15, Month.February, 2002); Date settlement=new Date(19, Month.February, 2002); Settings.setEvaluationDate(today); Handle<YieldTermStructure> termStructure= new Handle<YieldTermStructure>(Utilities.flatRate(settlement, 0.04875825, new Actual365Fixed())); //termStructure.link HullWhite model=new HullWhite(termStructure); CalibrationData[] data = { new CalibrationData( 1, 5, 0.1148 ), new CalibrationData( 2, 4, 0.1108 ), new CalibrationData( 3, 3, 0.1070 ), new CalibrationData( 4, 2, 0.1021 ), new CalibrationData( 5, 1, 0.1000 )}; IborIndex index = new Euribor6M(termStructure); IPricingEngine engine = new JamshidianSwaptionEngine(model); List<CalibrationHelper> swaptions = new List<CalibrationHelper>(); for (int i=0; i<data.Length; i++) { Quote vol = new SimpleQuote(data[i].volatility); CalibrationHelper helper = new SwaptionHelper(new Period(data[i].start,TimeUnit.Years), new Period(data[i].length, TimeUnit.Years), new Handle<Quote>(vol), index, new Period(1, TimeUnit.Years), new Thirty360(), new Actual360(), termStructure); helper.setPricingEngine(engine); swaptions.Add(helper); } // Set up the optimization problem // Real simplexLambda = 0.1; // Simplex optimizationMethod(simplexLambda); LevenbergMarquardt optimizationMethod = new LevenbergMarquardt(1.0e-8,1.0e-8,1.0e-8); EndCriteria endCriteria = new EndCriteria(10000, 100, 1e-6, 1e-8, 1e-8); //Optimize model.calibrate(swaptions, optimizationMethod, endCriteria, new Constraint(),new List<double>()); EndCriteria.Type ecType = model.endCriteria(); // Check and print out results #if QL_USE_INDEXED_COUPON double cachedA = 0.0488199, cachedSigma = 0.00593579; #else double cachedA = 0.0488565, cachedSigma = 0.00593662; #endif double tolerance = 1.120e-5; //double tolerance = 1.0e-6; Vector xMinCalculated = model.parameters(); double yMinCalculated = model.value(xMinCalculated, swaptions); Vector xMinExpected = new Vector(2); xMinExpected[0]= cachedA; xMinExpected[1]= cachedSigma; double yMinExpected = model.value(xMinExpected, swaptions); if (Math.Abs(xMinCalculated[0]-cachedA) > tolerance || Math.Abs(xMinCalculated[1]-cachedSigma) > tolerance) { Assert.Fail ("Failed to reproduce cached calibration results:\n" + "calculated: a = " + xMinCalculated[0] + ", " + "sigma = " + xMinCalculated[1] + ", " + "f(a) = " + yMinCalculated + ",\n" + "expected: a = " + xMinExpected[0] + ", " + "sigma = " + xMinExpected[1] + ", " + "f(a) = " + yMinExpected + ",\n" + "difference: a = " + (xMinCalculated[0]-xMinExpected[0]) + ", " + "sigma = " + (xMinCalculated[1]-xMinExpected[1]) + ", " + "f(a) = " + (yMinCalculated - yMinExpected) + ",\n" + "end criteria = " + ecType ); } }
public void testCalibration() { //("Testing calibration of a Libor forward model..."); //SavedSettings backup; const int size = 14; const double tolerance = 8e-3; double[] capVols = {0.145708,0.158465,0.166248,0.168672, 0.169007,0.167956,0.166261,0.164239, 0.162082,0.159923,0.157781,0.155745, 0.153776,0.151950,0.150189,0.148582, 0.147034,0.145598,0.144248}; double[] swaptionVols = {0.170595, 0.166844, 0.158306, 0.147444, 0.136930, 0.126833, 0.118135, 0.175963, 0.166359, 0.155203, 0.143712, 0.132769, 0.122947, 0.114310, 0.174455, 0.162265, 0.150539, 0.138734, 0.128215, 0.118470, 0.110540, 0.169780, 0.156860, 0.144821, 0.133537, 0.123167, 0.114363, 0.106500, 0.164521, 0.151223, 0.139670, 0.128632, 0.119123, 0.110330, 0.103114, 0.158956, 0.146036, 0.134555, 0.124393, 0.115038, 0.106996, 0.100064}; IborIndex index = makeIndex(); LiborForwardModelProcess process = new LiborForwardModelProcess(size, index); Handle<YieldTermStructure> termStructure = index.forwardingTermStructure(); // set-up the model LmVolatilityModel volaModel = new LmExtLinearExponentialVolModel(process.fixingTimes(), 0.5,0.6,0.1,0.1); LmCorrelationModel corrModel = new LmLinearExponentialCorrelationModel(size, 0.5, 0.8); LiborForwardModel model = new LiborForwardModel(process, volaModel, corrModel); int swapVolIndex = 0; DayCounter dayCounter = index.forwardingTermStructure().link.dayCounter(); // set-up calibration helper List<CalibrationHelper> calibrationHelper = new List<CalibrationHelper>(); int i; for (i=2; i < size; ++i) { Period maturity = i*index.tenor(); Handle<Quote> capVol = new Handle<Quote>(new SimpleQuote(capVols[i-2])); CalibrationHelper caphelper = new CapHelper(maturity, capVol, index,Frequency.Annual, index.dayCounter(), true, termStructure, CalibrationHelper.CalibrationErrorType.ImpliedVolError); caphelper.setPricingEngine(new AnalyticCapFloorEngine(model, termStructure)); calibrationHelper.Add(caphelper); if (i<= size/2) { // add a few swaptions to test swaption calibration as well for (int j=1; j <= size/2; ++j) { Period len = j*index.tenor(); Handle<Quote> swaptionVol = new Handle<Quote>( new SimpleQuote(swaptionVols[swapVolIndex++])); CalibrationHelper swaptionHelper = new SwaptionHelper(maturity, len, swaptionVol, index, index.tenor(), dayCounter, index.dayCounter(), termStructure, CalibrationHelper.CalibrationErrorType.ImpliedVolError ); swaptionHelper.setPricingEngine(new LfmSwaptionEngine(model,termStructure)); calibrationHelper.Add(swaptionHelper); } } } LevenbergMarquardt om = new LevenbergMarquardt(1e-6, 1e-6, 1e-6); //ConjugateGradient gc = new ConjugateGradient(); model.calibrate(calibrationHelper, om, new EndCriteria(2000, 100, 1e-6, 1e-6, 1e-6), new Constraint(), new List<double>()); // measure the calibration error double calculated = 0.0; for (i=0; i<calibrationHelper.Count ; ++i) { double diff = calibrationHelper[i].calibrationError(); calculated += diff*diff; } if (Math.Sqrt(calculated) > tolerance) Assert.Fail("Failed to calibrate libor forward model" + "\n calculated diff: " + Math.Sqrt(calculated) + "\n expected : smaller than " + tolerance); }