//------------------------------------------------------------------------- public Trade parseTrade(FpmlDocument document, XmlElement tradeEl) { // supported elements: // 'payment/payerPartyReference' // 'payment/receiverPartyReference' // 'payment/paymentAmount' // 'payment/paymentDate?' // ignored elements: // 'payment/payerAccountReference?' // 'payment/receiverAccountReference?' // 'payment/paymentType?' // 'payment/settlementInformation?' // 'payment/discountFactor?' // 'payment/presentValueAmount?' TradeInfoBuilder tradeInfoBuilder = document.parseTradeInfo(tradeEl); XmlElement bulletEl = tradeEl.getChild("bulletPayment"); XmlElement paymentEl = bulletEl.getChild("payment"); BulletPayment.Builder bulletBuilder = BulletPayment.builder(); // pay/receive and counterparty bulletBuilder.payReceive(document.parsePayerReceiver(paymentEl, tradeInfoBuilder)); // payment date bulletBuilder.date(document.parseAdjustableDate(paymentEl.getChild("paymentDate"))); // amount bulletBuilder.value(document.parseCurrencyAmount(paymentEl.getChild("paymentAmount"))); return(BulletPaymentTrade.builder().info(tradeInfoBuilder.build()).product(bulletBuilder.build()).build()); }
//------------------------------------------------------------------------- public Trade parseTrade(FpmlDocument document, XmlElement tradeEl) { // supported elements: // 'exchangedCurrency1/paymentAmount' // 'exchangedCurrency2/paymentAmount' // 'valueDate' // 'currency1ValueDate' // 'currency2ValueDate' // 'nonDeliverableSettlement?' // ignored elements: // 'dealtCurrency?' // 'exchangeRate' XmlElement fxEl = tradeEl.getChild("fxSingleLeg"); // amounts TradeInfoBuilder tradeInfoBuilder = document.parseTradeInfo(tradeEl); XmlElement curr1El = fxEl.getChild("exchangedCurrency1"); XmlElement curr2El = fxEl.getChild("exchangedCurrency2"); // pay/receive and counterparty PayReceive curr1PayReceive = document.parsePayerReceiver(curr1El, tradeInfoBuilder); PayReceive curr2PayReceive = document.parsePayerReceiver(curr2El, tradeInfoBuilder); if (curr1PayReceive == curr2PayReceive) { throw new FpmlParseException("FX single leg currencies must not have same Pay/Receive direction"); } // amount CurrencyAmount curr1Amount = document.parseCurrencyAmount(curr1El.getChild("paymentAmount")); CurrencyAmount curr2Amount = document.parseCurrencyAmount(curr2El.getChild("paymentAmount")); if (curr1PayReceive == PayReceive.PAY) { curr1Amount = curr1Amount.negative(); curr2Amount = curr2Amount.positive(); } else { curr1Amount = curr1Amount.positive(); curr2Amount = curr2Amount.negative(); } // payment date LocalDate currency1Date = document.parseDate(fxEl.findChild("currency1ValueDate").orElseGet(() => fxEl.getChild("valueDate"))); LocalDate currency2Date = document.parseDate(fxEl.findChild("currency2ValueDate").orElseGet(() => fxEl.getChild("valueDate"))); // FxSingle or NDF Optional <XmlElement> ndfEl = fxEl.findChild("nonDeliverableSettlement"); if (!ndfEl.Present) { return(FxSingleTrade.builder().info(tradeInfoBuilder.build()).product(FxSingle.of(Payment.of(curr1Amount, currency1Date), Payment.of(curr2Amount, currency2Date))).build()); } if (!currency1Date.Equals(currency2Date)) { throw new FpmlParseException("FxNdf only supports a single payment date"); } return(parseNdf(document, fxEl, ndfEl.get(), curr1Amount, curr2Amount, currency1Date, tradeInfoBuilder)); }
//------------------------------------------------------------------------- public Trade parseTrade(FpmlDocument document, XmlElement tradeEl) { // supported elements: // 'nearLeg' // 'farLeg' TradeInfoBuilder tradeInfoBuilder = document.parseTradeInfo(tradeEl); XmlElement fxEl = tradeEl.getChild("fxSwap"); FxSingle nearLeg = parseLeg(fxEl.getChild("nearLeg"), document, tradeInfoBuilder); FxSingle farLeg = parseLeg(fxEl.getChild("farLeg"), document, tradeInfoBuilder); return(FxSwapTrade.builder().info(tradeInfoBuilder.build()).product(FxSwap.of(nearLeg, farLeg)).build()); }
//------------------------------------------------------------------------- public Trade parseTrade(FpmlDocument document, XmlElement tradeEl) { // supported elements: // 'swaption' // 'swaption/buyerPartyReference' // 'swaption/sellerPartyReference' // 'swaption/premium/payerPartyReference' // 'swaption/premium/receiverPartyReference' // 'swaption/premium/paymentAmount' // 'swaption/premium/paymentDate' // 'swaption/europeanExercise' // 'swaption/europeanExercise/expirationDate' // 'swaption/europeanExercise/expirationDate/adjustableDate' // 'swaption/europeanExercise/expirationDate/adjustableDate/unadjustedDate' // 'swaption/europeanExercise/expirationDate/adjustableDate/dateAdjustments' // 'swaption/europeanExercise/expirationTime // 'swaption/swap' // ignored elements: // 'Product.model?' // 'swaption/calculationAgent' // 'swaption/assetClass' // 'swaption/primaryAssestClass' // 'swaption/productId' // 'swaption/productType' // 'swaption/secondaryAssetClass' // 'swaption/sellerAccountReference' // 'swaption/sellerPartyReference' // 'swaption/swaptionAdjustedDates' // 'swaption/swaptionStraddle' TradeInfoBuilder tradeInfoBuilder = document.parseTradeInfo(tradeEl); XmlElement swaptionEl = tradeEl.getChild("swaption"); XmlElement europeanExerciseEl = swaptionEl.getChild("europeanExercise"); XmlElement expirationTimeEl = europeanExerciseEl.getChild("expirationTime"); // Parse the premium, expiry date, expiry time and expiry zone, longShort and swaption settlement. AdjustablePayment premium = parsePremium(swaptionEl, document, tradeInfoBuilder); AdjustableDate expiryDate = parseExpiryDate(europeanExerciseEl, document); LocalTime expiryTime = parseExpiryTime(expirationTimeEl, document); ZoneId expiryZone = parseExpiryZone(expirationTimeEl, document); LongShort longShort = parseLongShort(swaptionEl, document, tradeInfoBuilder); SwaptionSettlement swaptionSettlement = parseSettlement(swaptionEl, document); //Re use the Swap FpML parser to parse the underlying swap on this swaption. SwapFpmlParserPlugin swapParser = SwapFpmlParserPlugin.INSTANCE; Swap swap = swapParser.parseSwap(document, swaptionEl, tradeInfoBuilder); Swaption swaption = Swaption.builder().expiryDate(expiryDate).expiryZone(expiryZone).expiryTime(expiryTime).longShort(longShort).swaptionSettlement(swaptionSettlement).underlying(swap).build(); return(SwaptionTrade.builder().info(tradeInfoBuilder.build()).product(swaption).premium(premium).build()); }
//------------------------------------------------------------------------- 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()); }
private Trade parseNdf(FpmlDocument document, XmlElement fxEl, XmlElement ndfEl, CurrencyAmount curr1Amount, CurrencyAmount curr2Amount, LocalDate valueDate, TradeInfoBuilder tradeInfoBuilder) { // rate XmlElement rateEl = fxEl.getChild("exchangeRate"); double rate = document.parseDecimal(rateEl.getChild("rate")); XmlElement pairEl = rateEl.getChild("quotedCurrencyPair"); Currency curr1 = document.parseCurrency(pairEl.getChild("currency1")); Currency curr2 = document.parseCurrency(pairEl.getChild("currency2")); string basis = pairEl.getChild("quoteBasis").Content; FxRate fxRate; if ("Currency2PerCurrency1".Equals(basis)) { fxRate = FxRate.of(curr1, curr2, rate); } else if ("Currency1PerCurrency2".Equals(basis)) { fxRate = FxRate.of(curr2, curr1, rate); } else { throw new FpmlParseException("Unknown quote basis: " + basis); } // settlement currency Currency settleCurr = document.parseCurrency(ndfEl.getChild("settlementCurrency")); CurrencyAmount settleCurrAmount = curr1Amount.Currency.Equals(settleCurr) ? curr1Amount : curr2Amount; // index XmlElement fixingEl = ndfEl.getChild("fixing"); // only support one of these in pricing model LocalDate fixingDate = document.parseDate(fixingEl.getChild("fixingDate")); DaysAdjustment offset = DaysAdjustment.ofCalendarDays(Math.toIntExact(valueDate.until(fixingDate, DAYS))); XmlElement sourceEl = fixingEl.getChild("fxSpotRateSource"); // required for our model XmlElement primarySourceEl = sourceEl.getChild("primaryRateSource"); string primarySource = primarySourceEl.getChild("rateSource").Content; string primaryPage = primarySourceEl.findChild("rateSourcePage").map(e => e.Content).orElse(""); LocalTime time = document.parseTime(sourceEl.getChild("fixingTime").getChild("hourMinuteTime")); // required for our model HolidayCalendarId calendar = document.parseBusinessCenter(sourceEl.getChild("fixingTime").getChild("businessCenter")); FxIndex index = ImmutableFxIndex.builder().name(primarySource + "/" + primaryPage + "/" + time).currencyPair(CurrencyPair.of(curr1, curr2)).fixingCalendar(calendar).maturityDateOffset(offset).build(); return(FxNdfTrade.builder().info(tradeInfoBuilder.build()).product(FxNdf.builder().settlementCurrencyNotional(settleCurrAmount).agreedFxRate(fxRate).index(index).paymentDate(valueDate).build()).build()); }
// parses the CDS internal Trade parseCds(FpmlDocument document, XmlElement tradeEl, TradeInfoBuilder tradeInfoBuilder) { XmlElement cdsEl = tradeEl.getChild("creditDefaultSwap"); XmlElement generalTermsEl = cdsEl.getChild("generalTerms"); XmlElement feeLegEl = cdsEl.getChild("feeLeg"); document.validateNotPresent(generalTermsEl, "basketReferenceInformation"); document.validateNotPresent(feeLegEl, "singlePayment"); BuySell buySell = document.parseBuyerSeller(generalTermsEl, tradeInfoBuilder); // effective and termination date are optional in FpML but mandatory for Strata AdjustableDate effectiveDate = document.parseAdjustableDate(generalTermsEl.getChild("effectiveDate")); AdjustableDate terminationDate = document.parseAdjustableDate(generalTermsEl.getChild("scheduledTerminationDate")); BusinessDayAdjustment bda = generalTermsEl.findChild("dateAdjustments").map(el => document.parseBusinessDayAdjustments(el)).orElse(BusinessDayAdjustment.NONE); PeriodicSchedule.Builder scheduleBuilder = PeriodicSchedule.builder().startDate(effectiveDate.Unadjusted).startDateBusinessDayAdjustment(effectiveDate.Adjustment).endDate(terminationDate.Unadjusted).endDateBusinessDayAdjustment(terminationDate.Adjustment).businessDayAdjustment(bda); // an upfront fee Optional <XmlElement> initialPaymentOptEl = feeLegEl.findChild("initialPayment"); AdjustablePayment upfrontFee = null; if (initialPaymentOptEl.Present) { XmlElement initialPaymentEl = initialPaymentOptEl.get(); PayReceive payRec = document.parsePayerReceiver(initialPaymentEl, tradeInfoBuilder); CurrencyAmount amount = document.parseCurrencyAmount(initialPaymentEl.getChild("paymentAmount")); LocalDate date = initialPaymentEl.findChild("adjustablePaymentDate").map(el => document.parseDate(el)).orElse(effectiveDate.Unadjusted); AdjustableDate adjDate = AdjustableDate.of(date, bda); upfrontFee = payRec.Pay ? AdjustablePayment.ofPay(amount, adjDate) : AdjustablePayment.ofReceive(amount, adjDate); } // we require a periodicPayment and fixedAmountCalculation XmlElement periodicPaymentEl = feeLegEl.getChild("periodicPayment"); scheduleBuilder.frequency(periodicPaymentEl.findChild("paymentFrequency").map(el => document.parseFrequency(el)).orElse(Frequency.P3M)); periodicPaymentEl.findChild("firstPaymentDate").ifPresent(el => scheduleBuilder.firstRegularStartDate(document.parseDate(el))); periodicPaymentEl.findChild("firstPeriodStartDate").ifPresent(el => scheduleBuilder.overrideStartDate(AdjustableDate.of(document.parseDate(el)))); periodicPaymentEl.findChild("lastRegularPaymentDate").ifPresent(el => scheduleBuilder.lastRegularEndDate(document.parseDate(el))); scheduleBuilder.rollConvention(periodicPaymentEl.findChild("rollConvention").map(el => document.convertRollConvention(el.Content)).orElse(null)); XmlElement fixedAmountCalcEl = periodicPaymentEl.getChild("fixedAmountCalculation"); double fixedRate = document.parseDecimal(fixedAmountCalcEl.getChild("fixedRate")); DayCount dayCount = fixedAmountCalcEl.findChild("dayCountFraction").map(el => document.parseDayCountFraction(el)).orElse(DayCounts.ACT_360); // handle a single protectionTerms element XmlElement protectionTermEl = cdsEl.getChild("protectionTerms"); CurrencyAmount notional = document.parseCurrencyAmount(protectionTermEl.getChild("calculationAmount")); // single name CDS Optional <XmlElement> singleOptEl = generalTermsEl.findChild("referenceInformation"); if (singleOptEl.Present) { // we require a single entityId XmlElement referenceEntityEl = singleOptEl.get().getChild("referenceEntity"); XmlElement entityIdEl = referenceEntityEl.getChild("entityId"); string scheme = entityIdEl.findAttribute("entityIdScheme").orElse("http://www.fpml.org/coding-scheme/external/entity-id-RED-1-0"); string value = entityIdEl.Content; StandardId entityId = StandardId.of(scheme, value); Cds cds = Cds.builder().buySell(buySell).legalEntityId(entityId).currency(notional.Currency).notional(notional.Amount).paymentSchedule(scheduleBuilder.build()).fixedRate(fixedRate).dayCount(dayCount).build(); return(CdsTrade.builder().info(tradeInfoBuilder.build()).product(cds).upfrontFee(upfrontFee).build()); } // CDS index Optional <XmlElement> indexOptEl = generalTermsEl.findChild("indexReferenceInformation"); if (indexOptEl.Present) { string indexName = indexOptEl.get().getChild("indexName").Content; CdsIndex cdsIndex = CdsIndex.builder().buySell(buySell).cdsIndexId(StandardId.of("CDX-Name", indexName)).currency(notional.Currency).notional(notional.Amount).paymentSchedule(scheduleBuilder.build()).fixedRate(fixedRate).dayCount(dayCount).build(); return(CdsIndexTrade.builder().info(tradeInfoBuilder.build()).product(cdsIndex).upfrontFee(upfrontFee).build()); } // unknown type throw new FpmlParseException("FpML CDS must be single name or index"); }