/** * This calculates the sensitivity of the present value (PV) to a unit move in the forward. The * volatility surface remains unchanged. * * @param swap the VarianceSwap * @param market the VarianceSwapDataBundle * @param relShift Relative size of shift made in centered-finite difference approximation. * @return A Double. Currency amount per unit amount change in the black volatility */ @SuppressWarnings({}) public Double calcForwardSensitivity( final VarianceSwap swap, final VarianceSwapDataBundle market, final double relShift) { Validate.notNull(swap, "null VarianceSwap"); Validate.notNull(market, "null VarianceSwapDataBundle"); final VarianceSwapPresentValueCalculator pricer = VarianceSwapPresentValueCalculator.getInstance(); // Shift UP VarianceSwapDataBundle bumpedMarket = new VarianceSwapDataBundle( market.getVolatilitySurface(), market.getDiscountCurve(), market.getForwardCurve().withFractionalShift(relShift)); final double pvUp = pricer.visitVarianceSwap(swap, bumpedMarket); // Shift Down bumpedMarket = new VarianceSwapDataBundle( market.getVolatilitySurface(), market.getDiscountCurve(), market.getForwardCurve().withFractionalShift(-relShift)); final double pvDown = pricer.visitVarianceSwap(swap, bumpedMarket); final double t = swap.getTimeToSettlement(); final double fwd = market.getForwardCurve().getForward(t); // Centered-difference result return (pvUp - pvDown) / 2.0 / relShift / fwd; }
/** * This calculates the sensitivity of the present value (PV) to the lognormal Black implied * volatities at the knot points of the surface. * * <p>Note - the change of the surface due to the movement of a single node is * interpolator-dependent, so an instrument may have non-local sensitivity * * @param swap the VarianceSwap * @param market the VarianceSwapDataBundle * @param shift Size of shift made in centered-finite difference approximation. e.g. 1% would be * 0.01, and 1bp 0.0001 * @return A Double. Currency amount per unit amount change in the black volatility */ @SuppressWarnings({}) public Double calcBlackVegaParallel( final VarianceSwap swap, final VarianceSwapDataBundle market, final double shift) { Validate.notNull(swap, "null VarianceSwap"); Validate.notNull(market, "null VarianceSwapDataBundle"); final VarianceSwapPresentValueCalculator pricer = VarianceSwapPresentValueCalculator.getInstance(); // Parallel shift UP final BlackVolatilitySurface<?> upSurface = market.getVolatilitySurface().withShift(shift, true); final double pvUp = pricer.visitVarianceSwap( swap, new VarianceSwapDataBundle( upSurface, market.getDiscountCurve(), market.getForwardCurve())); // Parallel shift DOWN final BlackVolatilitySurface<?> downSurface = market.getVolatilitySurface().withShift(-shift, true); final double pvDown = pricer.visitVarianceSwap( swap, new VarianceSwapDataBundle( downSurface, market.getDiscountCurve(), market.getForwardCurve())); // Centered-difference result return (pvUp - pvDown) / (2.0 * shift); }
/** * Compute the price sensitivity to a shift of the Black volatility at a given maturity and * strike. * * <p>Note - the change of the surface due to the movement of a single node is * interpolator-dependent, so an instrument may have non-local sensitivity. * * <p>Important!!! If the <i>(x, y)</i> value(s) of the shift(s) are not in the nodal points of * the original surface, they are added (with shift) to the nodal points of the new surface. * * @param swap the VarianceSwap * @param market the VarianceSwapDataBundle * @param maturity a double in same unit as VolatilitySurface * @param strike a double in same unit as VolatilitySurface * @param shift Size of shift made in centered-finite difference approximation. e.g. 1% would be * 0.01, and 1bp 0.0001 * @return Currency amount per unit amount change in the black volatility at the point provided */ public double calcBlackVegaForSinglePoint( final VarianceSwap swap, final VarianceSwapDataBundle market, final double maturity, final double strike, final double shift) { final VarianceSwapPresentValueCalculator pricer = VarianceSwapPresentValueCalculator.getInstance(); final Surface<Double, Double, Double> surface = market.getVolatilitySurface().getSurface(); Validate.isTrue( surface instanceof InterpolatedDoublesSurface, "Currently will only accept a Equity VolatilitySurfaces based on an InterpolatedDoublesSurface"); final InterpolatedDoublesSurface blackSurf = (InterpolatedDoublesSurface) surface; final InterpolatedSurfaceAdditiveShiftFunction volShifter = new InterpolatedSurfaceAdditiveShiftFunction(); // shift UP final InterpolatedDoublesSurface bumpedVolUp = volShifter.evaluate(blackSurf, maturity, strike, shift); VarianceSwapDataBundle bumpedMarket = new VarianceSwapDataBundle( market.getVolatilitySurface().withSurface(bumpedVolUp), market.getDiscountCurve(), market.getForwardCurve()); final double pvUp = pricer.visitVarianceSwap(swap, bumpedMarket); // shift DOWN final InterpolatedDoublesSurface bumpedVolDown = volShifter.evaluate(blackSurf, maturity, strike, -shift); bumpedMarket = new VarianceSwapDataBundle( market.getVolatilitySurface().withSurface(bumpedVolDown), market.getDiscountCurve(), market.getForwardCurve()); final double pvDown = pricer.visitVarianceSwap(swap, bumpedMarket); // Centered-difference result return (pvUp - pvDown) / (2.0 * shift); }