//------------------------------------------------------------------------- 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: // '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()); }
private FxSingle parseLeg(XmlElement legEl, FpmlDocument document, TradeInfoBuilder tradeInfoBuilder) { // supported elements: // 'exchangedCurrency1/paymentAmount' // 'exchangedCurrency2/paymentAmount' // 'valueDate' // ignored elements: // 'dealtCurrency?' // 'exchangeRate' // rejected elements: // 'nonDeliverableSettlement?' // 'currency1ValueDate' // 'currency2ValueDate' document.validateNotPresent(legEl, "currency1ValueDate"); document.validateNotPresent(legEl, "currency2ValueDate"); document.validateNotPresent(legEl, "nonDeliverableSettlement"); XmlElement curr1El = legEl.getChild("exchangedCurrency1"); XmlElement curr2El = legEl.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 valueDate = document.parseDate(legEl.getChild("valueDate")); // result return(FxSingle.of(curr1Amount, curr2Amount, valueDate)); }
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.Pay ? ccyAmount.negated() : ccyAmount; AdjustableDate paymentDate = premiumEl.findChild("paymentDate").map(el => document.parseAdjustableDate(el)).get(); return(AdjustablePayment.of(ccyAmount, paymentDate)); }
//------------------------------------------------------------------------- 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()); }
// 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"); }