static CurveSensitivityUtilsJacobianTest()
        {
            Tenor[] tenors = new Tenor[] { Tenor.TENOR_1D, Tenor.TENOR_1M, Tenor.TENOR_3M, Tenor.TENOR_6M, Tenor.TENOR_1Y, Tenor.TENOR_2Y, Tenor.TENOR_3Y, Tenor.TENOR_4Y, Tenor.TENOR_5Y, Tenor.TENOR_7Y, Tenor.TENOR_10Y, Tenor.TENOR_15Y, Tenor.TENOR_20Y, Tenor.TENOR_30Y };
            IList <TenorParameterMetadata> metadataList = new List <TenorParameterMetadata>();

            for (int looptenor = 0; looptenor < tenors.Length; looptenor++)
            {
                metadataList.Add(TenorParameterMetadata.of(tenors[looptenor]));
            }
            DoubleArray            rate_eur         = DoubleArray.of(0.0160, 0.0165, 0.0155, 0.0155, 0.0155, 0.0150, 0.0150, 0.0160, 0.0165, 0.0155, 0.0155, 0.0155, 0.0150, 0.0140);
            InterpolatedNodalCurve curve_single_eur = InterpolatedNodalCurve.builder().metadata(DefaultCurveMetadata.builder().curveName(EUR_SINGLE_NAME).parameterMetadata(metadataList).dayCount(ACT_365F).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.ZERO_RATE).build()).xValues(TIME_EUR).yValues(rate_eur).extrapolatorLeft(CurveExtrapolators.FLAT).extrapolatorRight(CurveExtrapolators.FLAT).interpolator(CurveInterpolators.LINEAR).build();

            MULTICURVE_EUR_SINGLE_INPUT = ImmutableRatesProvider.builder(VALUATION_DATE).discountCurve(EUR, curve_single_eur).iborIndexCurve(EUR_EURIBOR_6M, curve_single_eur).build();
            LIST_CURVE_NAMES_1.Add(CurveParameterSize.of(EUR_SINGLE_NAME, TIME_EUR.size()));
        }
        //-------------------------------------------------------------------------
        internal static ScenarioMarketData marketData()
        {
            CurveParameterSize        issuerSize   = CurveParameterSize.of(ISSUER_CURVE_ID.CurveName, 3);
            CurveParameterSize        repoSize     = CurveParameterSize.of(REPO_CURVE_ID.CurveName, 2);
            JacobianCalibrationMatrix issuerMatrix = JacobianCalibrationMatrix.of(ImmutableList.of(issuerSize, repoSize), DoubleMatrix.copyOf(new double[][]
            {
                new double[] { 0.95, 0.03, 0.01, 0.006, 0.004 },
                new double[] { 0.03, 0.95, 0.01, 0.005, 0.005 },
                new double[] { 0.03, 0.01, 0.95, 0.002, 0.008 }
            }));
            JacobianCalibrationMatrix repoMatrix = JacobianCalibrationMatrix.of(ImmutableList.of(issuerSize, repoSize), DoubleMatrix.copyOf(new double[][]
            {
                new double[] { 0.003, 0.003, 0.004, 0.97, 0.02 },
                new double[] { 0.003, 0.006, 0.001, 0.05, 0.94 }
            }));
            CurveMetadata issuerMetadata = Curves.zeroRates(ISSUER_CURVE_ID.CurveName, ACT_360).withInfo(CurveInfoType.JACOBIAN, issuerMatrix);
            CurveMetadata repoMetadata   = Curves.zeroRates(REPO_CURVE_ID.CurveName, ACT_360).withInfo(CurveInfoType.JACOBIAN, repoMatrix);
            Curve         issuerCurve    = InterpolatedNodalCurve.of(issuerMetadata, DoubleArray.of(1.0, 5.0, 10.0), DoubleArray.of(0.02, 0.04, 0.01), CurveInterpolators.LINEAR);
            Curve         repoCurve      = InterpolatedNodalCurve.of(repoMetadata, DoubleArray.of(0.5, 3.0), DoubleArray.of(0.005, 0.008), CurveInterpolators.LINEAR);

            return(new TestMarketDataMap(VALUATION_DATE, ImmutableMap.of(REPO_CURVE_ID, repoCurve, ISSUER_CURVE_ID, issuerCurve), ImmutableMap.of()));
        }
        //-------------------------------------------------------------------------
        // shift the curve
        private NodalCurve withShift(InterpolatedNodalCurve curve, IList <ParameterMetadata> parameterMetadata, DoubleMatrix sensitivity, bool computeJacobian, double shift)
        {
            int nNode = curve.ParameterCount;

            if (shift < curve.XValues.get(0))
            {
                //offset less than t value of 1st knot, so no knots are not removed
                double        eta      = curve.YValues.get(0) * shift;
                DoubleArray   time     = DoubleArray.of(nNode, i => curve.XValues.get(i) - shift);
                DoubleArray   rate     = DoubleArray.of(nNode, i => (curve.YValues.get(i) * curve.XValues.get(i) - eta) / time.get(i));
                CurveMetadata metadata = curve.Metadata.withParameterMetadata(parameterMetadata);
                if (computeJacobian)
                {
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] transf = new double[nNode][nNode];
                    double[][] transf = RectangularArrays.ReturnRectangularDoubleArray(nNode, nNode);
                    for (int i = 0; i < nNode; ++i)
                    {
                        transf[i][0]  = -shift / time.get(i);
                        transf[i][i] += curve.XValues.get(i) / time.get(i);
                    }
                    DoubleMatrix jacobianMatrix        = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(transf), MATRIX_ALGEBRA.getInverse(sensitivity));
                    JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curve.Name, nNode)), jacobianMatrix);
                    return(curve.withValues(time, rate).withMetadata(metadata.withInfo(CurveInfoType.JACOBIAN, jacobian)));
                }
                return(curve.withValues(time, rate).withMetadata(metadata));
            }
            if (shift >= curve.XValues.get(nNode - 1))
            {
                //new base after last knot. The new 'curve' has a constant zero rate which we represent with a nominal knot at 1.0
                double time     = 1d;
                double interval = curve.XValues.get(nNode - 1) - curve.XValues.get(nNode - 2);
                double rate     = (curve.YValues.get(nNode - 1) * curve.XValues.get(nNode - 1) - curve.YValues.get(nNode - 2) * curve.XValues.get(nNode - 2)) / interval;
                if (computeJacobian)
                {
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] transf = new double[1][nNode];
                    double[][] transf = RectangularArrays.ReturnRectangularDoubleArray(1, nNode);
                    transf[0][nNode - 2] = -curve.XValues.get(nNode - 2) / interval;
                    transf[0][nNode - 1] = curve.XValues.get(nNode - 1) / interval;
                    DoubleMatrix jacobianMatrix        = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(transf), MATRIX_ALGEBRA.getInverse(sensitivity));
                    JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curve.Name, nNode)), jacobianMatrix);
                    return(ConstantNodalCurve.of(curve.Metadata.withInfo(CurveInfoType.JACOBIAN, jacobian), time, rate));
                }
                return(ConstantNodalCurve.of(curve.Metadata, time, rate));
            }
            //offset greater than (or equal to) t value of 1st knot, so at least one knot must be removed
            int index = Arrays.binarySearch(curve.XValues.toArray(), shift);

            if (index < 0)
            {
                index = -(index + 1);
            }
            else
            {
                index++;
            }
            double        interval = curve.XValues.get(index) - curve.XValues.get(index - 1);
            double        tt1      = curve.XValues.get(index - 1) * (curve.XValues.get(index) - shift);
            double        tt2      = curve.XValues.get(index) * (shift - curve.XValues.get(index - 1));
            double        eta      = (curve.YValues.get(index - 1) * tt1 + curve.YValues.get(index) * tt2) / interval;
            int           m        = nNode - index;
            CurveMetadata metadata = curve.Metadata.withParameterMetadata(parameterMetadata.subList(index, nNode));
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int indexFinal = index;
            int         indexFinal = index;
            DoubleArray time       = DoubleArray.of(m, i => curve.XValues.get(i + indexFinal) - shift);
            DoubleArray rate       = DoubleArray.of(m, i => (curve.YValues.get(i + indexFinal) * curve.XValues.get(i + indexFinal) - eta) / time.get(i));

            if (computeJacobian)
            {
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] transf = new double[m][nNode];
                double[][] transf = RectangularArrays.ReturnRectangularDoubleArray(m, nNode);
                for (int i = 0; i < m; ++i)
                {
                    transf[i][index - 1] -= tt1 / (time.get(i) * interval);
                    transf[i][index]     -= tt2 / (time.get(i) * interval);
                    transf[i][i + index] += curve.XValues.get(i + index) / time.get(i);
                }
                DoubleMatrix jacobianMatrix        = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(transf), MATRIX_ALGEBRA.getInverse(sensitivity));
                JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curve.Name, nNode)), jacobianMatrix);
                return(curve.withValues(time, rate).withMetadata(metadata.withInfo(CurveInfoType.JACOBIAN, jacobian)));
            }
            return(curve.withValues(time, rate).withMetadata(metadata));
        }
        //-------------------------------------------------------------------------
        /// <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)));
        }
예제 #5
0
        //-------------------------------------------------------------------------
        internal static ScenarioMarketData marketData(CurveName curveName)
        {
            DoubleMatrix jacobian = DoubleMatrix.ofUnsafe(new double[][]
            {
                new double[] { 0.985d, 0.01d, 0d },
                new double[] { 0.01d, 0.98d, 0.01d },
                new double[] { 0.005d, 0.01d, 0.99d }
            });
            JacobianCalibrationMatrix jcm = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(curveName, 3)), jacobian);
            DoubleArray       time        = DoubleArray.of(0.1, 0.25, 0.5d);
            DoubleArray       rate        = DoubleArray.of(0.01, 0.015, 0.008d);
            Curve             curve       = InterpolatedNodalCurve.of(Curves.zeroRates(curveName, ACT_360).withInfo(CurveInfoType.JACOBIAN, jcm), time, rate, NATURAL_SPLINE);
            TestMarketDataMap md          = new TestMarketDataMap(VAL_DATE, ImmutableMap.of(FORWARD_CURVE_ID, curve, QUOTE_KEY, MARKET_PRICE), ImmutableMap.of());

            return(md);
        }
        internal virtual LegalEntitySurvivalProbabilities calibrate(IList <CdsIsdaCreditCurveNode> curveNodes, CurveName name, MarketData marketData, ImmutableCreditRatesProvider ratesProvider, DayCount definitionDayCount, Currency definitionCurrency, bool computeJacobian, bool storeTrade, ReferenceData refData)
        {
//JAVA TO C# CONVERTER TODO TASK: Method reference arbitrary object instance method syntax is not converted by Java to C# Converter:
//JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter:
            IEnumerator <StandardId> legalEntities = curveNodes.Select(CdsIsdaCreditCurveNode::getLegalEntityId).collect(Collectors.toSet()).GetEnumerator();
//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            StandardId legalEntityId = legalEntities.next();

//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            ArgChecker.isFalse(legalEntities.hasNext(), "legal entity must be common to curve nodes");
//JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter:
            IEnumerator <Currency> currencies = curveNodes.Select(n => n.Template.Convention.Currency).collect(Collectors.toSet()).GetEnumerator();
//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            Currency currency = currencies.next();

//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            ArgChecker.isFalse(currencies.hasNext(), "currency must be common to curve nodes");
            ArgChecker.isTrue(definitionCurrency.Equals(currency), "curve definition currency must be the same as the currency of CDS");
//JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter:
            IEnumerator <CdsQuoteConvention> quoteConventions = curveNodes.Select(n => n.QuoteConvention).collect(Collectors.toSet()).GetEnumerator();
//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            CdsQuoteConvention quoteConvention = quoteConventions.next();

//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            ArgChecker.isFalse(quoteConventions.hasNext(), "quote convention must be common to curve nodes");
            LocalDate valuationDate = marketData.ValuationDate;

            ArgChecker.isTrue(valuationDate.Equals(marketData.ValuationDate), "ratesProvider and marketDate must be based on the same valuation date");
            CreditDiscountFactors discountFactors = ratesProvider.discountFactors(currency);

            ArgChecker.isTrue(definitionDayCount.Equals(discountFactors.DayCount), "credit curve and discount curve must be based on the same day count convention");
            RecoveryRates recoveryRates = ratesProvider.recoveryRates(legalEntityId);

            int nNodes = curveNodes.Count;

            double[] coupons = new double[nNodes];
            double[] pufs    = new double[nNodes];
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] diag = new double[nNodes][nNodes];
            double[][] diag = RectangularArrays.ReturnRectangularDoubleArray(nNodes, nNodes);
            ImmutableList.Builder <ResolvedCdsTrade> tradesBuilder = ImmutableList.builder();
            for (int i = 0; i < nNodes; i++)
            {
                CdsCalibrationTrade tradeCalibration = curveNodes[i].trade(1d, marketData, refData);
                ResolvedCdsTrade    trade            = tradeCalibration.UnderlyingTrade.resolve(refData);
                tradesBuilder.add(trade);
                double[] temp = getStandardQuoteForm(trade, tradeCalibration.Quote, valuationDate, discountFactors, recoveryRates, computeJacobian, refData);
                coupons[i] = temp[0];
                pufs[i]    = temp[1];
                diag[i][i] = temp[2];
            }
            ImmutableList <ResolvedCdsTrade> trades = tradesBuilder.build();
            NodalCurve nodalCurve = calibrate(trades, DoubleArray.ofUnsafe(coupons), DoubleArray.ofUnsafe(pufs), name, valuationDate, discountFactors, recoveryRates, refData);

            if (computeJacobian)
            {
                LegalEntitySurvivalProbabilities            creditCurve      = LegalEntitySurvivalProbabilities.of(legalEntityId, IsdaCreditDiscountFactors.of(currency, valuationDate, nodalCurve));
                ImmutableCreditRatesProvider                ratesProviderNew = ratesProvider.toBuilder().creditCurves(ImmutableMap.of(Pair.of(legalEntityId, currency), creditCurve)).build();
                System.Func <ResolvedCdsTrade, DoubleArray> sensiFunc        = quoteConvention.Equals(CdsQuoteConvention.PAR_SPREAD) ? getParSpreadSensitivityFunction(ratesProviderNew, name, currency, refData) : getPointsUpfrontSensitivityFunction(ratesProviderNew, name, currency, refData);
                DoubleMatrix sensi = DoubleMatrix.ofArrayObjects(nNodes, nNodes, i => sensiFunc(trades.get(i)));
                sensi = (DoubleMatrix)MATRIX_ALGEBRA.multiply(DoubleMatrix.ofUnsafe(diag), sensi);
                JacobianCalibrationMatrix jacobian = JacobianCalibrationMatrix.of(ImmutableList.of(CurveParameterSize.of(name, nNodes)), MATRIX_ALGEBRA.getInverse(sensi));
                nodalCurve = nodalCurve.withMetadata(nodalCurve.Metadata.withInfo(CurveInfoType.JACOBIAN, jacobian));
            }

            ImmutableList <ParameterMetadata> parameterMetadata;

            if (storeTrade)
            {
                parameterMetadata = IntStream.range(0, nNodes).mapToObj(n => ResolvedTradeParameterMetadata.of(trades.get(n), curveNodes[n].Label)).collect(Guavate.toImmutableList());
            }
            else
            {
                parameterMetadata = IntStream.range(0, nNodes).mapToObj(n => curveNodes[n].metadata(trades.get(n).Product.ProtectionEndDate)).collect(Guavate.toImmutableList());
            }
            nodalCurve = nodalCurve.withMetadata(nodalCurve.Metadata.withParameterMetadata(parameterMetadata));

            return(LegalEntitySurvivalProbabilities.of(legalEntityId, IsdaCreditDiscountFactors.of(currency, valuationDate, nodalCurve)));
        }