//------------------------------------------------------------------------- /// <summary> /// Explains the present value of the FRA product. /// <para> /// This returns explanatory information about the calculation. /// /// </para> /// </summary> /// <param name="fra"> the FRA product for which present value should be computed </param> /// <param name="provider"> the rates provider </param> /// <returns> the explanatory information </returns> public virtual ExplainMap explainPresentValue(ResolvedFra fra, RatesProvider provider) { ExplainMapBuilder builder = ExplainMap.builder(); Currency currency = fra.Currency; builder.put(ExplainKey.ENTRY_TYPE, "FRA"); builder.put(ExplainKey.PAYMENT_DATE, fra.PaymentDate); builder.put(ExplainKey.START_DATE, fra.StartDate); builder.put(ExplainKey.END_DATE, fra.EndDate); builder.put(ExplainKey.ACCRUAL_YEAR_FRACTION, fra.YearFraction); builder.put(ExplainKey.DAYS, (int)DAYS.between(fra.StartDate, fra.EndDate)); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.NOTIONAL, CurrencyAmount.of(currency, fra.Notional)); builder.put(ExplainKey.TRADE_NOTIONAL, CurrencyAmount.of(currency, fra.Notional)); if (fra.PaymentDate.isBefore(provider.ValuationDate)) { builder.put(ExplainKey.COMPLETED, true); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.zero(currency)); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.zero(currency)); } else { double rate = rateComputationFn.explainRate(fra.FloatingRate, fra.StartDate, fra.EndDate, provider, builder); builder.put(ExplainKey.FIXED_RATE, fra.FixedRate); builder.put(ExplainKey.DISCOUNT_FACTOR, provider.discountFactor(currency, fra.PaymentDate)); builder.put(ExplainKey.PAY_OFF_RATE, rate); builder.put(ExplainKey.UNIT_AMOUNT, unitAmount(fra, provider)); builder.put(ExplainKey.FORECAST_VALUE, forecastValue(fra, provider)); builder.put(ExplainKey.PRESENT_VALUE, presentValue(fra, provider)); } return(builder.build()); }
/// <summary> /// Calculates the forecast value sensitivity of the FRA product. /// <para> /// The forecast value sensitivity of the product is the sensitivity of the forecast value to /// the underlying curves. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the point sensitivity of the forecast value </returns> public virtual PointSensitivities forecastValueSensitivity(ResolvedFra fra, RatesProvider provider) { double notional = fra.Notional; double derivative = this.derivative(fra, provider); PointSensitivityBuilder iborSens = forwardRateSensitivity(fra, provider).multipliedBy(derivative * notional); return(iborSens.withCurrency(fra.Currency).build()); }
// AFMA discounting method private double derivativeAfma(ResolvedFra fra, RatesProvider provider) { double forwardRate = this.forwardRate(fra, provider); double yearFraction = fra.YearFraction; double dsc = 1.0 / (1.0 + forwardRate * yearFraction); return(yearFraction * dsc * dsc); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the FRA product. /// <para> /// The present value of the product is the value on the valuation date. /// This is the discounted forecast value. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the present value of the product </returns> public virtual CurrencyAmount presentValue(ResolvedFra fra, RatesProvider provider) { // forecastValue * discountFactor double df = provider.discountFactor(fra.Currency, fra.PaymentDate); double pv = forecastValue0(fra, provider) * df; return(CurrencyAmount.of(fra.Currency, pv)); }
// NONE discounting method private double unitAmountNone(ResolvedFra fra, RatesProvider provider) { double fixedRate = fra.FixedRate; double forwardRate = this.forwardRate(fra, provider); double yearFraction = fra.YearFraction; return((forwardRate - fixedRate) * yearFraction); }
// AFMA discounting method private double unitAmountAfma(ResolvedFra fra, RatesProvider provider) { double fixedRate = fra.FixedRate; double forwardRate = this.forwardRate(fra, provider); double yearFraction = fra.YearFraction; return((1.0 / (1.0 + fixedRate * yearFraction)) - (1.0 / (1.0 + forwardRate * yearFraction))); }
//------------------------------------------------------------------------- // calculates the forecast value private double forecastValue0(ResolvedFra fra, RatesProvider provider) { if (fra.PaymentDate.isBefore(provider.ValuationDate)) { return(0d); } // notional * unitAmount return(fra.Notional * unitAmount(fra, provider)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the future cash flow of the FRA product. /// <para> /// There is only one cash flow on the payment date for the FRA product. /// The expected currency amount of the cash flow is the same as <seealso cref="#forecastValue(ResolvedFra, RatesProvider)"/>. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the cash flows </returns> public virtual CashFlows cashFlows(ResolvedFra fra, RatesProvider provider) { LocalDate paymentDate = fra.PaymentDate; double forecastValue = forecastValue0(fra, provider); double df = provider.discountFactor(fra.Currency, paymentDate); CashFlow cashFlow = CashFlow.ofForecastValue(paymentDate, fra.Currency, forecastValue, df); return(CashFlows.of(cashFlow)); }
/// <summary> /// Calculates the current cash of the FRA trade. /// </summary> /// <param name="trade"> the trade </param> /// <param name="provider"> the rates provider </param> /// <returns> the current cash </returns> public virtual CurrencyAmount currentCash(ResolvedFraTrade trade, RatesProvider provider) { ResolvedFra fra = trade.Product; if (fra.PaymentDate.isEqual(provider.ValuationDate)) { return(productPricer.presentValue(fra, provider)); } return(CurrencyAmount.zero(fra.Currency)); }
/// <summary> /// Calculates the present value sensitivity of the FRA product. /// <para> /// The present value sensitivity of the product is the sensitivity of the present value to /// the underlying curves. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the point sensitivity of the present value </returns> public virtual PointSensitivities presentValueSensitivity(ResolvedFra fra, RatesProvider provider) { DiscountFactors discountFactors = provider.discountFactors(fra.Currency); double df = discountFactors.discountFactor(fra.PaymentDate); double notional = fra.Notional; double unitAmount = this.unitAmount(fra, provider); double derivative = this.derivative(fra, provider); PointSensitivityBuilder iborSens = forwardRateSensitivity(fra, provider).multipliedBy(derivative * df * notional); PointSensitivityBuilder discSens = discountFactors.zeroRatePointSensitivity(fra.PaymentDate).multipliedBy(unitAmount * notional); return(iborSens.withCurrency(fra.Currency).combinedWith(discSens).build()); }
//------------------------------------------------------------------------- // determine the derivative private double derivative(ResolvedFra fra, RatesProvider provider) { switch (fra.Discounting) { case NONE: return(derivativeNone(fra, provider)); case ISDA: return(derivativeIsda(fra, provider)); case AFMA: return(derivativeAfma(fra, provider)); default: throw new System.ArgumentException("Unknown FraDiscounting value: " + fra.Discounting); } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the forecast value of the FRA product. /// <para> /// The forecast value of the product is the value on the valuation date without present value discounting. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the forecast value of the product </returns> public virtual CurrencyAmount forecastValue(ResolvedFra fra, RatesProvider provider) { double fv = forecastValue0(fra, provider); return(CurrencyAmount.of(fra.Currency, fv)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the par rate of the FRA product. /// <para> /// The par rate is the rate for which the FRA present value is 0. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the par rate </returns> public virtual double parRate(ResolvedFra fra, RatesProvider provider) { return(forwardRate(fra, provider)); }
// query the sensitivity private PointSensitivityBuilder forwardRateSensitivity(ResolvedFra fra, RatesProvider provider) { return(rateComputationFn.rateSensitivity(fra.FloatingRate, fra.StartDate, fra.EndDate, provider)); }
//------------------------------------------------------------------------- // query the forward rate private double forwardRate(ResolvedFra fra, RatesProvider provider) { return(rateComputationFn.rate(fra.FloatingRate, fra.StartDate, fra.EndDate, provider)); }
/// <summary> /// Calculates the par spread of the FRA product. /// <para> /// This is spread to be added to the fixed rate to have a present value of 0. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the par spread </returns> public virtual double parSpread(ResolvedFra fra, RatesProvider provider) { double forward = forwardRate(fra, provider); return(forward - fra.FixedRate); }
// NONE discounting method private double derivativeNone(ResolvedFra fra, RatesProvider provider) { return(fra.YearFraction); }
/// <summary> /// Calculates the par spread curve sensitivity of the FRA product. /// <para> /// The par spread curve sensitivity of the product is the sensitivity of the par spread to /// the underlying curves. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the par spread sensitivity </returns> public virtual PointSensitivities parSpreadSensitivity(ResolvedFra fra, RatesProvider provider) { return(forwardRateSensitivity(fra, provider).build()); }