/** * Gets the periodic frequency of accrual. * <p> * Interest will be accrued over periods at the specified periodic frequency, such as every 3 months. * <p> * This will default to the tenor of the index if not specified. * * @return the accrual frequency, not null */ public Frequency getAccrualFrequency() { return accrualFrequency != null ? accrualFrequency : Frequency.of(index.getTenor().getPeriod()); }
@DataProvider(name = "based") public static Object[][] data_based() { return new Object[][] { {Tenor.ofDays(1), false, false}, {Tenor.ofDays(2), false, false}, {Tenor.ofDays(6), false, false}, {Tenor.ofDays(7), true, false}, {Tenor.ofWeeks(1), true, false}, {Tenor.ofWeeks(3), true, false}, {Tenor.ofMonths(1), false, true}, {Tenor.ofMonths(3), false, true}, {Tenor.ofYears(1), false, true}, {Tenor.ofYears(3), false, true}, {Tenor.of(Period.of(1, 2, 3)), false, false}, }; }
@Override public IborIndex toIborIndex(Tenor tenor) { if (!type.isIbor()) { throw new IllegalStateException("Incorrect index type, expected Ibor: " + externalName); } return IborIndex.of(indexName + tenor.normalized().toString()); }
/** * Parses a formatted string representing the tenor. * <p> * The format can either be based on ISO-8601, such as 'P3M' * or without the 'P' prefix e.g. '2W'. * * @param toParse the string representing the tenor * @return the tenor * @throws IllegalArgumentException if the tenor cannot be parsed */ @FromString public static Tenor parse(String toParse) { String prefixed = toParse.startsWith("P") ? toParse : "P" + toParse; try { return Tenor.of(Period.parse(prefixed)); } catch (DateTimeParseException ex) { throw new IllegalArgumentException(ex); } }
@ImmutablePreBuild private static void preBuild(Builder builder) { if (builder.label == null && builder.tenor != null) { builder.label = builder.tenor.toString(); } }
@Test(dataProvider = "normalized") public void test_normalized(Period period, Period normalized) { assertEquals(Tenor.of(period).normalized().getPeriod(), normalized); }
/** * Converts a date range to a period string. * * @param start the start date * @param end the end date * @return the string form */ public static String datePeriod(LocalDate start, LocalDate end) { int months = Math.toIntExact(MONTHS.between(start, end.plusDays(3))); if (months > 0) { return Tenor.of(Period.ofMonths((int) months)).normalized().toString(); } else { return Tenor.of(Period.ofDays((int) start.until(end, ChronoUnit.DAYS))).toString(); } }
/** * Checks the parsed sensitivity tenor, potentially altering the value. * <p> * The input is the tenor exactly as parsed. * The default implementation normalizes it and ensures that it does not contain a combination * of years/months and days. * * @param tenor the tenor to check and potentially alter * @return the potentially adjusted tenor */ public default Tenor checkSensitivityTenor(Tenor tenor) { Tenor resultTenor = tenor.normalized(); if (resultTenor.getPeriod().toTotalMonths() > 0 && resultTenor.getPeriod().getDays() > 0) { throw new IllegalArgumentException( "Invalid tenor, cannot mix years/months and days: " + tenor); } return resultTenor; }
@ImmutablePreBuild private static void preBuild(Builder builder) { if (builder.index != null) { if (builder.accrualFactor == 0d && builder.index.getTenor().isMonthBased()) { builder.accrualFactor(builder.index.getTenor().getPeriod().toTotalMonths() / 12d); } if (builder.currency == null) { builder.currency = builder.index.getCurrency(); } } }
private static Period parseInflationLag(Optional<String> strOpt, Currency currency) { if (!strOpt.isPresent()) { if (Currency.GBP.equals(currency)) { return Period.ofMonths(2); } return Period.ofMonths(3); } String str = strOpt.get(); Integer months = Ints.tryParse(str); if (months != null) { return Period.ofMonths(months); } return Tenor.parse(str).getPeriod(); }
public void test_initialGuess() { OvernightIborSwapCurveNode node = OvernightIborSwapCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); LocalDate valuationDate = LocalDate.of(2015, 1, 22); double rate = 0.035; MarketData marketData = ImmutableMarketData.builder(valuationDate).addValue(QUOTE_ID, rate).build(); assertEquals(node.initialGuess(marketData, ValueType.ZERO_RATE), rate); assertEquals(node.initialGuess(marketData, ValueType.FORWARD_RATE), rate); double df = Math.exp(-TENOR_10Y.get(ChronoUnit.YEARS) * rate); assertEquals(node.initialGuess(marketData, ValueType.DISCOUNT_FACTOR), df, TOLERANCE_DF); assertEquals(node.initialGuess(marketData, ValueType.PRICE_INDEX), 0d); }
/** * Converts an FpML tenor string to a {@code Tenor}. * * @param multiplier the multiplier * @param unit the unit * @return the tenor * @throws IllegalArgumentException if the tenor is not known */ public Tenor convertIndexTenor(String multiplier, String unit) { String periodStr = multiplier + unit; Tenor tenor = TENOR_MAP.get(periodStr); return tenor != null ? tenor : Tenor.parse(periodStr); }
public void test_equals_hashCode() { Tenor a1 = TENOR_3D; Tenor a2 = Tenor.ofDays(3); Tenor b = TENOR_4M; assertEquals(a1.equals(a1), true); assertEquals(a1.equals(b), false); assertEquals(a1.equals(a2), true); assertEquals(a2.equals(a1), true); assertEquals(a2.equals(a2), true); assertEquals(a2.equals(b), false); assertEquals(b.equals(a1), false); assertEquals(b.equals(a2), false); assertEquals(b.equals(b), true); assertEquals(a1.hashCode(), a2.hashCode()); }
/** * Obtains an instance from a {@code Period}. * <p> * The period normally consists of either days and weeks, or months and years. * It must also be positive and non-zero. * <p> * If the number of days is an exact multiple of 7 it will be converted to weeks. * Months are not normalized into years. * * @param period the period to convert to a tenor * @return the tenor * @throws IllegalArgumentException if the period is negative or zero */ public static Tenor of(Period period) { int days = period.getDays(); long months = period.toTotalMonths(); if (months == 0 && days != 0) { return ofDays(days); } return new Tenor(period, period.toString().substring(1)); }