All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opengamma.strata.loader.impl.fpml.FxSingleLegFpmlParserPlugin Maven / Gradle / Ivy

There is a newer version: 2.12.46
Show newest version
/*
 * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.loader.impl.fpml;

import static java.time.temporal.ChronoUnit.DAYS;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Optional;

import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.CurrencyPair;
import com.opengamma.strata.basics.currency.FxRate;
import com.opengamma.strata.basics.currency.Payment;
import com.opengamma.strata.basics.date.DaysAdjustment;
import com.opengamma.strata.basics.date.HolidayCalendarId;
import com.opengamma.strata.basics.index.FxIndex;
import com.opengamma.strata.basics.index.ImmutableFxIndex;
import com.opengamma.strata.collect.io.XmlElement;
import com.opengamma.strata.loader.fpml.FpmlDocument;
import com.opengamma.strata.loader.fpml.FpmlParseException;
import com.opengamma.strata.loader.fpml.FpmlParserPlugin;
import com.opengamma.strata.product.Trade;
import com.opengamma.strata.product.TradeInfoBuilder;
import com.opengamma.strata.product.common.PayReceive;
import com.opengamma.strata.product.fx.FxNdf;
import com.opengamma.strata.product.fx.FxNdfTrade;
import com.opengamma.strata.product.fx.FxSingle;
import com.opengamma.strata.product.fx.FxSingleTrade;

/**
 * FpML parser for single leg FX.
 * 

* This parser handles the subset of FpML necessary to populate the trade model. */ final class FxSingleLegFpmlParserPlugin implements FpmlParserPlugin { // this class is loaded by ExtendedEnum reflection /** * The singleton instance of the parser. */ public static final FxSingleLegFpmlParserPlugin INSTANCE = new FxSingleLegFpmlParserPlugin(); /** * Restricted constructor. */ private FxSingleLegFpmlParserPlugin() { } //------------------------------------------------------------------------- @Override 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 ndfEl = fxEl.findChild("nonDeliverableSettlement"); if (!ndfEl.isPresent()) { 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, but found '{value}' and '{value2}'", currency1Date, currency2Date); } return parseNdf(document, fxEl, ndfEl.get(), curr1Amount, curr2Amount, currency1Date, tradeInfoBuilder); } 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").getContent(); 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 '{value}'", basis); } // settlement currency Currency settleCurr = document.parseCurrency(ndfEl.getChild("settlementCurrency")); CurrencyAmount settleCurrAmount = curr1Amount.getCurrency().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").getContent(); String primaryPage = primarySourceEl.findChild("rateSourcePage").map(e -> e.getContent()).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(); } //------------------------------------------------------------------------- @Override public String getName() { return "fxSingleLeg"; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy