private static CurveNode curveFxSwapCurveNode( String conventionStr, String timeStr, String label, QuoteId quoteId, double spread, CurveNodeDate date, CurveNodeDateOrder order) { if (!DoubleMath.fuzzyEquals(spread, 0d, 1e-10d)) { throw new IllegalArgumentException("Additional spread must be zero for FX swaps"); } Matcher matcher = SIMPLE_YMD_TIME_REGEX.matcher(timeStr.toUpperCase(Locale.ENGLISH)); if (!matcher.matches()) { throw new IllegalArgumentException(Messages.format("Invalid time format for FX swap: {}", timeStr)); } Period periodToEnd = Period.parse("P" + matcher.group(1)); FxSwapConvention convention = FxSwapConvention.of(conventionStr); FxSwapTemplate template = FxSwapTemplate.of(periodToEnd, convention); return FxSwapCurveNode.builder() .template(template) .farForwardPointsId(quoteId) .label(label) .date(date) .dateOrder(order) .build(); }