public XABRInterpolationImpl(List <double> xBegin, int size, List <double> yBegin, double t, double forward, List <double?> _params, List <bool> paramIsFixed, bool vegaWeighted, EndCriteria endCriteria, OptimizationMethod optMethod, double errorAccept, bool useMaxError, int maxGuesses, List <double?> addParams = null) : base(xBegin, size, yBegin) { // XABRCoeffHolder<Model>(t, forward, params, paramIsFixed), endCriteria_ = endCriteria; optMethod_ = optMethod; errorAccept_ = errorAccept; useMaxError_ = useMaxError; maxGuesses_ = maxGuesses; forward_ = forward; vegaWeighted_ = vegaWeighted; // if no optimization method or endCriteria is provided, we provide one if (optMethod_ == null) { optMethod_ = new LevenbergMarquardt(1e-8, 1e-8, 1e-8); } if (endCriteria_ == null) { endCriteria_ = new EndCriteria(60000, 100, 1e-8, 1e-8, 1e-8); } coeff_ = new XABRCoeffHolder <Model>(t, forward, _params, paramIsFixed, addParams); this.coeff_.weights_ = new InitializedList <double>(size, 1.0 / size); }
// to constrained <- from unconstrained public AbcdCalibration(List <double> t, List <double> blackVols, double aGuess = -0.06, double bGuess = 0.17, double cGuess = 0.54, double dGuess = 0.17, bool aIsFixed = false, bool bIsFixed = false, bool cIsFixed = false, bool dIsFixed = false, bool vegaWeighted = false, EndCriteria endCriteria = null, OptimizationMethod method = null) { aIsFixed_ = aIsFixed; bIsFixed_ = bIsFixed; cIsFixed_ = cIsFixed; dIsFixed_ = dIsFixed; a_ = aGuess; b_ = bGuess; c_ = cGuess; d_ = dGuess; abcdEndCriteria_ = QLNet.EndCriteria.Type.None; endCriteria_ = endCriteria; optMethod_ = method; weights_ = new InitializedList <double>(blackVols.Count, 1.0 / blackVols.Count); vegaWeighted_ = vegaWeighted; times_ = t; blackVols_ = blackVols; AbcdMathFunction.validate(aGuess, bGuess, cGuess, dGuess); Utils.QL_REQUIRE(blackVols.Count == t.Count, () => "mismatch between number of times (" + t.Count + ") and blackVols (" + blackVols.Count + ")"); // if no optimization method or endCriteria is provided, we provide one if (optMethod_ == null) { double epsfcn = 1.0e-8; double xtol = 1.0e-8; double gtol = 1.0e-8; bool useCostFunctionsJacobian = false; optMethod_ = new LevenbergMarquardt(epsfcn, xtol, gtol, useCostFunctionsJacobian); } if (endCriteria_ == null) { int maxIterations = 10000; int maxStationaryStateIterations = 1000; double rootEpsilon = 1.0e-8; double functionEpsilon = 0.3e-4; // Why 0.3e-4 ? double gradientNormEpsilon = 0.3e-4; // Why 0.3e-4 ? endCriteria_ = new EndCriteria(maxIterations, maxStationaryStateIterations, rootEpsilon, functionEpsilon, gradientNormEpsilon); } }
public void nestedOptimizationTest() { //("Testing nested optimizations..."); OptimizationBasedCostFunction optimizationBasedCostFunction = new OptimizationBasedCostFunction(); NoConstraint constraint = new NoConstraint(); Vector initialValues = new Vector(1, 0.0); Problem problem = new Problem(optimizationBasedCostFunction, constraint, initialValues); LevenbergMarquardt optimizationMethod = new LevenbergMarquardt(); //Simplex optimizationMethod(0.1); //ConjugateGradient optimizationMethod; //SteepestDescent optimizationMethod; EndCriteria endCriteria = new EndCriteria(1000, 100, 1e-5, 1e-5, 1e-5); optimizationMethod.minimize(problem, endCriteria); }
static void CalibrateModel(ShortRateModel model, List<CalibrationHelper> helpers) { if (model == null) throw new ArgumentNullException("model"); var om = new LevenbergMarquardt(); model.calibrate(helpers, om, new EndCriteria(400, 100, 1.0e-8, 1.0e-8, 1.0e-8), new Constraint(), new List<double>()); // Output the implied Black volatilities for (int i = 0; i < NumRows; i++) { int j = NumCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1 int k = i * NumCols + j; double npv = helpers[i].modelValue(); double implied = helpers[i].impliedVolatility(npv, 1e-4, 1000, 0.05, 0.50); double diff = implied - SwaptionVols[k]; Console.WriteLine("{0}x{1}: model {2:0.00000 %}, market {3:0.00000 %}, diff {4:0.00000 %} ", i + 1, SwapLenghts[j], implied, SwaptionVols[k], diff); } }
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); }
public override Vector values(Vector x) { // dummy nested optimization Vector coefficients = new Vector(3, 1.0); OneDimensionalPolynomialDegreeN oneDimensionalPolynomialDegreeN = new OneDimensionalPolynomialDegreeN(coefficients); NoConstraint constraint = new NoConstraint(); Vector initialValues = new Vector(1, 100.0); Problem problem = new Problem(oneDimensionalPolynomialDegreeN, constraint, initialValues); LevenbergMarquardt optimizationMethod = new LevenbergMarquardt(); //Simplex optimizationMethod(0.1); //ConjugateGradient optimizationMethod; //SteepestDescent optimizationMethod; EndCriteria endCriteria = new EndCriteria(1000, 100, 1e-5, 1e-5, 1e-5); optimizationMethod.minimize(problem, endCriteria); // return dummy result Vector dummy = new Vector(1,0); return dummy; }
public void calculate() { validCurve_ = false; int nInsts = ts_.instruments_.Count, i; // ensure rate helpers are sorted ts_.instruments_.Sort((x, y) => x.latestDate().CompareTo(y.latestDate())); // check that there is no instruments with the same maturity for (i = 1; i < nInsts; ++i) { Date m1 = ts_.instruments_[i - 1].latestDate(), m2 = ts_.instruments_[i].latestDate(); if (m1 == m2) { throw new ArgumentException("two instruments have the same maturity (" + m1 + ")"); } } // check that there is no instruments with invalid quote if ((i = ts_.instruments_.FindIndex(x => !x.quoteIsValid())) != -1) { throw new ArgumentException("instrument " + i + " (maturity: " + ts_.instruments_[i].latestDate() + ") has an invalid quote"); } // setup instruments and register with them ts_.instruments_.ForEach((x, j) => ts_.setTermStructure(j)); // set initial guess only if the current curve cannot be used as guess if (validCurve_) { if (ts_.data_.Count != nInsts + 1) { throw new ArgumentException("dimension mismatch: expected " + nInsts + 1 + ", actual " + ts_.data_.Count); } } else { ts_.data_ = new InitializedList <double>(nInsts + 1); ts_.data_[0] = ts_.initialValue(); } // calculate dates and times ts_.dates_ = new InitializedList <Date>(nInsts + 1); ts_.times_ = new InitializedList <double>(nInsts + 1); ts_.dates_[0] = ts_.initialDate(); ts_.times_[0] = ts_.timeFromReference(ts_.dates_[0]); for (i = 0; i < nInsts; ++i) { ts_.dates_[i + 1] = ts_.instruments_[i].latestDate(); ts_.times_[i + 1] = ts_.timeFromReference(ts_.dates_[i + 1]); if (!validCurve_) { ts_.data_[i + 1] = ts_.data_[i]; } } LevenbergMarquardt solver = new LevenbergMarquardt(ts_.accuracy_, ts_.accuracy_, ts_.accuracy_); EndCriteria endCriteria = new EndCriteria(100, 10, 0.00, ts_.accuracy_, 0.00); PositiveConstraint posConstraint = new PositiveConstraint(); NoConstraint noConstraint = new NoConstraint(); Constraint solverConstraint = forcePositive_ ? (Constraint)posConstraint : (Constraint)noConstraint; // now start the bootstrapping. int iInst = localisation_ - 1; int dataAdjust = (ts_.interpolator_ as ConvexMonotone).dataSizeAdjustment; do { int initialDataPt = iInst + 1 - localisation_ + dataAdjust; Vector startArray = new Vector(localisation_ + 1 - dataAdjust); for (int j = 0; j < startArray.size() - 1; ++j) { startArray[j] = ts_.data_[initialDataPt + j]; } // here we are extending the interpolation a point at a // time... but the local interpolator can make an // approximation for the final localisation period. // e.g. if the localisation is 2, then the first section // of the curve will be solved using the first 2 // instruments... with the local interpolator making // suitable boundary conditions. ts_.interpolation_ = (ts_.interpolator_ as ConvexMonotone).localInterpolate(ts_.times_, iInst + 2, ts_.data_, localisation_, ts_.interpolation_ as ConvexMonotoneInterpolation, nInsts + 1); if (iInst >= localisation_) { startArray[localisation_ - dataAdjust] = ts_.guess(iInst, ts_, false, 0); } else { startArray[localisation_ - dataAdjust] = ts_.data_[0]; } var currentCost = new PenaltyFunction <T, U>(ts_, initialDataPt, ts_.instruments_, iInst - localisation_ + 1, iInst + 1); Problem toSolve = new Problem(currentCost, solverConstraint, startArray); EndCriteria.Type endType = solver.minimize(toSolve, endCriteria); // check the end criteria if (!(endType == EndCriteria.Type.StationaryFunctionAccuracy || endType == EndCriteria.Type.StationaryFunctionValue)) { throw new Exception("Unable to strip yieldcurve to required accuracy "); } ++iInst; } while (iInst < nInsts); validCurve_ = true; }