/// <summary> /// Constructor /// </summary> /// <param name="targets">Calibration targets containing swaption and caplet data</param> /// <param name="timeGrid">Time discretisation</param> /// <param name="volatilities">Volatility to be calibrated</param> /// <param name="parameters">Calibration parameter settings</param> public CalibrationObjective(CalibrationTargets targets, PedersenTimeGrid timeGrid, InterestRateVolatilities volatilities, CalibrationSettings parameters) { Finished = false; _gradPhase = false; _iterationCounter = 0; _taskCounter = new TaskCounter(); //_currentInput = new DenseVector(0); _targets = targets; _timeGrid = timeGrid; _volatilities = volatilities; _parameters = parameters; _hFactor = 1.0 / (_timeGrid.ExpiryCount * (_timeGrid.TenorCount - 1)); _vFactor = 1.0 / ((_timeGrid.ExpiryCount - 1) * _timeGrid.TenorCount); _sFactor = 1.0 / _targets.SwaptionCount; _cFactor = 1.0 / _targets.CapletCount; }
/// <summary> /// Main calibration method. /// </summary> /// <param name="timeGrid">Time discretisation</param> /// <param name="discount">Quarterly discount factors</param> /// <param name="shift">Quarterly shift values</param> /// <param name="correlation">Correlation matrix, corresponding the tenor time discretisation</param> /// <param name="targets">Caplet and swaption implied vols</param> /// <param name="parameters">Calibration settings</param> /// <param name="factors">Factors used</param> /// <param name="useCascade">Whether to apply cascade algorithm post-calibration</param> /// <param name="output"></param> /// <returns></returns> public static InterestRateVolatilities Calibrate(PedersenTimeGrid timeGrid, QuarterlyDiscounts discount, QuarterlyShifts shift, DenseMatrix correlation, CalibrationTargets targets, CalibrationSettings parameters, int factors, bool useCascade, ref string output) { #region Initialisations targets.AdjustImpliedVolsForShift(discount, shift); var swaptionWeights = new SwaptionWeights(timeGrid.MaxExpiry, timeGrid.MaxTenor); swaptionWeights.Populate(discount, shift); var volatilities = new InterestRateVolatilities(timeGrid, factors, swaptionWeights, correlation); var objective = new CalibrationObjective(targets, timeGrid, volatilities, parameters); Func <Vector <double>, double> f = objective.ObjFun; Func <Vector <double>, Vector <double> > g = objective.ObjGrad; var initialGuess = new DenseVector(timeGrid.ExpiryCount * timeGrid.TenorCount); double guessValue = targets.AverageImpliedVol(); if (guessValue == 0) { throw new Exception("The selected time range does not include any calibration targets."); } if (parameters.ExponentialForm) { for (var i = 0; i < initialGuess.Count; i++) { initialGuess[i] = Math.Log(guessValue) / 20; } } else { for (var i = 0; i < initialGuess.Count; i++) { initialGuess[i] = guessValue; } } Trace.WriteLine(String.Format("Calibration Starting...")); objective.StartOtherThreads(); var solution = BfgsSolver.Solve(initialGuess, f, g); objective.Finished = true; Trace.WriteLine($"Value at extremum: {solution}"); objective.PopulateVol(solution); objective.AverageAbsVol(); #endregion #region Cascade if (useCascade) { Trace.WriteLine(String.Format("Applying Cascade Algorithm...")); var cascade = new CascadeAlgorithm(volatilities, timeGrid, swaptionWeights, targets, parameters.CascadeParam, factors); cascade.ApplyCascade(); } #endregion #region Output output = objective.AverageAbsVol(); return(objective.ReturnVol(solution)); #endregion }