public virtual void test_parSpread() { SimpleRatesProvider prov = provider(VAL_DATE, DF_START, DF_END); double parSpread = PRICER.parSpread(RTERM_DEPOSIT, prov); TermDeposit depositPar = TermDeposit.builder().buySell(BuySell.BUY).startDate(START_DATE).endDate(END_DATE).businessDayAdjustment(BD_ADJ).dayCount(ACT_360).notional(NOTIONAL).currency(EUR).rate(RATE + parSpread).build(); double pvPar = PRICER.presentValue(depositPar.resolve(REF_DATA), prov).Amount; assertEquals(pvPar, 0.0, NOTIONAL * TOLERANCE); }
//------------------------------------------------------------------------- public Trade parseTrade(FpmlDocument document, XmlElement tradeEl) { // supported elements: // 'payerPartyReference' // 'receiverPartyReference' // 'startDate' // 'maturityDate' // 'principal' // 'fixedRate' // 'dayCountFraction' // ignored elements: // 'payerAccountReference?' // 'receiverAccountReference?' // 'interest?' // rejected elements: // 'features?' // 'payment*' TradeInfoBuilder tradeInfoBuilder = document.parseTradeInfo(tradeEl); XmlElement termEl = tradeEl.getChild("termDeposit"); document.validateNotPresent(termEl, "features"); document.validateNotPresent(termEl, "payment"); TermDeposit.Builder termBuilder = TermDeposit.builder(); // pay/receive and counterparty PayReceive payReceive = document.parsePayerReceiver(termEl, tradeInfoBuilder); termBuilder.buySell(BuySell.ofBuy(payReceive.Pay)); // start date termBuilder.startDate(document.parseDate(termEl.getChild("startDate"))); // maturity date termBuilder.endDate(document.parseDate(termEl.getChild("maturityDate"))); // principal CurrencyAmount principal = document.parseCurrencyAmount(termEl.getChild("principal")); termBuilder.currency(principal.Currency); termBuilder.notional(principal.Amount); // fixed rate termBuilder.rate(document.parseDecimal(termEl.getChild("fixedRate"))); // day count termBuilder.dayCount(document.parseDayCountFraction(termEl.getChild("dayCountFraction"))); return(TermDepositTrade.builder().info(tradeInfoBuilder.build()).product(termBuilder.build()).build()); }
// parse the row to a trade private static TermDepositTrade parseRow(CsvRow row, TradeInfo info, TradeCsvInfoResolver resolver) { BuySell buySell = LoaderUtils.parseBuySell(row.getValue(BUY_SELL_FIELD)); double notional = LoaderUtils.parseDouble(row.getValue(NOTIONAL_FIELD)); double fixedRate = LoaderUtils.parseDoublePercent(row.getValue(FIXED_RATE_FIELD)); Optional <TermDepositConvention> conventionOpt = row.findValue(CONVENTION_FIELD).map(s => TermDepositConvention.of(s)); Optional <Period> tenorOpt = row.findValue(TENOR_FIELD).map(s => LoaderUtils.parseTenor(s).Period); Optional <LocalDate> startDateOpt = row.findValue(START_DATE_FIELD).map(s => LoaderUtils.parseDate(s)); Optional <LocalDate> endDateOpt = row.findValue(END_DATE_FIELD).map(s => LoaderUtils.parseDate(s)); Optional <Currency> currencyOpt = row.findValue(CURRENCY_FIELD).map(s => Currency.parse(s)); Optional <DayCount> dayCountOpt = row.findValue(DAY_COUNT_FIELD).map(s => LoaderUtils.parseDayCount(s)); BusinessDayConvention dateCnv = row.findValue(DATE_ADJ_CNV_FIELD).map(s => LoaderUtils.parseBusinessDayConvention(s)).orElse(BusinessDayConventions.MODIFIED_FOLLOWING); Optional <HolidayCalendarId> dateCalOpt = row.findValue(DATE_ADJ_CAL_FIELD).map(s => HolidayCalendarId.of(s)); // use convention if available if (conventionOpt.Present) { if (currencyOpt.Present || dayCountOpt.Present) { throw new System.ArgumentException("TermDeposit trade had invalid combination of fields. When '" + CONVENTION_FIELD + "' is present these fields must not be present: " + ImmutableList.of(CURRENCY_FIELD, DAY_COUNT_FIELD)); } TermDepositConvention convention = conventionOpt.get(); // explicit dates take precedence over relative ones if (startDateOpt.Present && endDateOpt.Present) { if (tenorOpt.Present) { throw new System.ArgumentException("TermDeposit trade had invalid combination of fields. When these fields are found " + ImmutableList.of(CONVENTION_FIELD, START_DATE_FIELD, END_DATE_FIELD) + " then these fields must not be present " + ImmutableList.of(TENOR_FIELD)); } LocalDate startDate = startDateOpt.get(); LocalDate endDate = endDateOpt.get(); TermDepositTrade trade = convention.toTrade(info, startDate, endDate, buySell, notional, fixedRate); return(adjustTrade(trade, dateCnv, dateCalOpt)); } // relative dates if (tenorOpt.Present && info.TradeDate.Present) { if (startDateOpt.Present || endDateOpt.Present) { throw new System.ArgumentException("TermDeposit trade had invalid combination of fields. When these fields are found " + ImmutableList.of(CONVENTION_FIELD, TENOR_FIELD, TRADE_DATE_FIELD) + " then these fields must not be present " + ImmutableList.of(START_DATE_FIELD, END_DATE_FIELD)); } LocalDate tradeDate = info.TradeDate.get(); Period periodToStart = tenorOpt.get(); TermDepositTrade trade = convention.createTrade(tradeDate, periodToStart, buySell, notional, fixedRate, resolver.ReferenceData); trade = trade.toBuilder().info(info).build(); return(adjustTrade(trade, dateCnv, dateCalOpt)); } } else if (startDateOpt.Present && endDateOpt.Present && currencyOpt.Present && dayCountOpt.Present) { LocalDate startDate = startDateOpt.get(); LocalDate endDate = endDateOpt.get(); Currency currency = currencyOpt.get(); DayCount dayCount = dayCountOpt.get(); TermDeposit.Builder builder = TermDeposit.builder().buySell(buySell).currency(currency).notional(notional).startDate(startDate).endDate(endDate).dayCount(dayCount).rate(fixedRate); TermDepositTrade trade = TermDepositTrade.of(info, builder.build()); return(adjustTrade(trade, dateCnv, dateCalOpt)); } // no match throw new System.ArgumentException("TermDeposit trade had invalid combination of fields. These fields are mandatory:" + ImmutableList.of(BUY_SELL_FIELD, NOTIONAL_FIELD, FIXED_RATE_FIELD) + " and one of these combinations is mandatory: " + ImmutableList.of(CONVENTION_FIELD, TRADE_DATE_FIELD, TENOR_FIELD) + " or " + ImmutableList.of(CONVENTION_FIELD, START_DATE_FIELD, END_DATE_FIELD) + " or " + ImmutableList.of(START_DATE_FIELD, END_DATE_FIELD, CURRENCY_FIELD, DAY_COUNT_FIELD)); }