private CashSwaptionSettlementMethod parseCashSettlementMethod(XmlElement cashSettlementEl) { if (cashSettlementEl.findChild("cashPriceAlternateMethod").isPresent()) { return CashSwaptionSettlementMethod.CASH_PRICE; } else if (cashSettlementEl.findChild("parYieldCurveUnadjustedMethod").isPresent() || cashSettlementEl.findChild("parYieldCurveAadjustedMethod").isPresent()) { return CashSwaptionSettlementMethod.PAR_YIELD; } else if (cashSettlementEl.findChild("zeroCouponYieldAdjustedMethod").isPresent()) { return CashSwaptionSettlementMethod.ZERO_COUPON_YIELD; } else { throw new FpmlParseException("Invalid swaption cash settlement method: " + cashSettlementEl); } }
/** * Validates that a specific element is not present. * * @param baseEl the FpML element to parse * @param elementName the element name * @throws FpmlParseException if the element is found */ public void validateNotPresent(XmlElement baseEl, String elementName) { if (baseEl.findChild(elementName).isPresent()) { throw new FpmlParseException("Unsupported element: '" + elementName + "'"); } }
/** * Gets the child element with the specified name, throwing an exception if not found or more than one. * <p> * This returns the child element with the specified name. * An exception is thrown if there is more than one matching child or the child does not exist. * * @param childName the name to match * @return the child matching the name * @throws IllegalArgumentException if there is more than one match or no matches */ public XmlElement getChild(String childName) { return findChild(childName) .orElseThrow(() -> new IllegalArgumentException(Messages.format( "Unknown element '{}' in element '{}'", childName, name))); }
private AdjustableDate parseExpiryDate(XmlElement europeanExerciseEl, FpmlDocument document) { XmlElement expirationDate = europeanExerciseEl.getChild("expirationDate"); return expirationDate.findChild("adjustableDate") .map(el -> document.parseAdjustableDate(el)).get(); }
private Trade parseTrade(FpmlDocument document, XmlElement tradeEl) { // find which trade type it is by comparing children to known parsers for (Entry<String, FpmlParserPlugin> entry : tradeParsers.entrySet()) { Optional<XmlElement> productOptEl = tradeEl.findChild(entry.getKey()); if (productOptEl.isPresent()) { return entry.getValue().parseTrade(document, tradeEl); } } // failed to find a known trade type ImmutableSet<String> childNames = tradeEl.getChildren().stream().map(XmlElement::getName).collect(toImmutableSet()); throw new FpmlParseException("Unknown product type: " + childNames); }
private FixedRateStubCalculation parseStubCalculationForFixed(XmlElement baseEl, FpmlDocument document) { Optional<XmlElement> rateOptEl = baseEl.findChild("stubRate"); if (rateOptEl.isPresent()) { return FixedRateStubCalculation.ofFixedRate(document.parseDecimal(rateOptEl.get())); } Optional<XmlElement> amountOptEl = baseEl.findChild("stubAmount"); if (amountOptEl.isPresent()) { return FixedRateStubCalculation.ofKnownAmount(document.parseCurrencyAmount(amountOptEl.get())); } throw new FpmlParseException("Invalid stub, fixed rate leg cannot have a floating rate stub"); }
private RateCalculation parseSwapCalculation( XmlElement legEl, XmlElement calcEl, PeriodicSchedule accrualSchedule, FpmlDocument document) { // supported elements: // 'calculationPeriodAmount/calculation/fixedRateSchedule' // 'calculationPeriodAmount/calculation/floatingRateCalculation' // 'calculationPeriodAmount/calculation/inflationRateCalculation' Optional<XmlElement> fixedOptEl = calcEl.findChild("fixedRateSchedule"); Optional<XmlElement> floatingOptEl = calcEl.findChild("floatingRateCalculation"); Optional<XmlElement> inflationOptEl = calcEl.findChild("inflationRateCalculation"); if (fixedOptEl.isPresent()) { return parseFixed(legEl, calcEl, fixedOptEl.get(), document); } else if (floatingOptEl.isPresent()) { return parseFloat(legEl, calcEl, floatingOptEl.get(), accrualSchedule, document); } else if (inflationOptEl.isPresent()) { return parseInflation(legEl, calcEl, inflationOptEl.get(), accrualSchedule, document); } else { throw new FpmlParseException( "Invalid 'calculation' type, not fixedRateSchedule, floatingRateCalculation or inflationRateCalculation"); } }
/** * Converts an FpML 'BusinessDayAdjustments' to a {@code BusinessDayAdjustment}. * * @param baseEl the FpML business centers or reference element to parse * @return the business day adjustment * @throws RuntimeException if unable to parse */ public BusinessDayAdjustment parseBusinessDayAdjustments(XmlElement baseEl) { // FpML content: ('businessDayConvention', 'BusinessCentersOrReference.model?') BusinessDayConvention bdc = convertBusinessDayConvention( baseEl.getChild("businessDayConvention").getContent()); Optional<XmlElement> centersEl = baseEl.findChild("businessCenters"); Optional<XmlElement> centersRefEl = baseEl.findChild("businessCentersReference"); HolidayCalendarId calendar = (centersEl.isPresent() || centersRefEl.isPresent() ? parseBusinessCenters(baseEl) : HolidayCalendarIds.NO_HOLIDAYS); return BusinessDayAdjustment.of(bdc, calendar); }
private ListMultimap<String, StandardId> parseAllTradeIds(XmlElement tradeHeaderEl) { // look through each partyTradeIdentifier ListMultimap<String, StandardId> allIds = ArrayListMultimap.create(); List<XmlElement> partyTradeIdentifierEls = tradeHeaderEl.getChildren("partyTradeIdentifier"); for (XmlElement partyTradeIdentifierEl : partyTradeIdentifierEls) { Optional<XmlElement> partyRefOptEl = partyTradeIdentifierEl.findChild("partyReference"); if (partyRefOptEl.isPresent() && partyRefOptEl.get().findAttribute(HREF).isPresent()) { String partyHref = partyRefOptEl.get().findAttribute(HREF).get(); // try to find a tradeId, either in versionedTradeId or as a direct child Optional<XmlElement> vtradeIdOptEl = partyTradeIdentifierEl.findChild("versionedTradeId"); Optional<XmlElement> tradeIdOptEl = vtradeIdOptEl .map(vt -> Optional.of(vt.getChild("tradeId"))) .orElse(partyTradeIdentifierEl.findChild("tradeId")); if (tradeIdOptEl.isPresent() && tradeIdOptEl.get().findAttribute("tradeIdScheme").isPresent()) { XmlElement tradeIdEl = tradeIdOptEl.get(); String scheme = tradeIdEl.getAttribute("tradeIdScheme"); // ignore if there is an empty scheme or value if (!scheme.isEmpty() && !tradeIdEl.getContent().isEmpty()) { allIds.put(partyHref, StandardId.of(StandardId.encodeScheme(scheme), tradeIdEl.getContent())); } } } } return allIds; }
/** * Converts an FpML 'AdjustableDate' or 'AdjustableDate2' to an {@code AdjustableDate}. * * @param baseEl the FpML adjustable date element * @return the adjustable date * @throws RuntimeException if unable to parse */ public AdjustableDate parseAdjustableDate(XmlElement baseEl) { // FpML content: ('unadjustedDate', 'dateAdjustments', 'adjustedDate?') Optional<XmlElement> unadjOptEl = baseEl.findChild("unadjustedDate"); if (unadjOptEl.isPresent()) { LocalDate unadjustedDate = parseDate(unadjOptEl.get()); Optional<XmlElement> adjustmentOptEl = baseEl.findChild("dateAdjustments"); Optional<XmlElement> adjustmentRefOptEl = baseEl.findChild("dateAdjustmentsReference"); if (!adjustmentOptEl.isPresent() && !adjustmentRefOptEl.isPresent()) { return AdjustableDate.of(unadjustedDate); } XmlElement adjustmentEl = adjustmentRefOptEl.isPresent() ? lookupReference(adjustmentRefOptEl.get()) : adjustmentOptEl.get(); BusinessDayAdjustment adjustment = parseBusinessDayAdjustments(adjustmentEl); return AdjustableDate.of(unadjustedDate, adjustment); } LocalDate adjustedDate = parseDate(baseEl.getChild("adjustedDate")); return AdjustableDate.of(adjustedDate); }
private AdjustablePayment parsePremium(XmlElement swaptionEl, FpmlDocument document, TradeInfoBuilder tradeInfoBuilder) { XmlElement premiumEl = swaptionEl.getChild("premium"); PayReceive payReceive = document.parsePayerReceiver(premiumEl, tradeInfoBuilder); XmlElement paymentAmountEl = premiumEl.getChild("paymentAmount"); CurrencyAmount ccyAmount = document.parseCurrencyAmount(paymentAmountEl); ccyAmount = payReceive.isPay() ? ccyAmount.negated() : ccyAmount; AdjustableDate paymentDate = premiumEl.findChild("paymentDate") .map(el -> document.parseAdjustableDate(el)).get(); return AdjustablePayment.of(ccyAmount, paymentDate); }
/** * Converts an FpML 'BusinessCentersOrReference.model' to a {@code HolidayCalendar}. * * @param baseEl the FpML business centers or reference element to parse * @return the holiday calendar * @throws RuntimeException if unable to parse */ public HolidayCalendarId parseBusinessCenters(XmlElement baseEl) { // FpML content: ('businessCentersReference' | 'businessCenters') // FpML 'businessCenters' content: ('businessCenter+') // Each 'businessCenter' is a location treated as a holiday calendar Optional<XmlElement> optionalBusinessCentersEl = baseEl.findChild("businessCenters"); XmlElement businessCentersEl = optionalBusinessCentersEl.orElseGet(() -> lookupReference(baseEl.getChild("businessCentersReference"))); HolidayCalendarId calendar = HolidayCalendarIds.NO_HOLIDAYS; for (XmlElement businessCenterEl : businessCentersEl.getChildren("businessCenter")) { calendar = calendar.combinedWith(parseBusinessCenter(businessCenterEl)); } return calendar; }
private ValueStepSequence parseAmountSchedule(XmlElement scheduleEl, double initialValue, FpmlDocument document) { Frequency freq = document.parseFrequency(scheduleEl.getChild("stepFrequency")); LocalDate start = document.parseDate(scheduleEl.getChild("firstNotionalStepDate")); LocalDate end = document.parseDate(scheduleEl.getChild("lastNotionalStepDate")); Optional<XmlElement> amountElOpt = scheduleEl.findChild("notionalStepAmount"); if (amountElOpt.isPresent()) { double amount = document.parseDecimal(amountElOpt.get()); return ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaAmount(amount)); } double rate = document.parseDecimal(scheduleEl.getChild("notionalStepRate")); String relativeTo = scheduleEl.findChild("stepRelativeTo").map(el -> el.getContent()).orElse("Previous"); if (relativeTo.equals("Previous")) { return ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaMultiplier(rate)); } else if (relativeTo.equals("Initial")) { // data model does not support 'relative to initial' but can calculate amount here double amount = initialValue * rate; return ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaAmount(amount)); } else { throw new FpmlParseException(Messages.format( "Unknown 'stepRelativeTo' value '{}', expected 'Initial' or 'Previous'", relativeTo)); } }
public void test_ofChildren_one() { XmlElement test = XmlElement.ofChildren("test", ATTR_MAP, CHILD_LIST_ONE); assertEquals(test.getName(), "test"); assertEquals(test.getAttributes(), ATTR_MAP); assertEquals(test.hasContent(), false); assertEquals(test.getContent(), ""); assertEquals(test.getChildren(), CHILD_LIST_ONE); assertEquals(test.getAttribute("key"), "value"); assertEquals(test.findAttribute("key"), Optional.of("value")); assertEquals(test.findAttribute("none"), Optional.empty()); assertEquals(test.getChild(0), LEAF1); assertEquals(test.getChild("leaf1"), LEAF1); assertEquals(test.findChild("leaf1"), Optional.of(LEAF1)); assertEquals(test.getChildren("leaf1"), ImmutableList.of(LEAF1)); assertEquals(test.toString(), "<test key=\"value\" og=\"strata\">" + System.lineSeparator() + " <leaf1 ... />" + System.lineSeparator() + "</test>"); }
private NotionalSchedule parseSwapNotionalSchedule(XmlElement legEl, XmlElement calcEl, FpmlDocument document) { // supported elements: // 'principalExchanges/initialExchange' // 'principalExchanges/finalExchange' // 'principalExchanges/intermediateExchange' // 'calculationPeriodAmount/calculation/notionalSchedule/notionalStepSchedule' // 'calculationPeriodAmount/calculation/notionalSchedule/notionalStepParameters' NotionalSchedule.Builder notionalScheduleBuilder = NotionalSchedule.builder(); // exchanges legEl.findChild("principalExchanges").ifPresent(el -> { notionalScheduleBuilder.initialExchange(Boolean.parseBoolean(el.getChild("initialExchange").getContent())); notionalScheduleBuilder.intermediateExchange( Boolean.parseBoolean(el.getChild("intermediateExchange").getContent())); notionalScheduleBuilder.finalExchange(Boolean.parseBoolean(el.getChild("finalExchange").getContent())); }); // notional schedule XmlElement notionalEl = calcEl.getChild("notionalSchedule"); XmlElement stepScheduleEl = notionalEl.getChild("notionalStepSchedule"); Optional<XmlElement> paramScheduleElOpt = notionalEl.findChild("notionalStepParameters"); double initialValue = document.parseDecimal(stepScheduleEl.getChild("initialValue")); ValueStepSequence seq = paramScheduleElOpt.map(el -> parseAmountSchedule(el, initialValue, document)).orElse(null); notionalScheduleBuilder.amount(parseSchedule(stepScheduleEl, initialValue, seq, document)); notionalScheduleBuilder.currency(document.parseCurrency(stepScheduleEl.getChild("currency"))); return notionalScheduleBuilder.build(); }
public void test_ofChildren_multi() { XmlElement test = XmlElement.ofChildren("test", ATTR_MAP, CHILD_LIST_MULTI); assertEquals(test.getName(), "test"); assertEquals(test.getAttributes(), ATTR_MAP); assertEquals(test.getAttribute("key"), "value"); assertEquals(test.hasContent(), false); assertEquals(test.getContent(), ""); assertEquals(test.getChildren(), CHILD_LIST_MULTI); assertEquals(test.getAttribute("key"), "value"); assertEquals(test.getChild(0), LEAF1); assertEquals(test.getChild(1), LEAF2A); assertEquals(test.getChild(2), LEAF2B); assertEquals(test.getChild("leaf1"), LEAF1); assertThrowsIllegalArg(() -> test.getChild("leaf2")); assertEquals(test.findChild("leaf1"), Optional.of(LEAF1)); assertThrowsIllegalArg(() -> test.findChild("leaf2")); assertEquals(test.getChildren("leaf1"), ImmutableList.of(LEAF1)); assertEquals(test.getChildren("leaf2"), ImmutableList.of(LEAF2A, LEAF2B)); }
public void test_ofChildren_empty() { XmlElement test = XmlElement.ofChildren("test", CHILD_LIST_EMPTY); assertEquals(test.getName(), "test"); assertEquals(test.getAttributes(), ATTR_MAP_EMPTY); assertEquals(test.hasContent(), false); assertEquals(test.getContent(), ""); assertEquals(test.getChildren(), CHILD_LIST_EMPTY); assertThrowsIllegalArg(() -> test.getAttribute("notFound")); assertThrows(() -> test.getChild(0), IndexOutOfBoundsException.class); assertThrowsIllegalArg(() -> test.getChild("notFound")); assertEquals(test.findChild("notFound"), Optional.empty()); assertEquals(test.getChildren("notFound"), ImmutableList.of()); assertEquals(test.toString(), "<test></test>"); }
public void test_ofContent() { XmlElement test = XmlElement.ofContent("test", ATTR_MAP_EMPTY, "hello"); assertEquals(test.getName(), "test"); assertEquals(test.getAttributes(), ATTR_MAP_EMPTY); assertEquals(test.hasContent(), true); assertEquals(test.getContent(), "hello"); assertEquals(test.getChildren(), CHILD_LIST_EMPTY); assertThrowsIllegalArg(() -> test.getAttribute("notFound")); assertThrows(() -> test.getChild(0), IndexOutOfBoundsException.class); assertThrowsIllegalArg(() -> test.getChild("notFound")); assertEquals(test.findChild("notFound"), Optional.empty()); assertEquals(test.getChildren("notFound"), ImmutableList.of()); assertEquals(test.toString(), "<test>hello</test>"); }
public void test_ofContent_empty() { XmlElement test = XmlElement.ofContent("test", ""); assertEquals(test.getName(), "test"); assertEquals(test.getAttributes(), ATTR_MAP_EMPTY); assertEquals(test.hasContent(), false); assertEquals(test.getContent(), ""); assertEquals(test.getChildren(), CHILD_LIST_EMPTY); assertThrowsIllegalArg(() -> test.getAttribute("notFound")); assertThrows(() -> test.getChild(0), IndexOutOfBoundsException.class); assertThrowsIllegalArg(() -> test.getChild("notFound")); assertEquals(test.findChild("notFound"), Optional.empty()); assertEquals(test.getChildren("notFound"), ImmutableList.of()); assertEquals(test.toString(), "<test></test>"); }
/** * Converts an FpML 'RelativeDateOffset' to a {@code DaysAdjustment}. * * @param baseEl the FpML adjustable date element * @return the days adjustment * @throws RuntimeException if unable to parse */ public DaysAdjustment parseRelativeDateOffsetDays(XmlElement baseEl) { // FpML content: ('periodMultiplier', 'period', 'dayType?', // 'businessDayConvention', 'BusinessCentersOrReference.model?' // 'dateRelativeTo', 'adjustedDate') // The 'dateRelativeTo' element is not used here // The 'adjustedDate' element is ignored Period period = parsePeriod(baseEl); if (period.toTotalMonths() != 0) { throw new FpmlParseException("Expected days-based period but found " + period); } Optional<XmlElement> dayTypeEl = baseEl.findChild("dayType"); boolean calendarDays = period.isZero() || (dayTypeEl.isPresent() && dayTypeEl.get().getContent().equals("Calendar")); BusinessDayConvention fixingBdc = convertBusinessDayConvention( baseEl.getChild("businessDayConvention").getContent()); HolidayCalendarId calendar = parseBusinessCenters(baseEl); if (calendarDays) { return DaysAdjustment.ofCalendarDays( period.getDays(), BusinessDayAdjustment.of(fixingBdc, calendar)); } else { return DaysAdjustment.ofBusinessDays(period.getDays(), calendar); } }