/** * 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); }
/** * This calculates the sensitivity of the present value (PV) to the continuously-compounded * discount rates at the knot points of the funding curve. * * <p>The return format is a DoubleMatrix1D (i.e. a vector) with length equal to the total number * of knots in the curve * * <p>The change of a curve due to the movement of a single knot is interpolator-dependent, so an * instrument can have sensitivity to knots at times beyond its maturity * * @param swap the VarianceSwap * @param market the VarianceSwapDataBundle * @return A DoubleMatrix1D containing bucketed delta in order and length of * market.getDiscountCurve(). Currency amount per unit amount change in discount rate */ public DoubleMatrix1D calcDeltaBucketed( final VarianceSwap swap, final VarianceSwapDataBundle market) { Validate.notNull(swap, "null VarianceSwap"); Validate.notNull(market, "null VarianceSwapDataBundle"); // We know that the VarianceSwap only has true sensitivity to one maturity on one curve. // A function written for interestRate sensitivities spreads this sensitivity across yield nodes // NodeSensitivityCalculator.curveToNodeSensitivities(curveSensitivities, interpolatedCurves) // 2nd arg = LinkedHashMap<String, YieldAndDiscountCurve> interpolatedCurves final YieldAndDiscountCurve discCrv = market.getDiscountCurve(); final String discCrvName = discCrv.getCurve().getName(); final YieldCurveBundle interpolatedCurves = new YieldCurveBundle(); interpolatedCurves.setCurve(discCrvName, discCrv); // 1st arg = Map<String, List<DoublesPair>> curveSensitivities = <curveName, // List<(maturity,sensitivity)>> final double settlement = swap.getTimeToSettlement(); final Double sens = calcDiscountRateSensitivity(swap, market); final Map<String, List<DoublesPair>> curveSensitivities = new HashMap<String, List<DoublesPair>>(); curveSensitivities.put(discCrvName, Lists.newArrayList(new DoublesPair(settlement, sens))); final NodeSensitivityCalculator distributor = PresentValueNodeSensitivityCalculator.getDefaultInstance(); return distributor.curveToNodeSensitivities(curveSensitivities, interpolatedCurves); }
/** * 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); }