internal LocalDate nextFixing; // Running variable through the different methods: next fixing date to be analyzed internal ObservationDetails(OvernightCompoundedRateComputation computation, OvernightIndexRates rates) { this.computation = computation; this.rates = rates; this.indexFixingDateSeries = rates.Fixings; this.dayCount = computation.Index.DayCount; // Details of the cutoff period this.firstFixing = computation.StartDate; this.lastFixingP1 = computation.EndDate; this.lastFixing = computation.FixingCalendar.previous(lastFixingP1); this.cutoffOffset = Math.Max(computation.RateCutOffDays, 1); this.accrualFactorCutoff = new double[cutoffOffset - 1]; LocalDate currentFixing = lastFixing; for (int i = 0; i < cutoffOffset - 1; i++) { currentFixing = computation.FixingCalendar.previous(currentFixing); LocalDate effectiveDate = computation.calculateEffectiveFromFixing(currentFixing); LocalDate maturityDate = computation.calculateMaturityFromEffective(effectiveDate); accrualFactorCutoff[i] = dayCount.yearFraction(effectiveDate, maturityDate); } this.lastFixingNonCutoff = currentFixing; LocalDate startUnderlyingPeriod = computation.calculateEffectiveFromFixing(firstFixing); LocalDate endUnderlyingPeriod = computation.calculateMaturityFromFixing(lastFixing); this.accrualFactorTotal = dayCount.yearFraction(startUnderlyingPeriod, endUnderlyingPeriod); }
// Composition - publication strictly before valuation date: try accessing fixing time-series internal double pastCompositionFactor() { double compositionFactor = 1.0d; LocalDate currentFixing = firstFixing; LocalDate currentPublication = computation.calculatePublicationFromFixing(currentFixing); while ((currentFixing.isBefore(lastFixingNonCutoff)) && rates.ValuationDate.isAfter(currentPublication)) { // publication before valuation LocalDate effectiveDate = computation.calculateEffectiveFromFixing(currentFixing); LocalDate maturityDate = computation.calculateMaturityFromEffective(effectiveDate); double accrualFactor = dayCount.yearFraction(effectiveDate, maturityDate); compositionFactor *= 1.0d + accrualFactor * checkedFixing(currentFixing, indexFixingDateSeries, computation.Index); currentFixing = computation.FixingCalendar.next(currentFixing); currentPublication = computation.calculatePublicationFromFixing(currentFixing); } if (currentFixing.Equals(lastFixingNonCutoff) && rates.ValuationDate.isAfter(currentPublication)) { // publication before valuation double rate = checkedFixing(currentFixing, indexFixingDateSeries, computation.Index); LocalDate effectiveDate = computation.calculateEffectiveFromFixing(currentFixing); LocalDate maturityDate = computation.calculateMaturityFromEffective(effectiveDate); double accrualFactor = dayCount.yearFraction(effectiveDate, maturityDate); compositionFactor *= 1.0d + accrualFactor * rate; for (int i = 0; i < cutoffOffset - 1; i++) { compositionFactor *= 1.0d + accrualFactorCutoff[i] * rate; } currentFixing = computation.FixingCalendar.next(currentFixing); } nextFixing = currentFixing; return(compositionFactor); }
//------------------------------------------------------------------------- // constructs an interpolated nodal curve internal InterpolatedNodalCurve createCurve(LocalDate date, IList <LoadedCurveNode> curveNodes) { // copy and sort IList <LoadedCurveNode> nodes = new List <LoadedCurveNode>(curveNodes); nodes.sort(System.Collections.IComparer.naturalOrder()); // build each node double[] xValues = new double[nodes.Count]; double[] yValues = new double[nodes.Count]; IList <ParameterMetadata> pointsMetadata = new List <ParameterMetadata>(nodes.Count); for (int i = 0; i < nodes.Count; i++) { LoadedCurveNode point = nodes[i]; double yearFraction = dayCount.yearFraction(date, point.Date); xValues[i] = yearFraction; yValues[i] = point.Value; ParameterMetadata pointMetadata = LabelDateParameterMetadata.of(point.Date, point.Label); pointsMetadata.Add(pointMetadata); } // create metadata CurveMetadata curveMetadata = DefaultCurveMetadata.builder().curveName(curveName).xValueType(xValueType).yValueType(yValueType).dayCount(dayCount).parameterMetadata(pointsMetadata).build(); return(InterpolatedNodalCurve.builder().metadata(curveMetadata).xValues(DoubleArray.copyOf(xValues)).yValues(DoubleArray.copyOf(yValues)).interpolator(interpolator).extrapolatorLeft(extrapolatorLeft).extrapolatorRight(extrapolatorRight).build()); }
// Compute the accrued interest on a given period by approximation private static double approximatedInterest(OvernightIndexObservation observation, LocalDate endDate, OvernightIndexRates rates) { DayCount dayCount = observation.Index.DayCount; double remainingFixingAccrualFactor = dayCount.yearFraction(observation.EffectiveDate, endDate); double forwardRate = rates.periodRate(observation, endDate); return(Math.Log(1.0 + forwardRate * remainingFixingAccrualFactor)); }
public virtual void test_yearFraction_badOrder() { DayCount test = DayCount.of("Bus/252 EUTA"); LocalDate date1 = date(2014, 12, 2); LocalDate date2 = date(2014, 12, 1); assertThrowsIllegalArg(() => test.yearFraction(date1, date2)); }
// Compute the accrued interest sensitivity on a given period by approximation private static PointSensitivityBuilder approximatedInterestSensitivity(OvernightIndexObservation observation, LocalDate endDate, OvernightIndexRates rates) { DayCount dayCount = observation.Index.DayCount; double remainingFixingAccrualFactor = dayCount.yearFraction(observation.EffectiveDate, endDate); double forwardRate = rates.periodRate(observation, endDate); PointSensitivityBuilder forwardRateSensitivity = rates.periodRatePointSensitivity(observation, endDate); double rateExp = 1.0 + forwardRate * remainingFixingAccrualFactor; forwardRateSensitivity = forwardRateSensitivity.multipliedBy(remainingFixingAccrualFactor / rateExp); return(forwardRateSensitivity); }
//------------------------------------------------------------------------- public virtual void test_yearFraction() { DayCount test = DayCount.of("Bus/252 EUTA"); LocalDate date1 = date(2014, 12, 1); LocalDate date2 = date(2014, 12, 1); for (int i = 0; i < 366; i++) { assertEquals(test.yearFraction(date1, date2), EUTA.resolve(REF_DATA).daysBetween(date1, date2) / 252d); date2 = date2.plusDays(1); } }
//------------------------------------------------------------------------- /// <summary> /// Computes the implied normal volatility from the present value of a swaption. /// <para> /// The guess volatility for the start of the root-finding process is 1%. /// /// </para> /// </summary> /// <param name="swaption"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="dayCount"> the day-count used to estimate the time between valuation date and swaption expiry </param> /// <param name="presentValue"> the present value of the swaption product </param> /// <returns> the implied volatility associated with the present value </returns> public virtual double impliedVolatilityFromPresentValue(ResolvedSwaption swaption, RatesProvider ratesProvider, DayCount dayCount, double presentValue) { double sign = swaption.LongShort.sign(); ArgChecker.isTrue(presentValue * sign > 0, "Present value sign must be in line with the option Long/Short flag "); validateSwaption(swaption); LocalDate valuationDate = ratesProvider.ValuationDate; LocalDate expiryDate = swaption.ExpiryDate; ArgChecker.isTrue(expiryDate.isAfter(valuationDate), "Expiry must be after valuation date to compute an implied volatility"); double expiry = dayCount.yearFraction(valuationDate, expiryDate); ResolvedSwap underlying = swaption.Underlying; ResolvedSwapLeg fixedLeg = this.fixedLeg(underlying); double forward = SwapPricer.parRate(underlying, ratesProvider); double numeraire = calculateNumeraire(swaption, fixedLeg, forward, ratesProvider); double strike = calculateStrike(fixedLeg); PutCall putCall = PutCall.ofPut(fixedLeg.PayReceive.Receive); return(NormalFormulaRepository.impliedVolatility(Math.Abs(presentValue), forward, strike, expiry, 0.01, numeraire, putCall)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the year fraction using the specified day count. /// <para> /// Additional information from the schedule is made available to the day count algorithm. /// /// </para> /// </summary> /// <param name="dayCount"> the day count convention </param> /// <param name="schedule"> the schedule that contains this period </param> /// <returns> the year fraction, calculated via the day count </returns> public double yearFraction(DayCount dayCount, Schedule schedule) { ArgChecker.notNull(dayCount, "dayCount"); ArgChecker.notNull(schedule, "schedule"); return(dayCount.yearFraction(startDate, endDate, schedule)); }