/** * Calculates the exercise boundary for swaptions. * <p> * Reference: Henrard, M. (2003). "Explicit bond option and swaption formula in Heath-Jarrow-Morton one-factor model". * International Journal of Theoretical and Applied Finance, 6(1):57--72. * * @param discountedCashFlow the cash flow equivalent discounted to today * @param alpha the zero-coupon bond volatilities * @return the exercise boundary */ public double kappa(DoubleArray discountedCashFlow, DoubleArray alpha) { final Function<Double, Double> swapValue = new Function<Double, Double>() { @Override public Double apply(Double x) { double error = 0.0; for (int loopcf = 0; loopcf < alpha.size(); loopcf++) { error += discountedCashFlow.get(loopcf) * Math.exp(-0.5 * alpha.get(loopcf) * alpha.get(loopcf) - (alpha.get(loopcf) - alpha.get(0)) * x); } return error; } }; BracketRoot bracketer = new BracketRoot(); double accuracy = 1.0E-8; RidderSingleRootFinder rootFinder = new RidderSingleRootFinder(accuracy); double[] range = bracketer.getBracketedPoints(swapValue, -2.0, 2.0); return rootFinder.getRoot(swapValue, range[0], range[1]); }
/** * Calculates the common part of the exercise boundary of European swaptions forward. * <p> * This is intended to be used in particular for Bermudan swaption first step of the pricing. * <p> * Reference: Henrard, "M. Bermudan Swaptions in Gaussian HJM One-Factor Model: Analytical and Numerical Approaches". * SSRN, October 2008. Available at SSRN: http://ssrn.com/abstract=1287982 * * @param discountedCashFlow the swap discounted cash flows * @param alpha2 square of the alpha parameter * @param hwH the H factors * @return the exercise boundary */ public double lambda(DoubleArray discountedCashFlow, DoubleArray alpha2, DoubleArray hwH) { final Function<Double, Double> swapValue = new Function<Double, Double>() { @Override public Double apply(Double x) { double value = 0.0; for (int loopcf = 0; loopcf < alpha2.size(); loopcf++) { value += discountedCashFlow.get(loopcf) * Math.exp(-0.5 * alpha2.get(loopcf) - hwH.get(loopcf) * x); } return value; } }; BracketRoot bracketer = new BracketRoot(); double accuracy = 1.0E-8; RidderSingleRootFinder rootFinder = new RidderSingleRootFinder(accuracy); double[] range = bracketer.getBracketedPoints(swapValue, -2.0, 2.0); return rootFinder.getRoot(swapValue, range[0], range[1]); }
private double[] computesFittingParameters() { double[] param = new double[3]; // Implementation note: called a,b,c in the note. // Computes derivatives at cut-off. double[] vD = new double[6]; double[][] vD2 = new double[2][2]; volatilityK = sabrFunction.volatilityAdjoint2(forward, cutOffStrike, timeToExpiry, sabrData, vD, vD2); Pair<ValueDerivatives, double[][]> pa2 = BlackFormulaRepository.priceAdjoint2(forward, cutOffStrike, timeToExpiry, volatilityK, true); double[] bsD = pa2.getFirst().getDerivatives().toArrayUnsafe(); double[][] bsD2 = pa2.getSecond(); priceK[0] = pa2.getFirst().getValue(); priceK[1] = bsD[1] + bsD[3] * vD[1]; priceK[2] = bsD2[1][1] + bsD2[1][2] * vD[1] + (bsD2[2][1] + bsD2[2][2] * vD[1]) * vD[1] + bsD[3] * vD2[1][1]; if (Math.abs(priceK[0]) < SMALL_PRICE && Math.abs(priceK[1]) < SMALL_PRICE && Math.abs(priceK[2]) < SMALL_PRICE) { // Implementation note: If value and its derivatives is too small, then parameters are such that the extrapolated price is "very small". return new double[] {-100.0, 0, 0}; } Function<Double, Double> toSolveC = getCFunction(priceK, cutOffStrike, mu); BracketRoot bracketer = new BracketRoot(); double accuracy = 1.0E-5; RidderSingleRootFinder rootFinder = new RidderSingleRootFinder(accuracy); double[] range = bracketer.getBracketedPoints(toSolveC, -1.0, 1.0); param[2] = rootFinder.getRoot(toSolveC, range[0], range[1]); param[1] = -2 * param[2] / cutOffStrike - (priceK[1] / priceK[0] * cutOffStrike + mu) * cutOffStrike; param[0] = Math.log(priceK[0] / Math.pow(cutOffStrike, -mu)) - param[1] / cutOffStrike - param[2] / (cutOffStrike * cutOffStrike); return param; }