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)); }
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); }
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))); }