@Test /** Test the price computed from the curves */ public void price() { final YieldCurveBundle curves = TestsDataSets.createCurves1(); final double price = METHOD.price(ERU2, curves); final YieldAndDiscountCurve forwardCurve = curves.getCurve(FORWARD_CURVE_NAME); final double forward = (forwardCurve.getDiscountFactor(FIXING_START_TIME) / forwardCurve.getDiscountFactor(FIXING_END_TIME) - 1) / FIXING_ACCRUAL; final double factor = MODEL.futureConvexityFactor(ERU2, MODEL_PARAMETERS); final double expectedPrice = 1.0 - factor * forward + (1 - factor) / FIXING_ACCRUAL; assertEquals("Future price from curves in Hull-White one factor model", expectedPrice, price); }
/** * Computes the interest rate sensitivity of future price. * * @param future The future security. * @param curves The curves. * @return The curve sensitivity. */ @Override public InterestRateCurveSensitivity priceCurveSensitivity( final FederalFundsFutureSecurity future, final YieldCurveBundle curves) { Validate.notNull(future, "Future"); Validate.notNull(curves, "Curves"); int nbFixing = future.getFixingPeriodAccrualFactor().length; YieldAndDiscountCurve ois = curves.getCurve(future.getOISCurveName()); double[] df = new double[nbFixing + 1]; for (int loopfix = 0; loopfix < nbFixing + 1; loopfix++) { df[loopfix] = ois.getDiscountFactor(future.getFixingPeriodTime()[loopfix]); } // Backward sweep double priceBar = 1.0; double interestBar = -1.0 / future.getFixingTotalAccrualFactor() * priceBar; double[] dfBar = new double[nbFixing + 1]; for (int loopfix = 0; loopfix < nbFixing; loopfix++) { dfBar[loopfix] += 1.0 / df[loopfix + 1] * interestBar; dfBar[loopfix + 1] += -df[loopfix] / (df[loopfix + 1] * df[loopfix + 1]) * interestBar; } Map<String, List<DoublesPair>> resultMap = new HashMap<String, List<DoublesPair>>(); List<DoublesPair> listOIS = new ArrayList<DoublesPair>(); for (int loopfix = 0; loopfix < nbFixing + 1; loopfix++) { listOIS.add( new DoublesPair( future.getFixingPeriodTime()[loopfix], -future.getFixingPeriodTime()[loopfix] * df[loopfix] * dfBar[loopfix])); } resultMap.put(future.getOISCurveName(), listOIS); InterestRateCurveSensitivity result = new InterestRateCurveSensitivity(resultMap); return result; }
@Test(enabled = false) /** * Test the present value vs a external system. "enabled = false" for the standard testing: the * external system is using a TimeCalculator with ACT/365. */ public void presentValueExternal() { G2ppPiecewiseConstantParameters parametersCst = G2ppTestsDataSet.createG2ppCstParameters(); final YieldAndDiscountCurve curve5 = new YieldCurve(ConstantDoublesCurve.from(0.05)); final YieldCurveBundle curves = new YieldCurveBundle(); curves.setCurve(FUNDING_CURVE_NAME, curve5); curves.setCurve(FORWARD_CURVE_NAME, curve5); G2ppPiecewiseConstantDataBundle bundleCst = new G2ppPiecewiseConstantDataBundle(parametersCst, curves); CurrencyAmount pv = METHOD_G2PP_APPROXIMATION.presentValue(SWAPTION_PAYER_LONG, bundleCst); double pvExternal = 6885626.28245924; // ! TimeCalculator with ACT/365 assertEquals( "Swaption physical - G2++ - present value - external system", pvExternal, pv.getAmount(), 1E-2); }
@Override /** * Computes the Federal Funds future price using average of forward rates (not convexity * adjustment). * * @param future The future security. * @param curves The curves. * @return The price. */ public double price(final FederalFundsFutureSecurity future, final YieldCurveBundle curves) { Validate.notNull(future, "Future"); Validate.notNull(curves, "Curves"); int nbFixing = future.getFixingPeriodAccrualFactor().length; YieldAndDiscountCurve ois = curves.getCurve(future.getOISCurveName()); double[] df = new double[nbFixing + 1]; for (int loopfix = 0; loopfix < nbFixing + 1; loopfix++) { df[loopfix] = ois.getDiscountFactor(future.getFixingPeriodTime()[loopfix]); } double interest = future.getAccruedInterest(); for (int loopfix = 0; loopfix < nbFixing; loopfix++) { interest += df[loopfix] / df[loopfix + 1] - 1.0; } return 1.0 - interest / future.getFixingTotalAccrualFactor(); }
@Test /** * Test the present value sensitivity to rate for a swaption with strike above the cut-off strike. */ public void testPresentValueSensitivityExtra() { final YieldCurveBundle curves = TestsDataSetsSABR.createCurves1(); final SABRInterestRateParameters sabrParameter = TestsDataSetsSABR.createSABR1(); final SABRInterestRateDataBundle sabrBundle = new SABRInterestRateDataBundle(sabrParameter, curves); final double highStrike = 0.10; final SwapFixedIborDefinition swapDefinitionPayerHighStrike = SwapFixedIborDefinition.from( SETTLEMENT_DATE, CMS_INDEX, NOTIONAL, highStrike, FIXED_IS_PAYER); final SwaptionCashFixedIborDefinition swaptionDefinitionLongPayerHighStrike = SwaptionCashFixedIborDefinition.from(EXPIRY_DATE, swapDefinitionPayerHighStrike, IS_LONG); final SwaptionCashFixedIborDefinition swaptionDefinitionShortPayerHighStrike = SwaptionCashFixedIborDefinition.from(EXPIRY_DATE, swapDefinitionPayerHighStrike, !IS_LONG); final SwaptionCashFixedIbor swaptionLongPayerHighStrike = swaptionDefinitionLongPayerHighStrike.toDerivative(REFERENCE_DATE, CURVES_NAME); final SwaptionCashFixedIbor swaptionShortPayerHighStrike = swaptionDefinitionShortPayerHighStrike.toDerivative(REFERENCE_DATE, CURVES_NAME); final SwaptionCashFixedIborSABRExtrapolationRightMethod methodExtra = new SwaptionCashFixedIborSABRExtrapolationRightMethod(CUT_OFF_STRIKE, MU); // Swaption sensitivity InterestRateCurveSensitivity pvsLongPayerExtra = methodExtra.presentValueSensitivity(swaptionLongPayerHighStrike, sabrBundle); final InterestRateCurveSensitivity pvsShortPayerExtra = methodExtra.presentValueSensitivity(swaptionShortPayerHighStrike, sabrBundle); // Long/short parity final InterestRateCurveSensitivity pvsShortPayer_1 = pvsShortPayerExtra.multiply(-1); assertEquals(pvsLongPayerExtra.getSensitivities(), pvsShortPayer_1.getSensitivities()); // Present value sensitivity comparison with finite difference. final double deltaTolerance = 5.0E+4; // Testing note: Sensitivity is for a movement of 1. 1E+2 = 1 cent for a 1 bp move. Tolerance // increased to cope with numerical imprecision of finite difference. final double deltaShift = 1.0E-5; pvsLongPayerExtra = pvsLongPayerExtra.clean(); final double pv = methodExtra.presentValue(swaptionLongPayerHighStrike, sabrBundle); // 1. Forward curve sensitivity final String bumpedCurveName = "Bumped Curve"; final String[] bumpedCurvesForwardName = {FUNDING_CURVE_NAME, bumpedCurveName}; final SwaptionCashFixedIbor swaptionBumpedForward = swaptionDefinitionLongPayerHighStrike.toDerivative(REFERENCE_DATE, bumpedCurvesForwardName); final YieldAndDiscountCurve curveForward = curves.getCurve(FORWARD_CURVE_NAME); final Set<Double> timeForwardSet = new TreeSet<Double>(); for (final Payment pay : swaptionLongPayerHighStrike.getUnderlyingSwap().getSecondLeg().getPayments()) { final CouponIbor coupon = (CouponIbor) pay; timeForwardSet.add(coupon.getFixingPeriodStartTime()); timeForwardSet.add(coupon.getFixingPeriodEndTime()); } final int nbForwardDate = timeForwardSet.size(); final List<Double> timeForwardList = new ArrayList<Double>(timeForwardSet); Double[] timeForwardArray = new Double[nbForwardDate]; timeForwardArray = timeForwardList.toArray(timeForwardArray); final double[] yieldsForward = new double[nbForwardDate + 1]; final double[] nodeTimesForward = new double[nbForwardDate + 1]; yieldsForward[0] = curveForward.getInterestRate(0.0); for (int i = 0; i < nbForwardDate; i++) { nodeTimesForward[i + 1] = timeForwardArray[i]; yieldsForward[i + 1] = curveForward.getInterestRate(nodeTimesForward[i + 1]); } final YieldAndDiscountCurve tempCurveForward = new YieldCurve( InterpolatedDoublesCurve.fromSorted( nodeTimesForward, yieldsForward, new LinearInterpolator1D())); final List<DoublesPair> tempForward = pvsLongPayerExtra.getSensitivities().get(FORWARD_CURVE_NAME); final double[] resFwd = new double[nbForwardDate]; for (int i = 0; i < nbForwardDate; i++) { final YieldAndDiscountCurve bumpedCurveForward = tempCurveForward.withSingleShift(nodeTimesForward[i + 1], deltaShift); final YieldCurveBundle curvesBumpedForward = new YieldCurveBundle(); curvesBumpedForward.addAll(curves); curvesBumpedForward.setCurve("Bumped Curve", bumpedCurveForward); final SABRInterestRateDataBundle sabrBundleBumped = new SABRInterestRateDataBundle(sabrParameter, curvesBumpedForward); final double bumpedpv = methodExtra.presentValue(swaptionBumpedForward, sabrBundleBumped); resFwd[i] = (bumpedpv - pv) / deltaShift; final DoublesPair pair = tempForward.get(i); assertEquals( "Sensitivity to forward curve: Node " + i, nodeTimesForward[i + 1], pair.getFirst(), 1E-8); assertEquals( "Sensitivity to forward curve: Node " + i, resFwd[i], pair.getSecond(), deltaTolerance); } // 2. Funding curve sensitivity final String[] bumpedCurvesFundingName = {bumpedCurveName, FORWARD_CURVE_NAME}; final SwaptionCashFixedIbor swaptionBumpedFunding = swaptionDefinitionLongPayerHighStrike.toDerivative(REFERENCE_DATE, bumpedCurvesFundingName); final int nbPayDate = swaptionDefinitionLongPayerHighStrike.getUnderlyingSwap().getIborLeg().getPayments().length; final YieldAndDiscountCurve curveFunding = curves.getCurve(FUNDING_CURVE_NAME); final double[] yieldsFunding = new double[nbPayDate + 2]; final double[] nodeTimesFunding = new double[nbPayDate + 2]; yieldsFunding[0] = curveFunding.getInterestRate(0.0); nodeTimesFunding[1] = swaptionLongPayerHighStrike.getSettlementTime(); yieldsFunding[1] = curveFunding.getInterestRate(nodeTimesFunding[1]); for (int i = 0; i < nbPayDate; i++) { nodeTimesFunding[i + 2] = swaptionLongPayerHighStrike .getUnderlyingSwap() .getSecondLeg() .getNthPayment(i) .getPaymentTime(); yieldsFunding[i + 2] = curveFunding.getInterestRate(nodeTimesFunding[i + 2]); } final YieldAndDiscountCurve tempCurveFunding = new YieldCurve( InterpolatedDoublesCurve.fromSorted( nodeTimesFunding, yieldsFunding, new LinearInterpolator1D())); final List<DoublesPair> tempFunding = pvsLongPayerExtra.getSensitivities().get(FUNDING_CURVE_NAME); final double[] resDsc = new double[nbPayDate]; for (int i = 0; i < nbPayDate; i++) { final YieldAndDiscountCurve bumpedCurve = tempCurveFunding.withSingleShift(nodeTimesFunding[i + 1], deltaShift); final YieldCurveBundle curvesBumped = new YieldCurveBundle(); curvesBumped.addAll(curves); curvesBumped.setCurve("Bumped Curve", bumpedCurve); final SABRInterestRateDataBundle sabrBundleBumped = new SABRInterestRateDataBundle(sabrParameter, curvesBumped); final double bumpedpv = methodExtra.presentValue(swaptionBumpedFunding, sabrBundleBumped); resDsc[i] = (bumpedpv - pv) / deltaShift; final DoublesPair pair = tempFunding.get(i); assertEquals( "Sensitivity to discounting curve: Node " + i, nodeTimesFunding[i + 1], pair.getFirst(), 1E-8); assertEquals( "Sensitivity to discounting curve: Node " + i, resDsc[i], pair.getSecond(), deltaTolerance); } }