//------------------------------------------------------------------------- public virtual void test_presentValueSensitivity() { for (int i = 0; i < NB_STRIKES; ++i) { ResolvedFxVanillaOption option = CALLS[i]; PointSensitivityBuilder point = PRICER.presentValueSensitivityRatesStickyStrike(option, RATES_PROVIDER, VOLS); CurrencyParameterSensitivities sensiComputed = RATES_PROVIDER.parameterSensitivity(point.build()); double timeToExpiry = VOLS.relativeTime(EXPIRY); double forwardRate = FX_PRICER.forwardFxRate(UNDERLYING[i], RATES_PROVIDER).fxRate(CURRENCY_PAIR); double strikeRate = option.Strike; SmileDeltaParameters smileAtTime = VOLS.Smile.smileForExpiry(timeToExpiry); double[] vols = smileAtTime.Volatility.toArray(); double df = RATES_PROVIDER.discountFactor(USD, PAY); CurrencyParameterSensitivities sensiExpected = FD_CAL.sensitivity(RATES_PROVIDER, p => PRICER.presentValue(option, p, VOLS)); CurrencyParameterSensitivities sensiRes = FD_CAL.sensitivity(RATES_PROVIDER, (ImmutableRatesProvider p) => { double fwd = FX_PRICER.forwardFxRate(option.Underlying, p).fxRate(CURRENCY_PAIR); double[] strs = smileAtTime.strike(fwd).toArray(); double[] wghts = weights(fwd, strikeRate, strs, timeToExpiry, vols[1]); double res = 0d; for (int j = 0; j < 3; ++j) { res += wghts[j] * (BlackFormulaRepository.price(forwardRate, strs[j], timeToExpiry, vols[j], true) - BlackFormulaRepository.price(forwardRate, strs[j], timeToExpiry, vols[1], true)); } return(CurrencyAmount.of(USD, -res * df * NOTIONAL)); }); assertTrue(sensiComputed.equalWithTolerance(sensiExpected.combinedWith(sensiRes), FD_EPS * NOTIONAL * 10d)); } }
// computes sensitivity with finite difference approximation private CurrencyParameterSensitivities fdSensitivityWithZSpread(CapitalIndexedBondPaymentPeriod period, ImmutableRatesProvider ratesProvider, LegalEntityDiscountingProvider issuerRatesProvider, double zSpread, CompoundedRateType compoundedRateType, int periodsPerYear) { CurrencyParameterSensitivities sensi1 = FD_CAL.sensitivity(issuerRatesProvider, p => CurrencyAmount.of(USD, PRICER.presentValueWithZSpread(period, ratesProvider, p.issuerCurveDiscountFactors(CapitalIndexedBondCurveDataSet.IssuerId, USD), zSpread, compoundedRateType, periodsPerYear))); CurrencyParameterSensitivities sensi2 = FD_CAL.sensitivity(ratesProvider, p => CurrencyAmount.of(USD, PRICER.presentValueWithZSpread(period, p, issuerRatesProvider.issuerCurveDiscountFactors(CapitalIndexedBondCurveDataSet.IssuerId, USD), zSpread, compoundedRateType, periodsPerYear))); return(sensi1.combinedWith(sensi2)); }
public virtual void test_presentValueSensitivity() { PointSensitivities point = PRICER.presentValueSensitivity(FWD, PROVIDER); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expectedUsd = CAL_FD.sensitivity(PROVIDER, (p) => PRICER.presentValue(FWD, (p)).getAmount(USD)); CurrencyParameterSensitivities expectedKrw = CAL_FD.sensitivity(PROVIDER, (p) => PRICER.presentValue(FWD, (p)).getAmount(KRW)); assertTrue(computed.equalWithTolerance(expectedUsd.combinedWith(expectedKrw), NOMINAL_USD * FX_RATE * EPS_FD)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity of the FX barrier option trade. /// <para> /// The present value sensitivity of the trade is the sensitivity of the present value to /// the underlying curves. /// </para> /// <para> /// The sensitivity is computed by bump and re-price, returning <seealso cref="CurrencyParameterSensitivities"/>, /// not <seealso cref="PointSensitivities"/>. /// </para> /// <para> /// The trinomial tree is first calibrated to Black volatilities, /// then the price is computed based on the calibrated tree. /// /// </para> /// </summary> /// <param name="trade"> the option trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the Black volatility provider </param> /// <returns> the present value curve sensitivity of the trade </returns> public virtual CurrencyParameterSensitivities presentValueSensitivityRates(ResolvedFxSingleBarrierOptionTrade trade, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { ResolvedFxSingleBarrierOption product = trade.Product; CurrencyParameterSensitivities sensProduct = productPricer.presentValueSensitivityRates(product, ratesProvider, volatilities); Payment premium = trade.Premium; PointSensitivityBuilder pvcsPremium = paymentPricer.presentValueSensitivity(premium, ratesProvider); CurrencyParameterSensitivities sensPremium = ratesProvider.parameterSensitivity(pvcsPremium.build()); return(sensProduct.combinedWith(sensPremium)); }
public virtual void test_presentValueSensitivity_started() { ResolvedFxSwap product = ResolvedFxSwap.ofForwardPoints(CurrencyAmount.of(USD, NOMINAL_USD), KRW, FX_RATE, FX_FWD_POINTS, PAYMENT_DATE_PAST, PAYMENT_DATE_NEAR); PointSensitivities point = PRICER.presentValueSensitivity(product, PROVIDER); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expectedUsd = CAL_FD.sensitivity(PROVIDER, (p) => PRICER.presentValue(product, (p)).getAmount(USD)); CurrencyParameterSensitivities expectedKrw = CAL_FD.sensitivity(PROVIDER, (p) => PRICER.presentValue(product, (p)).getAmount(KRW)); assertTrue(computed.equalWithTolerance(expectedUsd.combinedWith(expectedKrw), NOMINAL_USD * FX_RATE * EPS_FD)); }
public virtual void test_presentValueSensitivity_position() { PointSensitivities point = PRICER.presentValueSensitivity(POSITION, RATES_PROVIDER, ISSUER_RATES_PROVIDER); CurrencyParameterSensitivities computed = ISSUER_RATES_PROVIDER.parameterSensitivity(point).combinedWith(RATES_PROVIDER.parameterSensitivity(point)); CurrencyParameterSensitivities fdRates = FD_CAL.sensitivity(RATES_PROVIDER, p => PRICER.presentValue(POSITION, p, ISSUER_RATES_PROVIDER)); CurrencyParameterSensitivities fdPrice = FD_CAL.sensitivity(ISSUER_RATES_PROVIDER, p => PRICER.presentValue(POSITION, RATES_PROVIDER, p)); CurrencyParameterSensitivities expected = fdRates.combinedWith(fdPrice); assertTrue(computed.equalWithTolerance(expected, NOTIONAL * QUANTITY * EPS)); }
public virtual void test_presentValueSensitivityWithZSpread_afterFix() { PointSensitivityBuilder pointInterp = PRICER.presentValueSensitivityWithZSpread(PERIOD_INTERP, IRP_AFTER_FIX, ICDF_AFTER_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyParameterSensitivities computedInterp1 = LEDP_AFTER_FIX.parameterSensitivity(pointInterp.build()); CurrencyParameterSensitivities computedInterp2 = IRP_AFTER_FIX.parameterSensitivity(pointInterp.build()); PointSensitivityBuilder pointMonthly = PRICER.presentValueSensitivityWithZSpread(PERIOD_MONTHLY, IRP_AFTER_FIX, ICDF_AFTER_FIX, Z_SPREAD, CONTINUOUS, 0); CurrencyParameterSensitivities computedMonthly1 = LEDP_AFTER_FIX.parameterSensitivity(pointMonthly.build()); CurrencyParameterSensitivities computedMonthly2 = IRP_AFTER_FIX.parameterSensitivity(pointMonthly.build()); CurrencyParameterSensitivities expectedInterp = fdSensitivityWithZSpread(PERIOD_INTERP, IRP_AFTER_FIX, LEDP_AFTER_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyParameterSensitivities expectedMonthly = fdSensitivityWithZSpread(PERIOD_MONTHLY, IRP_AFTER_FIX, LEDP_AFTER_FIX, Z_SPREAD, CONTINUOUS, 0); assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS)); assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS)); }
public virtual void test_presentValueSensitivity_onFix() { PointSensitivityBuilder pointInterp = PRICER.presentValueSensitivity(PERIOD_INTERP, IRP_ON_FIX, ICDF_ON_FIX); CurrencyParameterSensitivities computedInterp1 = LEDP_ON_FIX.parameterSensitivity(pointInterp.build()); CurrencyParameterSensitivities computedInterp2 = IRP_ON_FIX.parameterSensitivity(pointInterp.build()); PointSensitivityBuilder pointMonthly = PRICER.presentValueSensitivity(PERIOD_MONTHLY, IRP_ON_FIX, ICDF_ON_FIX); CurrencyParameterSensitivities computedMonthly1 = LEDP_ON_FIX.parameterSensitivity(pointMonthly.build()); CurrencyParameterSensitivities computedMonthly2 = IRP_ON_FIX.parameterSensitivity(pointMonthly.build()); CurrencyParameterSensitivities expectedInterp = fdSensitivity(PERIOD_INTERP, IRP_ON_FIX, LEDP_ON_FIX); CurrencyParameterSensitivities expectedMonthly = fdSensitivity(PERIOD_MONTHLY, IRP_ON_FIX, LEDP_ON_FIX); assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS)); assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS)); }
public virtual void test_presentValueSensitivityModelParamsVolatility_after() { PointSensitivityBuilder capComputed = PRICER.presentValueSensitivityModelParamsVolatility(CAP, RATES_AFTER, VOLS_AFTER); PointSensitivityBuilder floorComputed = PRICER.presentValueSensitivityModelParamsVolatility(FLOOR, RATES_AFTER, VOLS_AFTER); CurrencyParameterSensitivities capExpected = CurrencyParameterSensitivities.empty(); CurrencyParameterSensitivities floorExpected = CurrencyParameterSensitivities.empty(); int nPeriods = CAP.CapletFloorletPeriods.size(); for (int i = 3; i < nPeriods; ++i) { capExpected = capExpected.combinedWith(VOLS_AFTER.parameterSensitivity(PRICER_PERIOD.presentValueSensitivityModelParamsVolatility(CAP.CapletFloorletPeriods.get(i), RATES_AFTER, VOLS_AFTER).build())); floorExpected = floorExpected.combinedWith(VOLS_AFTER.parameterSensitivity(PRICER_PERIOD.presentValueSensitivityModelParamsVolatility(FLOOR.CapletFloorletPeriods.get(i), RATES_AFTER, VOLS_AFTER).build())); } CurrencyParameterSensitivities capSensiComputed = VOLS_AFTER.parameterSensitivity(capComputed.build()); CurrencyParameterSensitivities floorSensiComputed = VOLS_AFTER.parameterSensitivity(floorComputed.build()); assertTrue(capSensiComputed.equalWithTolerance(capExpected, TOL * NOTIONAL_VALUE)); assertTrue(floorSensiComputed.equalWithTolerance(floorExpected, TOL * NOTIONAL_VALUE)); }
//------------------------------------------------------------------------- public virtual void test_presentValueSensitivityVolatility() { PointSensitivityBuilder capComputed = PRICER.presentValueSensitivityModelParamsVolatility(CAP, RATES, VOLS); PointSensitivityBuilder floorComputed = PRICER.presentValueSensitivityModelParamsVolatility(FLOOR, RATES, VOLS); CurrencyParameterSensitivities capExpected = CurrencyParameterSensitivities.empty(); CurrencyParameterSensitivities floorExpected = CurrencyParameterSensitivities.empty(); int nPeriods = CAP.CapletFloorletPeriods.size(); for (int i = 0; i < nPeriods; ++i) { capExpected = capExpected.combinedWith(VOLS.parameterSensitivity(PRICER_PERIOD.presentValueSensitivityModelParamsVolatility(CAP.CapletFloorletPeriods.get(i), RATES, VOLS).build())); floorExpected = floorExpected.combinedWith(VOLS.parameterSensitivity(PRICER_PERIOD.presentValueSensitivityModelParamsVolatility(FLOOR.CapletFloorletPeriods.get(i), RATES, VOLS).build())); } CurrencyParameterSensitivities capSensiComputed = VOLS.parameterSensitivity(capComputed.build()); CurrencyParameterSensitivities floorSensiComputed = VOLS.parameterSensitivity(floorComputed.build()); CurrencyParameterSensitivity capSensiExpected = capExpected.Sensitivities.get(0); CurrencyParameterSensitivity floorSensiExpected = floorExpected.Sensitivities.get(0); assertTrue(DoubleArrayMath.fuzzyEquals(capSensiComputed.Sensitivities.get(0).Sensitivity.toArray(), capSensiExpected.Sensitivity.toArray(), TOL * NOTIONAL_VALUE)); assertTrue(DoubleArrayMath.fuzzyEquals(floorSensiComputed.Sensitivities.get(0).Sensitivity.toArray(), floorSensiExpected.Sensitivity.toArray(), TOL * NOTIONAL_VALUE)); }
//------------------------------------------------------------------------- public virtual void test_presentValueSensitivity() { // call PointSensitivities pointCall = PRICER.presentValueSensitivityRatesStickyStrike(CALL_OTM, RATES_PROVIDER, VOLS); CurrencyParameterSensitivities computedCall = RATES_PROVIDER.parameterSensitivity(pointCall); CurrencyParameterSensitivities expectedCall = FD_CAL.sensitivity(RATES_PROVIDER, (p) => PRICER.presentValue(CALL_OTM, (p), VOLS)); // contribution via implied volatility, to be subtracted. CurrencyAmount pvVegaCall = PRICER.presentValueVega(CALL_OTM, RATES_PROVIDER, VOLS); CurrencyParameterSensitivities impliedVolSenseCall = FD_CAL.sensitivity(RATES_PROVIDER, (p) => CurrencyAmount.of(USD, PRICER.impliedVolatility(CALL_OTM, (p), VOLS))).multipliedBy(-pvVegaCall.Amount); assertTrue(computedCall.equalWithTolerance(expectedCall.combinedWith(impliedVolSenseCall), NOTIONAL * FD_EPS)); // put PointSensitivities pointPut = PRICER.presentValueSensitivityRatesStickyStrike(PUT_OTM, RATES_PROVIDER, VOLS); CurrencyParameterSensitivities computedPut = RATES_PROVIDER.parameterSensitivity(pointPut); CurrencyParameterSensitivities expectedPut = FD_CAL.sensitivity(RATES_PROVIDER, (p) => PRICER.presentValue(PUT_OTM, (p), VOLS)); // contribution via implied volatility, to be subtracted. CurrencyAmount pvVegaPut = PRICER.presentValueVega(PUT_OTM, RATES_PROVIDER, VOLS); CurrencyParameterSensitivities impliedVolSensePut = FD_CAL.sensitivity(RATES_PROVIDER, (p) => CurrencyAmount.of(USD, PRICER.impliedVolatility(PUT_OTM, (p), VOLS))).multipliedBy(-pvVegaPut.Amount); assertTrue(computedPut.equalWithTolerance(expectedPut.combinedWith(impliedVolSensePut), NOTIONAL * FD_EPS)); }