//-------------------------------------------------------------------------
        private ValueDerivatives priceDerivatives(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData data)
        {
            validate(option, ratesProvider, volatilities);
            validateData(option, ratesProvider, volatilities, data);
            int nSteps = data.NumberOfSteps;
            ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption;
            double           timeToExpiry            = data.getTime(nSteps);
            ResolvedFxSingle underlyingFx            = underlyingOption.Underlying;
            Currency         ccyBase                  = underlyingFx.CounterCurrencyPayment.Currency;
            Currency         ccyCounter               = underlyingFx.CounterCurrencyPayment.Currency;
            DiscountFactors  baseDiscountFactors      = ratesProvider.discountFactors(ccyBase);
            DiscountFactors  counterDiscountFactors   = ratesProvider.discountFactors(ccyCounter);
            double           rebateAtExpiry           = 0d; // used to price knock-in option
            double           rebateAtExpiryDerivative = 0d; // used to price knock-in option
            double           notional                 = Math.Abs(underlyingFx.BaseCurrencyPayment.Amount);

            double[] rebateArray = new double[nSteps + 1];
            SimpleConstantContinuousBarrier barrier = (SimpleConstantContinuousBarrier)option.Barrier;

            if (option.Rebate.Present)
            {
                CurrencyAmount rebateCurrencyAmount = option.Rebate.get();
                double         rebatePerUnit        = rebateCurrencyAmount.Amount / notional;
                bool           isCounter            = rebateCurrencyAmount.Currency.Equals(ccyCounter);
                double         rebate = isCounter ? rebatePerUnit : rebatePerUnit * barrier.BarrierLevel;
                if (barrier.KnockType.KnockIn)
                {   // use in-out parity
                    double dfCounterAtExpiry = counterDiscountFactors.discountFactor(timeToExpiry);
                    double dfBaseAtExpiry    = baseDiscountFactors.discountFactor(timeToExpiry);
                    for (int i = 0; i < nSteps + 1; ++i)
                    {
                        rebateArray[i] = isCounter ? rebate * dfCounterAtExpiry / counterDiscountFactors.discountFactor(data.getTime(i)) : rebate * dfBaseAtExpiry / baseDiscountFactors.discountFactor(data.getTime(i));
                    }
                    if (isCounter)
                    {
                        rebateAtExpiry = rebatePerUnit * dfCounterAtExpiry;
                    }
                    else
                    {
                        rebateAtExpiry           = rebatePerUnit * data.Spot * dfBaseAtExpiry;
                        rebateAtExpiryDerivative = rebatePerUnit * dfBaseAtExpiry;
                    }
                }
                else
                {
                    Arrays.fill(rebateArray, rebate);
                }
            }
            ConstantContinuousSingleBarrierKnockoutFunction barrierFunction = ConstantContinuousSingleBarrierKnockoutFunction.of(underlyingOption.Strike, timeToExpiry, underlyingOption.PutCall, nSteps, barrier.BarrierType, barrier.BarrierLevel, DoubleArray.ofUnsafe(rebateArray));
            ValueDerivatives barrierPrice = TREE.optionPriceAdjoint(barrierFunction, data);

            if (barrier.KnockType.KnockIn)
            {     // use in-out parity
                EuropeanVanillaOptionFunction vanillaFunction = EuropeanVanillaOptionFunction.of(underlyingOption.Strike, timeToExpiry, underlyingOption.PutCall, nSteps);
                ValueDerivatives vanillaPrice = TREE.optionPriceAdjoint(vanillaFunction, data);
                return(ValueDerivatives.of(vanillaPrice.Value + rebateAtExpiry - barrierPrice.Value, DoubleArray.of(vanillaPrice.getDerivative(0) + rebateAtExpiryDerivative - barrierPrice.getDerivative(0))));
            }
            return(barrierPrice);
        }
예제 #2
0
        //-------------------------------------------------------------------------
        public virtual void test_presentValue()
        {
            CurrencyAmount pvComputed = PRICER.presentValue(BILL, PROVIDER);
            double         pvExpected = DSC_FACTORS_ISSUER.discountFactor(MATURITY_DATE) * NOTIONAL.Amount;

            assertEquals(pvComputed.Currency, EUR);
            assertEquals(pvComputed.Amount, pvExpected, TOLERANCE_PV);
        }
        //-------------------------------------------------------------------------
        public virtual void test_dirtyPriceFromCurves()
        {
            double         computed   = PRICER.dirtyPriceFromCurves(PRODUCT, PROVIDER, REF_DATA);
            CurrencyAmount pv         = PRICER.presentValue(PRODUCT, PROVIDER);
            LocalDate      settlement = DATE_OFFSET.adjust(VAL_DATE, REF_DATA);
            double         df         = DSC_FACTORS_REPO.discountFactor(settlement);

            assertEquals(computed, pv.Amount / df / NOTIONAL);
        }
        public virtual void test_discountFactorTimeDerivative()
        {
            DiscountFactors test = DiscountFactors.of(GBP, DATE_VAL, CURVE);
            double          relativeYearFraction = ACT_365F.relativeYearFraction(DATE_VAL, DATE_AFTER);
            double          expectedP            = test.discountFactor(relativeYearFraction + EPS);
            double          expectedM            = test.discountFactor(relativeYearFraction - EPS);

            assertEquals(test.discountFactorTimeDerivative(relativeYearFraction), (expectedP - expectedM) / (2 * EPS), TOL_FD);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the deposit fair rate given the start and end time and the accrual factor.
        /// <para>
        /// When the deposit has already started the number may not be meaningful as the remaining period
        /// is not in line with the accrual factor.
        ///
        /// </para>
        /// </summary>
        /// <param name="deposit">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the par rate </returns>
        public virtual double parRate(ResolvedTermDeposit deposit, RatesProvider provider)
        {
            Currency        currency        = deposit.Currency;
            DiscountFactors discountFactors = provider.discountFactors(currency);
            double          dfStart         = discountFactors.discountFactor(deposit.StartDate);
            double          dfEnd           = discountFactors.discountFactor(deposit.EndDate);
            double          accrualFactor   = deposit.YearFraction;

            return((dfStart / dfEnd - 1d) / accrualFactor);
        }
예제 #6
0
        private SimpleRatesProvider provider(LocalDate valuationDate, double dfStart, double dfEnd)
        {
            DiscountFactors mockDf = mock(typeof(DiscountFactors));

            when(mockDf.discountFactor(START_DATE)).thenReturn(dfStart);
            when(mockDf.discountFactor(END_DATE)).thenReturn(dfEnd);
            SimpleRatesProvider prov = new SimpleRatesProvider(valuationDate, mockDf);

            return(prov);
        }
예제 #7
0
        //-------------------------------------------------------------------------
        public virtual void priceFromCurves()
        {
            LocalDate settlementDate = VAL_DATE.plusDays(1);
            double    priceComputed  = PRICER.priceFromCurves(BILL, PROVIDER, settlementDate);
            double    dfMaturity     = DSC_FACTORS_ISSUER.discountFactor(MATURITY_DATE);
            double    dfSettle       = DSC_FACTORS_REPO.discountFactor(settlementDate);
            double    priceExpected  = dfMaturity / dfSettle;

            assertEquals(priceComputed, priceExpected, TOLERANCE_PRICE);
        }
	  /// <summary>
	  /// Test present value sensitivity for AFMA FRA discounting method.
	  /// </summary>
	  public virtual void test_presentValueSensitivity_AFMA()
	  {
		RateComputationFn<RateComputation> mockObs = mock(typeof(RateComputationFn));
		DiscountFactors mockDf = mock(typeof(DiscountFactors));
		SimpleRatesProvider simpleProv = new SimpleRatesProvider(VAL_DATE, mockDf);

		ResolvedFra fraExp = RFRA_AFMA;
		double forwardRate = 0.05;
		double discountRate = 0.025;
		double paymentTime = 0.3;
		double discountFactor = Math.Exp(-discountRate * paymentTime);
		LocalDate fixingDate = FRA_AFMA.StartDate;
		IborIndexObservation obs = IborIndexObservation.of(FRA.Index, fixingDate, REF_DATA);
		PointSensitivityBuilder sens = IborRateSensitivity.of(obs, 1d);
		when(mockDf.discountFactor(fraExp.PaymentDate)).thenReturn(discountFactor);
		when(mockDf.zeroRatePointSensitivity(fraExp.PaymentDate)).thenReturn(ZeroRateSensitivity.of(fraExp.Currency, paymentTime, -discountFactor * paymentTime));
		when(mockObs.rateSensitivity(fraExp.FloatingRate, fraExp.StartDate, fraExp.EndDate, simpleProv)).thenReturn(sens);
		when(mockObs.rate(fraExp.FloatingRate, FRA_AFMA.StartDate, FRA_AFMA.EndDate, simpleProv)).thenReturn(forwardRate);
		DiscountingFraProductPricer test = new DiscountingFraProductPricer(mockObs);
		PointSensitivities sensitivity = test.presentValueSensitivity(fraExp, simpleProv);
		double eps = 1.e-7;
		double fdDscSense = dscSensitivity(RFRA_AFMA, forwardRate, discountFactor, paymentTime, eps);
		double fdSense = presentValueFwdSensitivity(RFRA_AFMA, forwardRate, discountFactor, eps);

		ImmutableList<PointSensitivity> sensitivities = sensitivity.Sensitivities;
		assertEquals(sensitivities.size(), 2);
		IborRateSensitivity sensitivity0 = (IborRateSensitivity) sensitivities.get(0);
		assertEquals(sensitivity0.Index, FRA_AFMA.Index);
		assertEquals(sensitivity0.Observation.FixingDate, fixingDate);
		assertEquals(sensitivity0.Sensitivity, fdSense, FRA_AFMA.Notional * eps);
		ZeroRateSensitivity sensitivity1 = (ZeroRateSensitivity) sensitivities.get(1);
		assertEquals(sensitivity1.Currency, FRA_AFMA.Currency);
		assertEquals(sensitivity1.YearFraction, paymentTime);
		assertEquals(sensitivity1.Sensitivity, fdDscSense, FRA_AFMA.Notional * eps);
	  }
        /// <summary>
        /// Calibrate trinomial tree to Black volatilities.
        /// <para>
        /// {@code timeToExpiry} determines the coverage of the resulting trinomial tree.
        /// Thus this should match the time to expiry of the target instrument to price using the calibrated tree.
        ///
        /// </para>
        /// </summary>
        /// <param name="timeToExpiry">  the time to expiry </param>
        /// <param name="currencyPair">  the currency pair </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the trinomial tree data </returns>
        public virtual RecombiningTrinomialTreeData calibrateTrinomialTree(double timeToExpiry, CurrencyPair currencyPair, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities)
        {
            validate(ratesProvider, volatilities);
            if (timeToExpiry <= 0d)
            {
                throw new System.ArgumentException("option expired");
            }
            Currency        ccyBase                = currencyPair.Base;
            Currency        ccyCounter             = currencyPair.Counter;
            double          todayFx                = ratesProvider.fxRate(currencyPair);
            DiscountFactors baseDiscountFactors    = ratesProvider.discountFactors(ccyBase);
            DiscountFactors counterDiscountFactors = ratesProvider.discountFactors(ccyCounter);

            System.Func <double, double> interestRate = (double?t) =>
            {
                return(counterDiscountFactors.zeroRate(t.Value));
            };
            System.Func <double, double> dividendRate = (double?t) =>
            {
                return(baseDiscountFactors.zeroRate(t.Value));
            };
            System.Func <DoublesPair, double> impliedVolSurface = (DoublesPair tk) =>
            {
                double dfBase    = baseDiscountFactors.discountFactor(tk.First);
                double dfCounter = counterDiscountFactors.discountFactor(tk.First);
                double forward   = todayFx * dfBase / dfCounter;
                return(volatilities.volatility(currencyPair, tk.First, tk.Second, forward));
            };
            ImpliedTrinomialTreeLocalVolatilityCalculator localVol = new ImpliedTrinomialTreeLocalVolatilityCalculator(nSteps, timeToExpiry);

            return(localVol.calibrateImpliedVolatility(impliedVolSurface, todayFx, interestRate, dividendRate));
        }
        //-------------------------------------------------------------------------
        public virtual void calibration_test()
        {
            RatesProvider result2 = CALIBRATOR.calibrate(CURVE_GROUP_DEFN, ALL_QUOTES, REF_DATA);

            // pv test
            CurveNode[]           fwd3Nodes  = CURVES_NODES[0][0];
            IList <ResolvedTrade> fwd3Trades = new List <ResolvedTrade>();

            for (int i = 0; i < fwd3Nodes.Length; i++)
            {
                fwd3Trades.Add(fwd3Nodes[i].resolvedTrade(1d, ALL_QUOTES, REF_DATA));
            }
            for (int i = 0; i < FWD6_NB_NODES; i++)
            {
                MultiCurrencyAmount pvIrs2 = SWAP_PRICER.presentValue(((ResolvedSwapTrade)fwd3Trades[i]).Product, result2);
                assertEquals(pvIrs2.getAmount(GBP).Amount, 0.0, TOLERANCE_PV);
            }
            // regression test for curve
            DiscountFactors dsc     = result2.discountFactors(GBP);
            double          prevDsc = 0d;

            for (int i = 0; i < 121; ++i)
            {
                double time   = ((double)i);
                double curDsc = dsc.discountFactor(time);
                if (i > 59)
                {
                    double fwd = prevDsc / curDsc - 1d;
                    assertEquals(fwd, 0.042, 2d * ONE_BP);
                }
                assertEquals(curDsc, DSC_EXP.get(i), ONE_PC);
                prevDsc = curDsc;
            }
        }
 /// <summary>
 /// Computes the present value of the payment by discounting.
 /// <para>
 /// The present value is zero if the payment date is before the valuation date.
 /// </para>
 /// <para>
 /// The specified discount factors should be for the payment currency, however this is not validated.
 ///
 /// </para>
 /// </summary>
 /// <param name="payment">  the payment </param>
 /// <param name="discountFactors">  the discount factors to price against </param>
 /// <returns> the present value </returns>
 public virtual CurrencyAmount presentValue(Payment payment, DiscountFactors discountFactors)
 {
     if (discountFactors.ValuationDate.isAfter(payment.Date))
     {
         return(CurrencyAmount.zero(payment.Currency));
     }
     return(payment.Value.multipliedBy(discountFactors.discountFactor(payment.Date)));
 }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value by discounting the final cash flow (nominal + interest)
        /// and the initial payment (initial amount).
        /// <para>
        /// The present value of the product is the value on the valuation date.
        ///
        /// </para>
        /// </summary>
        /// <param name="deposit">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the present value of the product </returns>
        public virtual CurrencyAmount presentValue(ResolvedTermDeposit deposit, RatesProvider provider)
        {
            Currency currency = deposit.Currency;

            if (provider.ValuationDate.isAfter(deposit.EndDate))
            {
                return(CurrencyAmount.of(currency, 0.0d));
            }
            DiscountFactors discountFactors = provider.discountFactors(currency);
            double          dfStart         = discountFactors.discountFactor(deposit.StartDate);
            double          dfEnd           = discountFactors.discountFactor(deposit.EndDate);
            double          pvStart         = initialAmount(deposit, provider) * dfStart;
            double          pvEnd           = (deposit.Notional + deposit.Interest) * dfEnd;
            double          pv = pvEnd - pvStart;

            return(CurrencyAmount.of(currency, pv));
        }
예제 #13
0
        public virtual void test_of()
        {
            RepoCurveDiscountFactors test = RepoCurveDiscountFactors.of(DSC_FACTORS, GROUP);

            assertEquals(test.RepoGroup, GROUP);
            assertEquals(test.Currency, GBP);
            assertEquals(test.ValuationDate, DATE);
            assertEquals(test.discountFactor(DATE_AFTER), DSC_FACTORS.discountFactor(DATE_AFTER));
        }
        /// <summary>
        /// Calculates the present value sensitivity of the Ibor fixing product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of the present value to
        /// the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="deposit">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the point sensitivity of the present value </returns>
        public virtual PointSensitivities presentValueSensitivity(ResolvedIborFixingDeposit deposit, RatesProvider provider)
        {
            double          forwardRate     = this.forwardRate(deposit, provider);
            DiscountFactors discountFactors = provider.discountFactors(deposit.Currency);
            double          discountFactor  = discountFactors.discountFactor(deposit.EndDate);
            // sensitivity
            PointSensitivityBuilder sensiFwd = forwardRateSensitivity(deposit, provider).multipliedBy(-discountFactor * deposit.Notional * deposit.YearFraction);
            PointSensitivityBuilder sensiDsc = discountFactors.zeroRatePointSensitivity(deposit.EndDate).multipliedBy(deposit.Notional * deposit.YearFraction * (deposit.FixedRate - forwardRate));

            return(sensiFwd.combinedWith(sensiDsc).build());
        }
        public virtual PointSensitivityBuilder presentValueSensitivity(FxResetNotionalExchange @event, RatesProvider provider)
        {
            DiscountFactors         discountFactors = provider.discountFactors(@event.Currency);
            PointSensitivityBuilder sensiDsc        = discountFactors.zeroRatePointSensitivity(@event.PaymentDate);

            sensiDsc = sensiDsc.multipliedBy(forecastValue(@event, provider));
            PointSensitivityBuilder sensiFx = forecastValueSensitivity(@event, provider);

            sensiFx = sensiFx.multipliedBy(discountFactors.discountFactor(@event.PaymentDate));
            return(sensiDsc.combinedWith(sensiFx));
        }
        /// <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());
        }
        static DiscountingFraTradePricerTest()
        {
            DiscountFactors mockDf   = mock(typeof(DiscountFactors));
            IborIndexRates  mockIbor = mock(typeof(IborIndexRates));

            RATES_PROVIDER           = new SimpleRatesProvider(VAL_DATE, mockDf);
            RATES_PROVIDER.IborRates = mockIbor;
            IborIndexObservation obs  = ((IborRateComputation)RFRA.FloatingRate).Observation;
            IborRateSensitivity  sens = IborRateSensitivity.of(obs, 1d);

            when(mockIbor.ratePointSensitivity(obs)).thenReturn(sens);
            when(mockIbor.rate(obs)).thenReturn(FORWARD_RATE);
            when(mockDf.discountFactor(RFRA.PaymentDate)).thenReturn(DISCOUNT_FACTOR);
        }
예제 #18
0
        //-------------------------------------------------------------------------
        public virtual PointSensitivityBuilder presentValueSensitivity(RatePaymentPeriod period, RatesProvider provider)
        {
            Currency                ccy             = period.Currency;
            DiscountFactors         discountFactors = provider.discountFactors(ccy);
            LocalDate               paymentDate     = period.PaymentDate;
            double                  df = discountFactors.discountFactor(paymentDate);
            PointSensitivityBuilder forecastSensitivity = forecastValueSensitivity(period, provider);

            forecastSensitivity = forecastSensitivity.multipliedBy(df);
            double forecastValue = this.forecastValue(period, provider);
            PointSensitivityBuilder dscSensitivity = discountFactors.zeroRatePointSensitivity(paymentDate);

            dscSensitivity = dscSensitivity.multipliedBy(forecastValue);
            return(forecastSensitivity.combinedWith(dscSensitivity));
        }
        //-------------------------------------------------------------------------
        //  The derivatives are [0] spot, [1] strike, [2] rate, [3] cost-of-carry, [4] volatility, [5] timeToExpiry, [6] spot twice
        private ValueDerivatives priceDerivatives(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities)
        {
            validate(option, ratesProvider, volatilities);
            SimpleConstantContinuousBarrier barrier          = (SimpleConstantContinuousBarrier)option.Barrier;
            ResolvedFxVanillaOption         underlyingOption = option.UnderlyingOption;

            double[] derivatives = new double[7];
            if (volatilities.relativeTime(underlyingOption.Expiry) < 0d)
            {
                return(ValueDerivatives.of(0d, DoubleArray.ofUnsafe(derivatives)));
            }
            ResolvedFxSingle underlyingFx           = underlyingOption.Underlying;
            CurrencyPair     currencyPair           = underlyingFx.CurrencyPair;
            Currency         ccyBase                = currencyPair.Base;
            Currency         ccyCounter             = currencyPair.Counter;
            DiscountFactors  baseDiscountFactors    = ratesProvider.discountFactors(ccyBase);
            DiscountFactors  counterDiscountFactors = ratesProvider.discountFactors(ccyCounter);

            double           rateBase         = baseDiscountFactors.zeroRate(underlyingFx.PaymentDate);
            double           rateCounter      = counterDiscountFactors.zeroRate(underlyingFx.PaymentDate);
            double           costOfCarry      = rateCounter - rateBase;
            double           dfBase           = baseDiscountFactors.discountFactor(underlyingFx.PaymentDate);
            double           dfCounter        = counterDiscountFactors.discountFactor(underlyingFx.PaymentDate);
            double           todayFx          = ratesProvider.fxRate(currencyPair);
            double           strike           = underlyingOption.Strike;
            double           forward          = todayFx * dfBase / dfCounter;
            double           volatility       = volatilities.volatility(currencyPair, underlyingOption.Expiry, strike, forward);
            double           timeToExpiry     = volatilities.relativeTime(underlyingOption.Expiry);
            ValueDerivatives valueDerivatives = BARRIER_PRICER.priceAdjoint(todayFx, strike, timeToExpiry, costOfCarry, rateCounter, volatility, underlyingOption.PutCall.Call, barrier);

            if (!option.Rebate.Present)
            {
                return(valueDerivatives);
            }
            CurrencyAmount   rebate = option.Rebate.get();
            ValueDerivatives valueDerivativesRebate = rebate.Currency.Equals(ccyCounter) ? CASH_REBATE_PRICER.priceAdjoint(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType()) : ASSET_REBATE_PRICER.priceAdjoint(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType());
            double           rebateRate             = rebate.Amount / Math.Abs(underlyingFx.BaseCurrencyPayment.Amount);
            double           price = valueDerivatives.Value + rebateRate * valueDerivativesRebate.Value;

            derivatives[0] = valueDerivatives.getDerivative(0) + rebateRate * valueDerivativesRebate.getDerivative(0);
            derivatives[1] = valueDerivatives.getDerivative(1);
            for (int i = 2; i < 7; ++i)
            {
                derivatives[i] = valueDerivatives.getDerivative(i) + rebateRate * valueDerivativesRebate.getDerivative(i - 1);
            }
            return(ValueDerivatives.of(price, DoubleArray.ofUnsafe(derivatives)));
        }
예제 #20
0
        //-------------------------------------------------------------------------
        // 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);
        }
예제 #21
0
        //-------------------------------------------------------------------------
        // creates a simple provider
        private SimpleRatesProvider createProvider(FxResetNotionalExchange ne)
        {
            LocalDate paymentDate = ne.PaymentDate;
            double    paymentTime = ACT_360.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);
            FxIndexRates mockFxRates = mock(typeof(FxIndexRates));

            when(mockFxRates.rate(ne.Observation, ne.ReferenceCurrency)).thenReturn(FX_RATE);
            SimpleRatesProvider prov = new SimpleRatesProvider(VAL_DATE);

            prov.DiscountFactors = mockDf;
            prov.FxIndexRates    = mockFxRates;
            prov.DayCount        = ACT_360;
            return(prov);
        }
        //-------------------------------------------------------------------------
        public CurrencyParameterSensitivities parameterSensitivity(FxForwardSensitivity pointSensitivity)
        {
            // use the specified base currency to determine the desired currency pair
            // then derive sensitivity from discount factors based off desired currency pair, not that of the index
            CurrencyPair currencyPair        = pointSensitivity.CurrencyPair;
            Currency     refBaseCurrency     = pointSensitivity.ReferenceCurrency;
            Currency     refCounterCurrency  = pointSensitivity.ReferenceCounterCurrency;
            Currency     sensitivityCurrency = pointSensitivity.Currency;
            LocalDate    referenceDate       = pointSensitivity.ReferenceDate;

            bool            inverse = refBaseCurrency.Equals(currencyPair.Counter);
            DiscountFactors discountFactorsRefBase    = (inverse ? counterCurrencyDiscountFactors : baseCurrencyDiscountFactors);
            DiscountFactors discountFactorsRefCounter = (inverse ? baseCurrencyDiscountFactors : counterCurrencyDiscountFactors);
            double          dfCcyBaseAtMaturity       = discountFactorsRefBase.discountFactor(referenceDate);
            double          dfCcyCounterAtMaturityInv = 1d / discountFactorsRefCounter.discountFactor(referenceDate);

            double fxRate = fxRateProvider.fxRate(refBaseCurrency, refCounterCurrency);
            ZeroRateSensitivity dfCcyBaseAtMaturitySensitivity = discountFactorsRefBase.zeroRatePointSensitivity(referenceDate, sensitivityCurrency).multipliedBy(fxRate * dfCcyCounterAtMaturityInv * pointSensitivity.Sensitivity);

            ZeroRateSensitivity dfCcyCounterAtMaturitySensitivity = discountFactorsRefCounter.zeroRatePointSensitivity(referenceDate, sensitivityCurrency).multipliedBy(-fxRate * dfCcyBaseAtMaturity * dfCcyCounterAtMaturityInv * dfCcyCounterAtMaturityInv * pointSensitivity.Sensitivity);

            return(discountFactorsRefBase.parameterSensitivity(dfCcyBaseAtMaturitySensitivity).combinedWith(discountFactorsRefCounter.parameterSensitivity(dfCcyCounterAtMaturitySensitivity)));
        }
        /// <summary>
        /// Calculates the price of the FX barrier option product.
        /// <para>
        /// The price of the product is the value on the valuation date for one unit of the base currency
        /// and is expressed in the counter currency. The price does not take into account the long/short flag.
        /// See <seealso cref="#presentValue"/> for scaling and currency.
        /// </para>
        /// <para>
        /// The volatility used in this computation is the Black implied volatility at expiry time and strike.
        ///
        /// </para>
        /// </summary>
        /// <param name="option">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the price of the product </returns>
        public virtual double price(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities)
        {
            validate(option, ratesProvider, volatilities);
            SimpleConstantContinuousBarrier barrier          = (SimpleConstantContinuousBarrier)option.Barrier;
            ResolvedFxVanillaOption         underlyingOption = option.UnderlyingOption;

            if (volatilities.relativeTime(underlyingOption.Expiry) < 0d)
            {
                return(0d);
            }
            ResolvedFxSingle underlyingFx           = underlyingOption.Underlying;
            Currency         ccyBase                = underlyingFx.BaseCurrencyPayment.Currency;
            Currency         ccyCounter             = underlyingFx.CounterCurrencyPayment.Currency;
            CurrencyPair     currencyPair           = underlyingFx.CurrencyPair;
            DiscountFactors  baseDiscountFactors    = ratesProvider.discountFactors(ccyBase);
            DiscountFactors  counterDiscountFactors = ratesProvider.discountFactors(ccyCounter);

            double rateBase     = baseDiscountFactors.zeroRate(underlyingFx.PaymentDate);
            double rateCounter  = counterDiscountFactors.zeroRate(underlyingFx.PaymentDate);
            double costOfCarry  = rateCounter - rateBase;
            double dfBase       = baseDiscountFactors.discountFactor(underlyingFx.PaymentDate);
            double dfCounter    = counterDiscountFactors.discountFactor(underlyingFx.PaymentDate);
            double todayFx      = ratesProvider.fxRate(currencyPair);
            double strike       = underlyingOption.Strike;
            double forward      = todayFx * dfBase / dfCounter;
            double volatility   = volatilities.volatility(currencyPair, underlyingOption.Expiry, strike, forward);
            double timeToExpiry = volatilities.relativeTime(underlyingOption.Expiry);
            double price        = BARRIER_PRICER.price(todayFx, strike, timeToExpiry, costOfCarry, rateCounter, volatility, underlyingOption.PutCall.Call, barrier);

            if (option.Rebate.Present)
            {
                CurrencyAmount rebate      = option.Rebate.get();
                double         priceRebate = rebate.Currency.Equals(ccyCounter) ? CASH_REBATE_PRICER.price(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType()) : ASSET_REBATE_PRICER.price(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType());
                price += priceRebate * rebate.Amount / Math.Abs(underlyingFx.BaseCurrencyPayment.Amount);
            }
            return(price);
        }