Пример #1
0
        public YieldTermStructure fitSwap(int curveIndex, BasicFixedLeg swap, YieldTermStructure curve, double swapRate)
        {
            int    nPayments = swap._nPayments;
            int    nNodes    = curve.nJumps_;
            double t1        = curveIndex == 0 ? 0.0 : curve.t[curveIndex - 1];
            double t2        = curveIndex == nNodes - 1 ? double.PositiveInfinity : curve.t[curveIndex + 1];

            double temp  = 0;
            double temp2 = 0;
            int    i1    = 0;
            int    i2    = nPayments;

            double[] paymentAmounts = new double[nPayments];
            for (int i = 0; i < nPayments; i++)
            {
                double t = swap.getPaymentTime(i);
                paymentAmounts[i] = swap.getPaymentAmounts(i, swapRate);
                if (t <= t1)
                {
                    double df = Math.Exp(-curve.getRT_(t));
                    temp  += paymentAmounts[i] * df;
                    temp2 -= paymentAmounts[i] * curve.getSingleNodeDiscountFactorSensitivity(t, curveIndex);
                    i1++;
                }
                else if (t >= t2)
                {
                    double df = Math.Exp(-curve.getRT_(t));
                    temp  += paymentAmounts[i] * df;
                    temp2 += paymentAmounts[i] * curve.getSingleNodeDiscountFactorSensitivity(t, curveIndex);
                    i2--;
                }
            }
            double cachedValues = temp;
            double cachedSense  = temp2;
            int    index1       = i1;
            int    index2       = i2;

            BracketRoot BRACKETER = new BracketRoot();
            NewtonRaphsonSingleRootFinder ROOTFINDER = new NewtonRaphsonSingleRootFinder();
            Func <double, double>         func       = x => apply_(x, curve, curveIndex, cachedValues, index1, index2,
                                                                   swap, paymentAmounts);

            Func <double, double> grad = x => apply_sen(x, curve, curveIndex, cachedSense, index1, index2,
                                                        swap, swapRate);

            double guess = curve.getZeroRateAtIndex(curveIndex);

            if (guess == 0.0 && func(guess) == 0.0)
            {
                return(curve);
            }
            double[] bracket = BRACKETER.getBracketedPoints(func, 0.8 * guess, 1.25 * guess, 0, double.PositiveInfinity);
            double   r       = ROOTFINDER.getRoot(func, grad, bracket[0], bracket[1]);

            return(curve.withRate(r, curveIndex));
        }
Пример #2
0
        public double apply_(double x, YieldTermStructure curve, int curveIndex, double cachedValues, int index1, int index2,
                             BasicFixedLeg swap, double[] paymentAmounts)
        {
            YieldTermStructure tempCurve = curve.withRate(x, curveIndex);
            double             sum       = 1.0 - cachedValues; // Floating leg at par

            for (int i = index1; i < index2; i++)
            {
                double t = swap.getPaymentTime(i);
                sum -= paymentAmounts[i] * Math.Exp(-tempCurve.getRT_(t));
            }
            return(sum);
        }
Пример #3
0
        public double apply_sen(double x, YieldTermStructure curve, int curveIndex, double cachedSense, int index1, int index2,
                                BasicFixedLeg swap, double swapRate)
        {
            YieldTermStructure tempCurve = curve.withRate(x, curveIndex);
            double             sum       = cachedSense;

            for (int i = index1; i < index2; i++)
            {
                double t = swap.getPaymentTime(i);
                // TODO have two looks ups for the same time - could have a specialist function in ISDACompliantCurve
                sum -= swap.getPaymentAmounts(i, swapRate) * tempCurve.getSingleNodeDiscountFactorSensitivity(t, curveIndex);
            }
            return(sum);
        }
        private DoubleArray sensitivitySwap(BasicFixedLeg swap, NodalCurve curve, double swapRate)
        {
            int    nPayments = swap.NumPayments;
            double annuity   = 0d;
            UnitParameterSensitivities sensi = UnitParameterSensitivities.empty();

            for (int i = 0; i < nPayments - 1; i++)
            {
                double t  = swap.getPaymentTime(i);
                double df = Math.Exp(-curve.yValue(t) * t);
                annuity += swap.getYearFraction(i) * df;
                sensi    = sensi.combinedWith(curve.yValueParameterSensitivity(t).multipliedBy(-df * t * swap.getYearFraction(i) * swapRate));
            }
            int    lastIndex = nPayments - 1;
            double t         = swap.getPaymentTime(lastIndex);
            double df        = Math.Exp(-curve.yValue(t) * t);

            annuity += swap.getYearFraction(lastIndex) * df;
            sensi    = sensi.combinedWith(curve.yValueParameterSensitivity(t).multipliedBy(-df * t * (1d + swap.getYearFraction(lastIndex) * swapRate)));
            sensi    = sensi.multipliedBy(-1d / annuity);
            ArgChecker.isTrue(sensi.size() == 1);
            return(sensi.Sensitivities.get(0).Sensitivity);
        }
        //-------------------------------------------------------------------------
        private InterpolatedNodalCurve fitSwap(int curveIndex, BasicFixedLeg swap, InterpolatedNodalCurve curve, double swapRate)
        {
            int    nPayments = swap.NumPayments;
            int    nNodes    = curve.ParameterCount;
            double t1        = curveIndex == 0 ? 0.0 : curve.XValues.get(curveIndex - 1);
            double t2        = curveIndex == nNodes - 1 ? double.PositiveInfinity : curve.XValues.get(curveIndex + 1);
            double temp      = 0;
            double temp2     = 0;
            int    i1        = 0;
            int    i2        = nPayments;

            double[] paymentAmounts = new double[nPayments];
            for (int i = 0; i < nPayments; i++)
            {
                double t = swap.getPaymentTime(i);
                paymentAmounts[i] = swap.getPaymentAmounts(i, swapRate);
                if (t <= t1)
                {
                    double df = Math.Exp(-curve.yValue(t) * t);
                    temp  += paymentAmounts[i] * df;
                    temp2 += paymentAmounts[i] * t *df *curve.yValueParameterSensitivity(t).Sensitivity.get(curveIndex);

                    i1++;
                }
                else if (t >= t2)
                {
                    double df = Math.Exp(-curve.yValue(t) * t);
                    temp  += paymentAmounts[i] * df;
                    temp2 -= paymentAmounts[i] * t *df *curve.yValueParameterSensitivity(t).Sensitivity.get(curveIndex);

                    i2--;
                }
            }
            double cachedValues = temp;
            double cachedSense  = temp2;
            int    index1       = i1;
            int    index2       = i2;

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: java.util.function.Function<double, double> func = new java.util.function.Function<double, double>()
            System.Func <double, double> func = (double?x) =>
            {
                InterpolatedNodalCurve tempCurve = curve.withParameter(curveIndex, x);
                double sum = 1.0 - cachedValues; // Floating leg at par
                for (int i = index1; i < index2; i++)
                {
                    double t = swap.getPaymentTime(i);
                    sum -= paymentAmounts[i] * Math.Exp(-tempCurve.yValue(t) * t);
                }
                return(sum);
            };

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: java.util.function.Function<double, double> grad = new java.util.function.Function<double, double>()
            System.Func <double, double> grad = (double?x) =>
            {
                InterpolatedNodalCurve tempCurve = curve.withParameter(curveIndex, x);
                double sum = cachedSense;
                for (int i = index1; i < index2; i++)
                {
                    double t = swap.getPaymentTime(i);
                    sum += swap.getPaymentAmounts(i, swapRate) * t * Math.Exp(-tempCurve.yValue(t) * t) * tempCurve.yValueParameterSensitivity(t).Sensitivity.get(curveIndex);
                }
                return(sum);
            };

            double guess = curve.getParameter(curveIndex);

            if (guess == 0.0 && func(guess) == 0.0)
            {
                return(curve);
            }
            double[] bracket = guess > 0d ? BRACKETER.getBracketedPoints(func, 0.8 * guess, 1.25 * guess, double.NegativeInfinity, double.PositiveInfinity) : BRACKETER.getBracketedPoints(func, 1.25 * guess, 0.8 * guess, double.NegativeInfinity, double.PositiveInfinity);
            double   r       = rootFinder.getRoot(func, grad, bracket[0], bracket[1]).Value;

            return(curve.withParameter(curveIndex, r));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calibrates the ISDA compliant discount curve to the market data.
        /// <para>
        /// This creates the single discount curve for a specified currency.
        /// The curve nodes in {@code IsdaCreditCurveDefinition} should be term deposit or fixed-for-Ibor swap,
        /// and the number of nodes should be greater than 1.
        ///
        /// </para>
        /// </summary>
        /// <param name="curveDefinition">  the curve definition </param>
        /// <param name="marketData">  the market data </param>
        /// <param name="refData">  the reference data </param>
        /// <returns> the ISDA compliant discount curve </returns>
        public IsdaCreditDiscountFactors calibrate(IsdaCreditCurveDefinition curveDefinition, MarketData marketData, ReferenceData refData)
        {
//JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET:
//ORIGINAL LINE: java.util.List<? extends com.opengamma.strata.market.curve.IsdaCreditCurveNode> curveNodes = curveDefinition.getCurveNodes();
            IList <IsdaCreditCurveNode> curveNodes = curveDefinition.CurveNodes;
            int nNodes = curveNodes.Count;

            ArgChecker.isTrue(nNodes > 1, "the number of curve nodes must be greater than 1");
            LocalDate curveSnapDate      = marketData.ValuationDate;
            LocalDate curveValuationDate = curveDefinition.CurveValuationDate;
            DayCount  curveDayCount      = curveDefinition.DayCount;

            BasicFixedLeg[] swapLeg = new BasicFixedLeg[nNodes];
            double[]        termDepositYearFraction = new double[nNodes];
            double[]        curveNodeTime           = new double[nNodes];
            double[]        rates = new double[nNodes];
            ImmutableList.Builder <ParameterMetadata> paramMetadata = ImmutableList.builder();
            int       nTermDeposit  = 0;
            LocalDate curveSpotDate = null;

            for (int i = 0; i < nNodes; i++)
            {
                LocalDate           cvDateTmp;
                IsdaCreditCurveNode node = curveNodes[i];
                rates[i] = marketData.getValue(node.ObservableId);
                LocalDate adjMatDate = node.date(curveSnapDate, refData);
                paramMetadata.add(node.metadata(adjMatDate));
                if (node is DepositIsdaCreditCurveNode)
                {
                    DepositIsdaCreditCurveNode termDeposit = (DepositIsdaCreditCurveNode)node;
                    cvDateTmp                  = termDeposit.SpotDateOffset.adjust(curveSnapDate, refData);
                    curveNodeTime[i]           = curveDayCount.relativeYearFraction(cvDateTmp, adjMatDate);
                    termDepositYearFraction[i] = termDeposit.DayCount.relativeYearFraction(cvDateTmp, adjMatDate);
                    ArgChecker.isTrue(nTermDeposit == i, "TermDepositCurveNode should not be after FixedIborSwapCurveNode");
                    ++nTermDeposit;
                }
                else if (node is SwapIsdaCreditCurveNode)
                {
                    SwapIsdaCreditCurveNode swap = (SwapIsdaCreditCurveNode)node;
                    cvDateTmp        = swap.SpotDateOffset.adjust(curveSnapDate, refData);
                    curveNodeTime[i] = curveDayCount.relativeYearFraction(cvDateTmp, adjMatDate);
                    BusinessDayAdjustment busAdj = swap.BusinessDayAdjustment;
                    swapLeg[i] = new BasicFixedLeg(this, cvDateTmp, cvDateTmp.plus(swap.Tenor), swap.PaymentFrequency.Period, swap.DayCount, curveDayCount, busAdj, refData);
                }
                else
                {
                    throw new System.ArgumentException("unsupported cuve node type");
                }
                if (i > 0)
                {
                    ArgChecker.isTrue(curveNodeTime[i] - curveNodeTime[i - 1] > 0, "curve nodes should be ascending in terms of tenor");
                    ArgChecker.isTrue(cvDateTmp.Equals(curveSpotDate), "spot lag should be common for all of the curve nodes");
                }
                else
                {
                    ArgChecker.isTrue(curveNodeTime[i] >= 0d, "the first node should be after curve spot date");
                    curveSpotDate = cvDateTmp;
                }
            }
            ImmutableList <ParameterMetadata> parameterMetadata = paramMetadata.build();

            double[] ratesMod = Arrays.copyOf(rates, nNodes);
            for (int i = 0; i < nTermDeposit; ++i)
            {
                double dfInv = 1d + ratesMod[i] * termDepositYearFraction[i];
                ratesMod[i] = Math.Log(dfInv) / curveNodeTime[i];
            }
            InterpolatedNodalCurve curve = curveDefinition.curve(DoubleArray.ofUnsafe(curveNodeTime), DoubleArray.ofUnsafe(ratesMod));

            for (int i = nTermDeposit; i < nNodes; ++i)
            {
                curve = fitSwap(i, swapLeg[i], curve, rates[i]);
            }

            Currency     currency = curveDefinition.Currency;
            DoubleMatrix sensi    = quoteValueSensitivity(nTermDeposit, termDepositYearFraction, swapLeg, ratesMod, curve, curveDefinition.ComputeJacobian);

            if (curveValuationDate.isEqual(curveSpotDate))
            {
                if (curveDefinition.ComputeJacobian)
                {
                    JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curveDefinition.Name, nNodes)), MATRIX_ALGEBRA.getInverse(sensi));
                    NodalCurve curveWithParamMetadata  = curve.withMetadata(curve.Metadata.withInfo(CurveInfoType.JACOBIAN, jacobian).withParameterMetadata(parameterMetadata));
                    return(IsdaCreditDiscountFactors.of(currency, curveValuationDate, curveWithParamMetadata));
                }
                NodalCurve curveWithParamMetadata = curve.withMetadata(curve.Metadata.withParameterMetadata(parameterMetadata));
                return(IsdaCreditDiscountFactors.of(currency, curveValuationDate, curveWithParamMetadata));
            }
            double offset = curveDayCount.relativeYearFraction(curveSpotDate, curveValuationDate);

            return(IsdaCreditDiscountFactors.of(currency, curveValuationDate, withShift(curve, parameterMetadata, sensi, curveDefinition.ComputeJacobian, offset)));
        }