@Test /** Tests put call parity. */ public void presentValuePutCallParity() { final double strike = 1.45; final boolean isCall = true; final boolean isLong = true; final double notional = 100000000; final ZonedDateTime payDate = ScheduleCalculator.getAdjustedDate( REFERENCE_DATE, Period.ofMonths(9), BUSINESS_DAY, CALENDAR); final ZonedDateTime expDate = ScheduleCalculator.getAdjustedDate(payDate, -SETTLEMENT_DAYS, CALENDAR); final ForexDefinition forexUnderlyingDefinition = new ForexDefinition(EUR, USD, payDate, notional, strike); final ForexOptionDigitalDefinition callDefinition = new ForexOptionDigitalDefinition(forexUnderlyingDefinition, expDate, isCall, isLong); final ForexOptionDigitalDefinition putDefinition = new ForexOptionDigitalDefinition(forexUnderlyingDefinition, expDate, !isCall, isLong); final ForexOptionDigital call = callDefinition.toDerivative(REFERENCE_DATE, CURVES_NAME); final ForexOptionDigital put = putDefinition.toDerivative(REFERENCE_DATE, CURVES_NAME); final MultipleCurrencyAmount pvCall = METHOD_DIGITAL_SPREAD.presentValue(call, SMILE_BUNDLE); final MultipleCurrencyAmount pvPut = METHOD_DIGITAL_SPREAD.presentValue(put, SMILE_BUNDLE); final Double pvCash = PVC.visit(put.getUnderlyingForex().getPaymentCurrency2(), CURVES); assertEquals( "Forex Digital option: call spread method - present value", pvCall.getAmount(USD) + pvPut.getAmount(USD), Math.abs(pvCash), TOLERANCE_PRICE_FLAT); }
@Test /** Tests the present value long/short parity. */ public void presentValueLongShort() { final ForexOptionDigitalDefinition forexOptionShortDefinition = new ForexOptionDigitalDefinition(FOREX_DEFINITION, OPTION_EXP_DATE, IS_CALL, !IS_LONG); final InstrumentDerivative forexOptionShort = forexOptionShortDefinition.toDerivative(REFERENCE_DATE, CURVES_NAME); final MultipleCurrencyAmount pvShort = METHOD_DIGITAL_SPREAD.presentValue(forexOptionShort, SMILE_BUNDLE); final MultipleCurrencyAmount pvLong = METHOD_DIGITAL_SPREAD.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: present value long/short parity", pvLong.getAmount(USD), -pvShort.getAmount(USD), 1E-2); final MultipleCurrencyAmount ceShort = METHOD_DIGITAL_SPREAD.currencyExposure(forexOptionShort, SMILE_BUNDLE); final MultipleCurrencyAmount ceLong = METHOD_DIGITAL_SPREAD.currencyExposure(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: currency exposure long/short parity", ceLong.getAmount(USD), -ceShort.getAmount(USD), 1E-2); assertEquals( "Forex Digital option: currency exposure long/short parity", ceLong.getAmount(EUR), -ceShort.getAmount(EUR), 1E-2); }
@Override protected Set<ComputedValue> getResult( final ForexDerivative fxOption, final SmileDeltaTermStructureDataBundle data, final FunctionInputs inputs, final ComputationTarget target) { final MultipleCurrencyAmount result = CALCULATOR.visit(fxOption, data); final int n = result.size(); final Currency[] keys = new Currency[n]; final double[] values = new double[n]; int i = 0; for (final CurrencyAmount ca : result) { keys[i] = ca.getCurrency(); values[i++] = ca.getAmount(); } final ValueProperties properties = createValueProperties() .with(ValuePropertyNames.PAY_CURVE, getPutCurveName()) .with(ValuePropertyNames.RECEIVE_CURVE, getCallCurveName()) .with(ValuePropertyNames.SURFACE, getSurfaceName()) .get(); final ValueSpecification spec = new ValueSpecification(getValueRequirementName(), target.toSpecification(), properties); return Collections.singleton( new ComputedValue(spec, new CurrencyLabelledMatrix1D(keys, values))); }
@Test /** Tests the present value. */ public void presentValueNoNotional() { final MultipleCurrencyAmount pv = METHOD.presentValue(ZERO_COUPON_CAP, BLACK_INFLATION); final double timeToMaturity = ZERO_COUPON_CAP.getReferenceEndTime() - ZERO_COUPON_CAP.getLastKnownFixingTime(); final double df = MARKET .getCurve(ZERO_COUPON_CAP.getCurrency()) .getDiscountFactor(ZERO_COUPON_CAP.getPaymentTime()); final double finalIndex = MARKET.getCurve(PRICE_INDEX_EUR).getPriceIndex(ZERO_COUPON_CAP.getReferenceEndTime()); final double forward = finalIndex / INDEX_1MAY_2008; final EuropeanVanillaOption option = new EuropeanVanillaOption( Math.pow(1 + ZERO_COUPON_CAP.getStrike(), ZERO_COUPON_CAP.getMaturity()), timeToMaturity, ZERO_COUPON_CAP.isCap()); final double volatility = BLACK_INFLATION .getBlackParameters() .getVolatility(ZERO_COUPON_CAP.getReferenceEndTime(), ZERO_COUPON_CAP.getStrike()); final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatility); final Function1D<BlackFunctionData, Double> func = BLACK_FUNCTION.getPriceFunction(option); final double pvExpected = df * func.evaluate(dataBlack) * ZERO_COUPON_CAP.getNotional() * ZERO_COUPON_CAP.getPaymentYearFraction(); assertEquals( "Zero-coupon inflation DiscountingMethod: Present value", pvExpected, pv.getAmount(ZERO_COUPON_CAP.getCurrency()), TOLERANCE_PV); }
@Test /** Tests the Black volatility sensitivity (vega). */ public void presentValueBlackNodeSensitivity() { final double shift = 1.0E-6; final PresentValueBlackSwaptionSensitivity pvbvs = METHOD_BLACK.presentValueBlackSensitivity(SWAPTION_LONG_REC, BLACK_MULTICURVES); final PresentValueBlackSwaptionSensitivity pvbns = BSSNC.calculateNodeSensitivities(pvbvs, BLACK); final double[] x = ((InterpolatedDoublesSurface) BLACK.getVolatilitySurface()).getXDataAsPrimitive(); final double[] y = ((InterpolatedDoublesSurface) BLACK.getVolatilitySurface()).getYDataAsPrimitive(); for (int loopindex = 0; loopindex < x.length; loopindex++) { final BlackFlatSwaptionParameters BlackP = BlackDataSets.createBlackSwaptionEUR6Shift(loopindex, shift); final BlackSwaptionFlatProviderDiscount curvesBlackP = new BlackSwaptionFlatProviderDiscount(MULTICURVES, BlackP); final MultipleCurrencyAmount pvP = METHOD_BLACK.presentValue(SWAPTION_LONG_REC, curvesBlackP); final BlackFlatSwaptionParameters BlackM = BlackDataSets.createBlackSwaptionEUR6Shift(loopindex, -shift); final BlackSwaptionFlatProviderDiscount curvesBlackM = new BlackSwaptionFlatProviderDiscount(MULTICURVES, BlackM); final MultipleCurrencyAmount pvM = METHOD_BLACK.presentValue(SWAPTION_LONG_REC, curvesBlackM); assertEquals( "Swaption Black method: present value volatility sensitivity", (pvP.getAmount(EUR) - pvM.getAmount(EUR)) / (2 * shift), pvbns.getSensitivity().getMap().get(new DoublesPair(x[loopindex], y[loopindex])), TOLERANCE_PV_DELTA); } }
@Test /** Test the present value. */ public void presentValueExplicit() { final MultipleCurrencyAmount pv = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); final double timeToExpiry = SWAPTION_LONG_PAYER.getTimeToExpiry(); final AnnuityPaymentFixed cfe = CFEC.visitSwap(SWAPTION_LONG_PAYER.getUnderlyingSwap(), MULTICURVES); final int numberOfPayments = cfe.getNumberOfPayments(); final double alpha[] = new double[numberOfPayments]; final double disccf[] = new double[numberOfPayments]; for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) { alpha[loopcf] = MODEL.alpha( HW_PARAMETERS, 0.0, timeToExpiry, timeToExpiry, cfe.getNthPayment(loopcf).getPaymentTime()); disccf[loopcf] = MULTICURVES.getDiscountFactor(EUR, cfe.getNthPayment(loopcf).getPaymentTime()) * cfe.getNthPayment(loopcf).getAmount(); } final double kappa = MODEL.kappa(disccf, alpha); double pvExpected = 0.0; for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) { pvExpected += disccf[loopcf] * NORMAL.getCDF(-kappa - alpha[loopcf]); } assertEquals( "Swaption physical - Hull-White - present value", pvExpected, pv.getAmount(EUR), 1E-2); final MultipleCurrencyAmount pv2 = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, cfe, HW_MULTICURVES); assertEquals("Swaption physical - Hull-White - present value", pv, pv2); }
/** * Returns a copy of this {@code MultipleCurrencyAmount} with the specified amount added. * * <p>This adds the specified amount to this monetary amount, returning a new object. If the * currency is already present, the amount is added to the existing amount. If the currency is not * yet present, the currency-amount is added to the map. The addition simply uses standard {@code * double} arithmetic. * * <p>This instance is immutable and unaffected by this method. * * @param multipleCurrencyAmountToAdd the currency to add to, not null * @return an amount based on this with the specified amount added, not null */ public MultipleCurrencyAmount plus(final MultipleCurrencyAmount multipleCurrencyAmountToAdd) { ArgumentChecker.notNull(multipleCurrencyAmountToAdd, "multipleCurrencyAmountToAdd"); MultipleCurrencyAmount result = this; for (CurrencyAmount currencyAmount : multipleCurrencyAmountToAdd) { result = result.plus(currencyAmount); } return result; }
@Test public void presentValueMethodVsCalculator() { final MultipleCurrencyAmount pvMethod = METHOD_CPN_IBOR.presentValue(CPN_IBOR, MULTICURVES); final MultipleCurrencyAmount pvCalculator = CPN_IBOR.accept(PVDC, MULTICURVES); assertEquals( "CouponFixedDiscountingMarketMethod: present value", pvMethod.getAmount(EUR), pvCalculator.getAmount(EUR), TOLERANCE_PV); }
@Test /** Compare the method figures to the Calculator figures. */ public void presentValueMethodVsCalculator() { final MultipleCurrencyAmount pvMethod = METHOD_BLACK.presentValue(SWAPTION_LONG_REC, BLACK_MULTICURVES); final MultipleCurrencyAmount pvCalculator = SWAPTION_LONG_REC.accept(PVBSC, BLACK_MULTICURVES); assertEquals( "Swaption Black method: present value", pvCalculator.getAmount(EUR), pvMethod.getAmount(EUR), TOLERANCE_PV); }
@Test /** Tests the currency exposure against the present value. */ public void currencyExposureVsPresentValue() { MultipleCurrencyAmount pv = METHOD_DIGITAL_SPREAD.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE); MultipleCurrencyAmount ce = METHOD_DIGITAL_SPREAD.currencyExposure(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: call spread method - currency exposure vs present value", ce.getAmount(USD) + ce.getAmount(EUR) * SPOT, pv.getAmount(USD), TOLERANCE_PRICE); }
@Test /** Tests the present value in a flat smile case. */ public void presentValueFlat() { MultipleCurrencyAmount pvSpread = METHOD_DIGITAL_SPREAD.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE_FLAT); MultipleCurrencyAmount pvBlack = METHOD_DIGITAL_BLACK.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE_FLAT); assertEquals( "Forex Digital option: call spread method - present value", pvBlack.getAmount(USD), pvSpread.getAmount(USD), TOLERANCE_PRICE_FLAT); }
@Test /** Tests long/short parity. */ public void longShortParityExplicit() { final MultipleCurrencyAmount pvLong = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); final MultipleCurrencyAmount pvShort = METHOD_HW.presentValue(SWAPTION_SHORT_PAYER, HW_MULTICURVES); assertEquals( "Swaption physical - Hull-White - present value - long/short parity", pvLong.getAmount(EUR), -pvShort.getAmount(EUR), TOLERANCE_PV); }
@Test /** Tests the present value with an explicit computation. */ public void presentValue() { double strikeM = STRIKE * (1 - STANDARD_SPREAD); double strikeP = STRIKE * (1 + STANDARD_SPREAD); Forex forexM = new Forex( FOREX.getPaymentCurrency1().withAmount(1.0), FOREX.getPaymentCurrency2().withAmount(-strikeM)); Forex forexP = new Forex( FOREX.getPaymentCurrency1().withAmount(1.0), FOREX.getPaymentCurrency2().withAmount(-strikeP)); ForexOptionVanilla vanillaM = new ForexOptionVanilla(forexM, FOREX_CALL_OPTION.getExpirationTime(), IS_CALL, IS_LONG); ForexOptionVanilla vanillaP = new ForexOptionVanilla(forexP, FOREX_CALL_OPTION.getExpirationTime(), IS_CALL, IS_LONG); MultipleCurrencyAmount pvP = METHOD_VANILLA_BLACK.presentValue(vanillaP, SMILE_BUNDLE); MultipleCurrencyAmount pvM = METHOD_VANILLA_BLACK.presentValue(vanillaM, SMILE_BUNDLE); MultipleCurrencyAmount pvExpected = pvM.plus(pvP.multipliedBy(-1.0)) .multipliedBy( 1.0 / (strikeP - strikeM) * Math.abs(FOREX.getPaymentCurrency2().getAmount())); MultipleCurrencyAmount pvComputed = METHOD_DIGITAL_SPREAD.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: call spread method - present value", pvExpected.getAmount(USD), pvComputed.getAmount(USD), TOLERANCE_PRICE); }
@Test /** Tests the present value. Method vs Calculator. */ public void presentValueMethodVCalculator() { MultipleCurrencyAmount pv1 = METHOD_DIGITAL_SPREAD.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE); PresentValueCallSpreadBlackForexCalculator calculator = new PresentValueCallSpreadBlackForexCalculator(STANDARD_SPREAD); MultipleCurrencyAmount pvCalculator = calculator.visit(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: call spread method - present value", pv1.getAmount(USD), pvCalculator.getAmount(USD), TOLERANCE_PRICE); }
/** * Returns a copy of this {@code MultipleCurrencyAmount} with all the amounts multiplied by the * factor. * * <p>This instance is immutable and unaffected by this method. * * @param factor The multiplicative factor. * @return An amount based on this with all the amounts multiplied by the factor. Not null */ public MultipleCurrencyAmount multipliedBy(final double factor) { TreeMap<Currency, Double> map = new TreeMap<Currency, Double>(); for (CurrencyAmount currencyAmount : this) { map.put(currencyAmount.getCurrency(), currencyAmount.getAmount() * factor); } return MultipleCurrencyAmount.of(map); }
@Test /** Check the conversion of a multiple currency amount. */ public void convert() { final FXMatrix fxMatrix = new FXMatrix(); fxMatrix.addCurrency(EUR, USD, EUR_USD); fxMatrix.addCurrency(GBP, EUR, GBP_EUR); final double amountGBP = 1.0; final double amountEUR = 2.0; final double amountUSD = 3.0; MultipleCurrencyAmount amount = MultipleCurrencyAmount.of(GBP, amountGBP); amount = amount.plus(EUR, amountEUR); amount = amount.plus(USD, amountUSD); final CurrencyAmount totalUSDCalculated = fxMatrix.convert(amount, USD); final double totalUSDExpected = amountUSD + amountEUR * EUR_USD + amountGBP * GBP_EUR * EUR_USD; assertEquals("FXMatrix - convert", totalUSDExpected, totalUSDCalculated.getAmount(), 1.0E-10); assertEquals("FXMatrix - convert", USD, totalUSDCalculated.getCurrency()); }
@Test(enabled = false) /** Tests of performance. "enabled = false" for the standard testing. */ public void performanceCurveSensitivity() { long startTime, endTime; final int nbTest = 25; MultipleCurrencyAmount pvMC = MultipleCurrencyAmount.of(EUR, 0.0); final MultipleCurrencyMulticurveSensitivity pvcsExplicit = METHOD_HW.presentValueCurveSensitivity(SWAPTION_LONG_PAYER, HW_MULTICURVES); MultipleCurrencyMulticurveSensitivity pvcsMC = pvcsExplicit; final HullWhiteMonteCarloMethod methodMC = new HullWhiteMonteCarloMethod( new NormalRandomNumberGenerator(0.0, 1.0, new MersenneTwister()), NB_PATH); startTime = System.currentTimeMillis(); for (int looptest = 0; looptest < nbTest; looptest++) { pvMC = METHOD_HW_MONTECARLO.presentValue(SWAPTION_LONG_PAYER, EUR, HW_MULTICURVES); } endTime = System.currentTimeMillis(); System.out.println( nbTest + " swaption Hull-White Monte Carlo method (" + NB_PATH + " paths): " + (endTime - startTime) + " ms / price:" + pvMC.toString()); // Performance note: HW approximation: 03-Dec-2012: On Mac Pro 3.2 GHz Quad-Core Intel Xeon: 250 // ms for 25 swaptions (12500 paths). startTime = System.currentTimeMillis(); for (int looptest = 0; looptest < nbTest; looptest++) { pvcsMC = methodMC.presentValueCurveSensitivity(SWAPTION_LONG_PAYER, EUR, HW_MULTICURVES); } endTime = System.currentTimeMillis(); System.out.println( nbTest + " curve sensitivity swaption Hull-White MC method: (" + NB_PATH + " paths) " + (endTime - startTime) + " ms / risk:" + pvcsMC.toString()); // Performance note: curve sensitivity (40): 03-Dec-2012: On Mac Pro 3.2 GHz Quad-Core Intel // Xeon: 600 ms for 25 swaptions (12500 paths). }
@Test public void presentValueMarketDiscount() { final MultipleCurrencyAmount pvComputed = METHOD_CPN_IBOR.presentValue(CPN_IBOR, MULTICURVES); final double forward = MULTICURVES.getForwardRate( EURIBOR3M, CPN_IBOR.getFixingPeriodStartTime(), CPN_IBOR.getFixingPeriodEndTime(), CPN_IBOR.getFixingAccrualFactor()); final double df = MULTICURVES.getDiscountFactor(EURIBOR3M.getCurrency(), CPN_IBOR.getPaymentTime()); final double pvExpected = NOTIONAL * ACCRUAL_FACTOR * forward * df; assertEquals( "CouponIborDiscountingMarketMethod: present value", pvExpected, pvComputed.getAmount(EURIBOR3M.getCurrency()), TOLERANCE_PV); }
/** * Compute the the present value of a fixed payment by discounting to a parallel curve movement. * * @param payment The payment. * @param multicurves The multi-curve provider. * @return The present value. */ public MultipleCurrencyAmount presentValue( final PaymentFixed payment, final MulticurveProviderInterface multicurves) { ArgumentChecker.notNull(payment, "Payment"); ArgumentChecker.notNull(multicurves, "Multi-curves"); final double pv = payment.getAmount() * multicurves.getDiscountFactor(payment.getCurrency(), payment.getPaymentTime()); return MultipleCurrencyAmount.of(payment.getCurrency(), pv); }
@Test public void testNormalPresentValue() { Result<MultipleCurrencyAmount> result = _functionRunner.runFunction( ARGS, createSuppliedData(), new Function<Environment, Result<MultipleCurrencyAmount>>() { @Override public Result<MultipleCurrencyAmount> apply(Environment env) { return _normalIRFutureOptionFn.calculatePV(env, _irFutureOptionTrade); } }); assertSuccess(result); MultipleCurrencyAmount mca = result.getValue(); assertThat( mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(-902.7156551, STD_TOLERANCE_PV))); }
@Test public void presentValue() { final MultipleCurrencyAmount pvMethod = METHOD_BLACK.presentValue(SWAPTION_LONG_REC, BLACK_MULTICURVES); final double forward = SWAPTION_LONG_REC.getUnderlyingSwap().accept(PRDC, MULTICURVES); final double pvbp = METHOD_SWAP.presentValueBasisPoint(SWAPTION_LONG_REC.getUnderlyingSwap(), MULTICURVES); final double volatility = BLACK.getVolatility( SWAPTION_LONG_REC.getTimeToExpiry(), SWAPTION_LONG_REC.getMaturityTime()); final BlackPriceFunction blackFunction = new BlackPriceFunction(); final BlackFunctionData dataBlack = new BlackFunctionData(forward, pvbp, volatility); final Function1D<BlackFunctionData, Double> func = blackFunction.getPriceFunction(SWAPTION_LONG_REC); final double pvExpected = func.evaluate(dataBlack); assertEquals( "Swaption Black method: present value", pvExpected, pvMethod.getAmount(EUR), TOLERANCE_PV); }
/** * Compute the present value of a commodity cash settle forward by discounting. * * @param forward The forward. * @param multicurve The commodity multi-curve provider. * @return The present value. */ public MultipleCurrencyAmount presentValue( final ForwardCommodityCashSettle forward, final CommodityProviderInterface multicurve) { ArgumentChecker.notNull(forward, "Forward"); ArgumentChecker.notNull(multicurve, "Multi-curves provider"); final double fwd = multicurve.getForwardValue(forward.getUnderlying(), forward.getSettlementTime()); final double df = multicurve.getDiscountFactor(forward.getCurrency(), forward.getPaymentTime()); final double pv = forward.getNotional() * (fwd - forward.getRate()) * df; return MultipleCurrencyAmount.of(forward.getCurrency(), pv); }
@Test /** Compare explicit formula with approximated formula. */ public void presentValueApproximation() { final BlackImpliedVolatilityFormula implied = new BlackImpliedVolatilityFormula(); final double forward = SWAPTION_LONG_PAYER .getUnderlyingSwap() .accept(ParRateDiscountingCalculator.getInstance(), MULTICURVES); final double pvbp = METHOD_SWAP.presentValueBasisPoint(SWAPTION_LONG_PAYER.getUnderlyingSwap(), MULTICURVES); final MultipleCurrencyAmount pvPayerLongExplicit = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); final MultipleCurrencyAmount pvPayerLongApproximation = METHOD_HW_APPROXIMATION.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); final BlackFunctionData data = new BlackFunctionData(forward, pvbp, 0.20); final double volExplicit = implied.getImpliedVolatility(data, SWAPTION_LONG_PAYER, pvPayerLongExplicit.getAmount(EUR)); final double volApprox = implied.getImpliedVolatility( data, SWAPTION_LONG_PAYER, pvPayerLongApproximation.getAmount(EUR)); assertEquals( "Swaption physical - Hull-White - present value - explicit/approximation", pvPayerLongExplicit.getAmount(EUR), pvPayerLongApproximation.getAmount(EUR), 5.0E+2); assertEquals( "Swaption physical - Hull-White - present value - explicit/approximation", volExplicit, volApprox, 2.5E-4); // 0.025% final MultipleCurrencyAmount pvReceiverLongExplicit = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); final MultipleCurrencyAmount pvReceiverLongApproximation = METHOD_HW_APPROXIMATION.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); assertEquals( "Swaption physical - Hull-White - present value - explicit/numerical integration", pvReceiverLongExplicit.getAmount(EUR), pvReceiverLongApproximation.getAmount(EUR), 5.0E+2); }
@Test /** Tests the Black volatility sensitivity (vega). */ public void presentValueBlackSensitivity() { final double shift = 1.0E-6; final PresentValueBlackSwaptionSensitivity pvbvs = METHOD_BLACK.presentValueBlackSensitivity(SWAPTION_LONG_REC, BLACK_MULTICURVES); final BlackFlatSwaptionParameters BlackP = BlackDataSets.createBlackSwaptionEUR6Shift(shift); final BlackSwaptionFlatProviderDiscount curvesBlackP = new BlackSwaptionFlatProviderDiscount(MULTICURVES, BlackP); final MultipleCurrencyAmount pvP = METHOD_BLACK.presentValue(SWAPTION_LONG_REC, curvesBlackP); final BlackFlatSwaptionParameters BlackM = BlackDataSets.createBlackSwaptionEUR6Shift(-shift); final BlackSwaptionFlatProviderDiscount curvesBlackM = new BlackSwaptionFlatProviderDiscount(MULTICURVES, BlackM); final MultipleCurrencyAmount pvM = METHOD_BLACK.presentValue(SWAPTION_LONG_REC, curvesBlackM); final DoublesPair point = new DoublesPair(SWAPTION_LONG_REC.getTimeToExpiry(), SWAPTION_LONG_REC.getMaturityTime()); assertEquals( "Swaption Black method: present value volatility sensitivity", (pvP.getAmount(EUR) - pvM.getAmount(EUR)) / (2 * shift), pvbvs.getSensitivity().getMap().get(point), TOLERANCE_PV_DELTA); }
public static CurrencyLabelledMatrix1D getMultipleCurrencyAmountAsMatrix( final MultipleCurrencyAmount mca) { ArgumentChecker.notNull(mca, "multiple currency amount"); final int n = mca.size(); final Currency[] keys = new Currency[n]; final double[] values = new double[n]; int i = 0; for (final CurrencyAmount ca : mca) { keys[i] = ca.getCurrency(); values[i++] = ca.getAmount(); } return new CurrencyLabelledMatrix1D(keys, values); }
@Test /** Tests the present value. Spread change. */ public void presentValueSpreadChange() { double spread1 = 0.0001; double spread2 = 0.0002; ForexOptionDigitalCallSpreadBlackMethod methodCallSpreadBlack1 = new ForexOptionDigitalCallSpreadBlackMethod(spread1); ForexOptionDigitalCallSpreadBlackMethod methodCallSpreadBlack2 = new ForexOptionDigitalCallSpreadBlackMethod(spread2); MultipleCurrencyAmount pv1 = methodCallSpreadBlack1.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE); MultipleCurrencyAmount pv2 = methodCallSpreadBlack2.presentValue(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: call spread method - present value", pv1.getAmount(USD), pv2.getAmount(USD), 10.0); // MultipleCurrencyAmount pvBlack = METHOD_DIGITAL_BLACK.presentValue(FOREX_CALL_OPTION, // SMILE_BUNDLE); // assertEquals("Forex Digital option: call spread method - present value", // pvBlack.getAmount(USD), pv2.getAmount(USD), 10.0); // Should fail }
@Test /** Tests the currency exposure with an explicit computation. */ public void currencyExposure() { double spread = 0.0001; // Relative spread. double strikeM = STRIKE * (1 - spread); double strikeP = STRIKE * (1 + spread); Forex forexM = new Forex( FOREX.getPaymentCurrency1().withAmount(1.0), FOREX.getPaymentCurrency2().withAmount(-strikeM)); Forex forexP = new Forex( FOREX.getPaymentCurrency1().withAmount(1.0), FOREX.getPaymentCurrency2().withAmount(-strikeP)); ForexOptionVanilla vanillaM = new ForexOptionVanilla(forexM, FOREX_CALL_OPTION.getExpirationTime(), IS_CALL, IS_LONG); ForexOptionVanilla vanillaP = new ForexOptionVanilla(forexP, FOREX_CALL_OPTION.getExpirationTime(), IS_CALL, IS_LONG); MultipleCurrencyAmount ceP = METHOD_VANILLA_BLACK.currencyExposure(vanillaP, SMILE_BUNDLE); MultipleCurrencyAmount ceM = METHOD_VANILLA_BLACK.currencyExposure(vanillaM, SMILE_BUNDLE); MultipleCurrencyAmount ceExpected = ceM.plus(ceP.multipliedBy(-1.0)) .multipliedBy( 1.0 / (strikeP - strikeM) * Math.abs(FOREX.getPaymentCurrency2().getAmount())); MultipleCurrencyAmount ceComputed = METHOD_DIGITAL_SPREAD.currencyExposure(FOREX_CALL_OPTION, SMILE_BUNDLE); assertEquals( "Forex Digital option: call spread method - currency exposure", ceExpected.getAmount(USD), ceComputed.getAmount(USD), TOLERANCE_PRICE); assertEquals( "Forex Digital option: call spread method - currency exposure", ceExpected.getAmount(EUR), ceComputed.getAmount(EUR), TOLERANCE_PRICE); }
@Test public void testMultipleCashFlowsNoNetting() { for (final InstrumentDefinition<?> definition : NO_NETTING_MULTIPLE_CASHFLOWS) { final TreeMap<LocalDate, MultipleCurrencyAmount> pay = new TreeMap<LocalDate, MultipleCurrencyAmount>( definition.accept(PAY_CASH_FLOWS, IBOR_FIXING_SERIES)); final TreeMap<LocalDate, MultipleCurrencyAmount> receive = new TreeMap<LocalDate, MultipleCurrencyAmount>( definition.accept(RECEIVE_CASH_FLOWS, IBOR_FIXING_SERIES)); final TreeMap<LocalDate, MultipleCurrencyAmount> netted = new TreeMap<LocalDate, MultipleCurrencyAmount>( definition.accept(VISITOR, IBOR_FIXING_SERIES)); final Set<LocalDate> combinedDates = new HashSet<LocalDate>(); combinedDates.addAll(pay.keySet()); combinedDates.addAll(receive.keySet()); assertEquals(combinedDates.size(), netted.size()); for (final Map.Entry<LocalDate, MultipleCurrencyAmount> entry : netted.entrySet()) { final LocalDate date = entry.getKey(); final MultipleCurrencyAmount payAmount = pay.get(date); final MultipleCurrencyAmount receiveAmount = receive.get(date); MultipleCurrencyAmount combinedAmountForDate = null; if (payAmount != null) { combinedAmountForDate = payAmount.multipliedBy(-1); if (receiveAmount != null) { combinedAmountForDate = combinedAmountForDate.plus(receiveAmount); } } else { if (receiveAmount != null) { combinedAmountForDate = receiveAmount; } } assertNotNull(combinedAmountForDate); assertEquals(combinedAmountForDate, entry.getValue()); } } }
@Test public void presentValueDiscountingCalculator() { final MultipleCurrencyAmount pvSwap = SWAP_MULTI_LEG.accept(PVDC, MULTICURVES); MultipleCurrencyAmount pvLegs = MultipleCurrencyAmount.of(EUR, 0.0); for (int loopleg = 0; loopleg < NB_LEGS; loopleg++) { pvLegs = pvLegs.plus(SWAP_MULTI_LEG.getLegs()[loopleg].accept(PVDC, MULTICURVES)); } assertEquals( "SwapMultileg: presentValueDiscountingCalculator", pvSwap.getAmount(EUR), pvLegs.getAmount(EUR), TOLERANCE_PV); }
@Test /** Tests payer/receiver/swap parity. */ public void payerReceiverParityExplicit() { final MultipleCurrencyAmount pvReceiverLong = METHOD_HW.presentValue(SWAPTION_LONG_RECEIVER, HW_MULTICURVES); final MultipleCurrencyAmount pvPayerShort = METHOD_HW.presentValue(SWAPTION_SHORT_PAYER, HW_MULTICURVES); final MultipleCurrencyAmount pvSwap = SWAP_RECEIVER.accept(PVDC, MULTICURVES); assertEquals( "Swaption physical - Hull-White - present value - payer/receiver/swap parity", pvReceiverLong.getAmount(EUR) + pvPayerShort.getAmount(EUR), pvSwap.getAmount(EUR), TOLERANCE_PV); }