/// <summary> /// Computes the multi-factored volatilities given a particular input volatility grid, using principal component analysis. /// (See Pedersen, M. B. (1998) Calibrating Libor market models. Working paper, Financial Research Department, SimCorp.) /// </summary> /// <param name="inputVolMat"></param> public void Populate(Matrix inputVolMat) { if (!_volFixed) { for (int i = 0; i < _timeGrid.ExpiryCount; i++) { var currentRow = SingleRowOfVolatilities(i, inputVolMat.RowD(i)); for (int j = _timeGrid.ExpiryGrid[i]; j < _timeGrid.ExpiryGrid[i + 1]; j++) { for (int k = 0; k < _timeGrid.MaxTenor - j; k++) { for (int l = 0; l < _factors; l++) { _volatility[j][k, l] = currentRow[k, l]; } } } } } else { throw new Exception("Cannot alter finalised volatility."); } }
/// <summary> /// Computes the implied volatility of swaption with given expiry and tenor, or a caplet with given expiry, /// with the volatility at one particular expiry time bucket replaced with temporary values. /// A caplet implied volatility is equivalent to that of a swaption with the tenor length of 1. /// Saves computation time when checking the effect of a simple perturbation. /// </summary> /// <param name="expiry"></param> /// <param name="tenor"></param> /// <param name="newRow">Indicating the expiry time bucket to be replaced.</param> /// <param name="replacedRow">New interest rate volatility values for the expiry time bucket.</param> /// <returns></returns> public double FindImpliedVolatility(int expiry, int tenor, Matrix newRow, int replacedRow) { int exp = expiry - 1; int ten = tenor - 1; double result; if (exp >= _timeGrid.ExpiryGrid[replacedRow]) { result = _storedImpliedVolSq[exp][ten]; for (int i = _timeGrid.ExpiryGrid[replacedRow]; i < Math.Min(_timeGrid.ExpiryGrid[replacedRow + 1], expiry); i++) { var tempVector = new DenseVector(_factors); for (int j = 0; j <= ten; j++) { tempVector = tempVector + _weights.Get(expiry, tenor, j + 1) * newRow.RowD(j + exp - i); } double tempSum = tempVector * tempVector; result += tempSum - _storedImpliedVolTerm[exp][ten][i]; } result = Math.Sqrt(result / expiry); } else { result = _storedImpliedVol[exp][ten]; } return(result); }