//------------------------------------------------------------------------- //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @ImmutableValidator private void validate() private void validate() { ArgChecker.inOrderOrEqual(deliveryDate, underlyingSwap.StartDate, "deliveryDate", "startDate"); ArgChecker.isFalse(underlyingSwap.CrossCurrency, "underlying swap must not be cross currency"); foreach (ResolvedSwapLeg swapLeg in underlyingSwap.Legs) { if (swapLeg.Type.Equals(SwapLegType.FIXED)) { ArgChecker.isTrue(swapLeg.PayReceive.Receive, "underlying must be receiver swap"); } foreach (SwapPaymentEvent @event in swapLeg.PaymentEvents) { ArgChecker.isTrue(@event is NotionalExchange, "PaymentEvent must be NotionalExchange"); NotionalExchange notioanlEvent = (NotionalExchange)@event; ArgChecker.isTrue(Math.Abs(notioanlEvent.PaymentAmount.Amount) == 1d, "notional of underlying swap must be unity"); } foreach (SwapPaymentPeriod period in swapLeg.PaymentPeriods) { ArgChecker.isTrue(period is NotionalPaymentPeriod, "PaymentPeriod must be NotionalPaymentPeriod"); NotionalPaymentPeriod notioanlPeriod = (NotionalPaymentPeriod)period; ArgChecker.isTrue(Math.Abs(notioanlPeriod.NotionalAmount.Amount) == 1d, "notional of underlying swap must be unity"); } } ArgChecker.inOrderOrEqual(lastTradeDate, deliveryDate, "lastTradeDate", "deliveryDate"); }
/// <summary> /// Computes cash flow equivalent of Ibor leg. /// <para> /// The return type is {@code ResolvedSwapLeg} in which individual payments are /// represented in terms of {@code NotionalExchange}. /// /// </para> /// </summary> /// <param name="iborLeg"> the Ibor leg </param> /// <param name="ratesProvider"> the rates provider </param> /// <returns> the cash flow equivalent </returns> public static ResolvedSwapLeg cashFlowEquivalentIborLeg(ResolvedSwapLeg iborLeg, RatesProvider ratesProvider) { ArgChecker.isTrue(iborLeg.Type.Equals(SwapLegType.IBOR), "Leg type should be IBOR"); ArgChecker.isTrue(iborLeg.PaymentEvents.Empty, "PaymentEvent should be empty"); IList <NotionalExchange> paymentEvents = new List <NotionalExchange>(); foreach (SwapPaymentPeriod paymentPeriod in iborLeg.PaymentPeriods) { ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "rate payment should be RatePaymentPeriod"); RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod; ArgChecker.isTrue(ratePaymentPeriod.AccrualPeriods.size() == 1, "rate payment should not be compounding"); RateAccrualPeriod rateAccrualPeriod = ratePaymentPeriod.AccrualPeriods.get(0); CurrencyAmount notional = ratePaymentPeriod.NotionalAmount; LocalDate paymentDate = ratePaymentPeriod.PaymentDate; IborIndexObservation obs = ((IborRateComputation)rateAccrualPeriod.RateComputation).Observation; IborIndex index = obs.Index; LocalDate fixingStartDate = obs.EffectiveDate; double fixingYearFraction = obs.YearFraction; double beta = (1d + fixingYearFraction * ratesProvider.iborIndexRates(index).rate(obs)) * ratesProvider.discountFactor(paymentPeriod.Currency, paymentPeriod.PaymentDate) / ratesProvider.discountFactor(paymentPeriod.Currency, fixingStartDate); double ycRatio = rateAccrualPeriod.YearFraction / fixingYearFraction; NotionalExchange payStart = NotionalExchange.of(notional.multipliedBy(beta * ycRatio), fixingStartDate); NotionalExchange payEnd = NotionalExchange.of(notional.multipliedBy(-ycRatio), paymentDate); paymentEvents.Add(payStart); paymentEvents.Add(payEnd); } ResolvedSwapLeg leg = ResolvedSwapLeg.builder().paymentEvents(paymentEvents).payReceive(PayReceive.RECEIVE).type(SwapLegType.OTHER).build(); return(leg); }
/// <summary> /// Calculates the present value of the swaption product. /// <para> /// The result is expressed using the currency of the swapion. /// /// </para> /// </summary> /// <param name="swaption"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="hwProvider"> the Hull-White model parameter provider </param> /// <returns> the present value </returns> public virtual CurrencyAmount presentValue(ResolvedSwaption swaption, RatesProvider ratesProvider, HullWhiteOneFactorPiecewiseConstantParametersProvider hwProvider) { validate(swaption, ratesProvider, hwProvider); ResolvedSwap swap = swaption.Underlying; LocalDate expiryDate = swaption.ExpiryDate; if (expiryDate.isBefore(ratesProvider.ValuationDate)) { // Option has expired already return(CurrencyAmount.of(swap.Legs.get(0).Currency, 0d)); } ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, ratesProvider); int nPayments = cashFlowEquiv.PaymentEvents.size(); double[] alpha = new double[nPayments]; double[] discountedCashFlow = new double[nPayments]; for (int loopcf = 0; loopcf < nPayments; loopcf++) { NotionalExchange payment = (NotionalExchange)cashFlowEquiv.PaymentEvents.get(loopcf); LocalDate maturityDate = payment.PaymentDate; alpha[loopcf] = hwProvider.alpha(ratesProvider.ValuationDate, expiryDate, expiryDate, maturityDate); discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment.Payment, ratesProvider); } double omega = (swap.getLegs(SwapLegType.FIXED).get(0).PayReceive.Pay ? -1d : 1d); double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega); double pv = 0.0; for (int loopcf = 0; loopcf < nPayments; loopcf++) { pv += discountedCashFlow[loopcf] * NORMAL.getCDF(omega * (kappa + alpha[loopcf])); } return(CurrencyAmount.of(cashFlowEquiv.Currency, pv * (swaption.LongShort.Long ? 1d : -1d))); }
//------------------------------------------------------------------------- // creates a simple provider private SimpleRatesProvider createProvider(NotionalExchange ne) { LocalDate paymentDate = ne.PaymentDate; double paymentTime = DAY_COUNT.relativeYearFraction(VAL_DATE, paymentDate); Currency currency = ne.Currency; DiscountFactors mockDf = mock(typeof(DiscountFactors)); when(mockDf.discountFactor(paymentDate)).thenReturn(DISCOUNT_FACTOR); ZeroRateSensitivity sens = ZeroRateSensitivity.of(currency, paymentTime, -DISCOUNT_FACTOR * paymentTime); when(mockDf.zeroRatePointSensitivity(paymentDate)).thenReturn(sens); SimpleRatesProvider prov = new SimpleRatesProvider(VAL_DATE, mockDf); prov.DayCount = DAY_COUNT; return(prov); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity to piecewise constant volatility parameters of the Hull-White model. /// </summary> /// <param name="swaption"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="hwProvider"> the Hull-White model parameter provider </param> /// <returns> the present value Hull-White model parameter sensitivity of the swaption product </returns> public virtual DoubleArray presentValueSensitivityModelParamsHullWhite(ResolvedSwaption swaption, RatesProvider ratesProvider, HullWhiteOneFactorPiecewiseConstantParametersProvider hwProvider) { validate(swaption, ratesProvider, hwProvider); ResolvedSwap swap = swaption.Underlying; LocalDate expiryDate = swaption.ExpiryDate; if (expiryDate.isBefore(ratesProvider.ValuationDate)) { // Option has expired already return(DoubleArray.EMPTY); } ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, ratesProvider); int nPayments = cashFlowEquiv.PaymentEvents.size(); double[] alpha = new double[nPayments]; double[][] alphaAdjoint = new double[nPayments][]; double[] discountedCashFlow = new double[nPayments]; for (int loopcf = 0; loopcf < nPayments; loopcf++) { NotionalExchange payment = (NotionalExchange)cashFlowEquiv.PaymentEvents.get(loopcf); ValueDerivatives valueDeriv = hwProvider.alphaAdjoint(ratesProvider.ValuationDate, expiryDate, expiryDate, payment.PaymentDate); alpha[loopcf] = valueDeriv.Value; alphaAdjoint[loopcf] = valueDeriv.Derivatives.toArray(); discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment.Payment, ratesProvider); } double omega = (swap.getLegs(SwapLegType.FIXED).get(0).PayReceive.Pay ? -1d : 1d); double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega); int nParams = alphaAdjoint[0].Length; if (Math.Abs(kappa) > 1d / SMALL) { // decays exponentially return(DoubleArray.filled(nParams)); } double[] pvSensi = new double[nParams]; double sign = (swaption.LongShort.Long ? 1d : -1d); for (int i = 0; i < nParams; ++i) { for (int loopcf = 0; loopcf < nPayments; loopcf++) { pvSensi[i] += sign * discountedCashFlow[loopcf] * NORMAL.getPDF(omega * (kappa + alpha[loopcf])) * omega * alphaAdjoint[loopcf][i]; } } return(DoubleArray.ofUnsafe(pvSensi)); }
/// <summary> /// Computes cash flow equivalent of fixed leg. /// <para> /// The return type is {@code ResolvedSwapLeg} in which individual payments are /// represented in terms of {@code NotionalExchange}. /// /// </para> /// </summary> /// <param name="fixedLeg"> the fixed leg </param> /// <param name="ratesProvider"> the rates provider </param> /// <returns> the cash flow equivalent </returns> public static ResolvedSwapLeg cashFlowEquivalentFixedLeg(ResolvedSwapLeg fixedLeg, RatesProvider ratesProvider) { ArgChecker.isTrue(fixedLeg.Type.Equals(SwapLegType.FIXED), "Leg type should be FIXED"); ArgChecker.isTrue(fixedLeg.PaymentEvents.Empty, "PaymentEvent should be empty"); IList <NotionalExchange> paymentEvents = new List <NotionalExchange>(); foreach (SwapPaymentPeriod paymentPeriod in fixedLeg.PaymentPeriods) { ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "rate payment should be RatePaymentPeriod"); RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod; ArgChecker.isTrue(ratePaymentPeriod.AccrualPeriods.size() == 1, "rate payment should not be compounding"); RateAccrualPeriod rateAccrualPeriod = ratePaymentPeriod.AccrualPeriods.get(0); double factor = rateAccrualPeriod.YearFraction * ((FixedRateComputation)rateAccrualPeriod.RateComputation).Rate; CurrencyAmount notional = ratePaymentPeriod.NotionalAmount.multipliedBy(factor); LocalDate paymentDate = ratePaymentPeriod.PaymentDate; NotionalExchange pay = NotionalExchange.of(notional, paymentDate); paymentEvents.Add(pay); } ResolvedSwapLeg leg = ResolvedSwapLeg.builder().paymentEvents(paymentEvents).payReceive(PayReceive.RECEIVE).type(SwapLegType.OTHER).build(); return(leg); }
private IList <ZeroRateSensitivity> dscSensitivityFD(RatesProvider provider, NotionalExchange @event, double eps) { Currency currency = @event.Currency; LocalDate paymentDate = @event.PaymentDate; double discountFactor = provider.discountFactor(currency, paymentDate); double paymentTime = DAY_COUNT.relativeYearFraction(VAL_DATE, paymentDate); RatesProvider provUp = mock(typeof(RatesProvider)); RatesProvider provDw = mock(typeof(RatesProvider)); when(provUp.ValuationDate).thenReturn(VAL_DATE); when(provUp.discountFactor(currency, paymentDate)).thenReturn(discountFactor * Math.Exp(-eps * paymentTime)); when(provDw.ValuationDate).thenReturn(VAL_DATE); when(provDw.discountFactor(currency, paymentDate)).thenReturn(discountFactor * Math.Exp(eps * paymentTime)); DiscountingNotionalExchangePricer pricer = DiscountingNotionalExchangePricer.DEFAULT; double pvUp = pricer.presentValue(@event, provUp); double pvDw = pricer.presentValue(@event, provDw); double res = 0.5 * (pvUp - pvDw) / eps; IList <ZeroRateSensitivity> zeroRateSensi = new List <ZeroRateSensitivity>(); zeroRateSensi.Add(ZeroRateSensitivity.of(currency, paymentTime, res)); return(zeroRateSensi); }