// convention-based
        // ideally we'd use the trade date plus "period to start" to get the spot/payment date
        // but we don't have all the data and it gets complicated in places like TRY, RUB and AED
        private static FxSingleTrade parseConvention(CsvRow row, TradeInfo info)
        {
            CurrencyPair pair        = CurrencyPair.parse(row.getValue(CONVENTION_FIELD));
            BuySell      buySell     = LoaderUtils.parseBuySell(row.getValue(BUY_SELL_FIELD));
            Currency     currency    = Currency.parse(row.getValue(CURRENCY_FIELD));
            double       notional    = LoaderUtils.parseDouble(row.getValue(NOTIONAL_FIELD));
            double       fxRate      = LoaderUtils.parseDouble(row.getValue(FX_RATE_FIELD));
            LocalDate    paymentDate = LoaderUtils.parseDate(row.getValue(PAYMENT_DATE_FIELD));
            Optional <BusinessDayAdjustment> paymentAdj = parsePaymentDateAdjustment(row);

            CurrencyAmount amount = CurrencyAmount.of(currency, buySell.normalize(notional));
            FxSingle       fx     = paymentAdj.map(adj => FxSingle.of(amount, FxRate.of(pair, fxRate), paymentDate, adj)).orElseGet(() => FxSingle.of(amount, FxRate.of(pair, fxRate), paymentDate));

            return(FxSingleTrade.of(info, fx));
        }
        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));
        }
        // parse an FxSingle
        internal static FxSingle parseFxSingle(CsvRow row, string prefix)
        {
            PayReceive direction1   = LoaderUtils.parsePayReceive(row.getValue(prefix + LEG_1_DIRECTION_FIELD));
            Currency   currency1    = Currency.of(row.getValue(prefix + LEG_1_CURRENCY_FIELD));
            double     notional1    = LoaderUtils.parseDouble(row.getValue(prefix + LEG_1_NOTIONAL_FIELD));
            LocalDate  paymentDate1 = row.findValue(prefix + LEG_1_PAYMENT_DATE_FIELD).map(str => LoaderUtils.parseDate(str)).orElseGet(() => LoaderUtils.parseDate(row.getValue(prefix + PAYMENT_DATE_FIELD)));
            PayReceive direction2   = LoaderUtils.parsePayReceive(row.getValue(prefix + LEG_2_DIRECTION_FIELD));
            Currency   currency2    = Currency.of(row.getValue(prefix + LEG_2_CURRENCY_FIELD));
            double     notional2    = LoaderUtils.parseDouble(row.getValue(prefix + LEG_2_NOTIONAL_FIELD));
            LocalDate  paymentDate2 = row.findValue(prefix + LEG_2_PAYMENT_DATE_FIELD).map(str => LoaderUtils.parseDate(str)).orElseGet(() => LoaderUtils.parseDate(row.getValue(prefix + PAYMENT_DATE_FIELD)));
            Optional <BusinessDayAdjustment> paymentAdj = parsePaymentDateAdjustment(row);

            if (direction1.Equals(direction2))
            {
                throw new System.ArgumentException(Messages.format("FxSingle legs must not have the same direction: {}, {}", direction1.ToString(), direction2.ToString()));
            }
            Payment payment1 = Payment.of(currency1, direction1.normalize(notional1), paymentDate1);
            Payment payment2 = Payment.of(currency2, direction2.normalize(notional2), paymentDate2);

            return(paymentAdj.map(adj => FxSingle.of(payment1, payment2, adj)).orElseGet(() => FxSingle.of(payment1, payment2)));
        }
        internal static FxVanillaOption sut2()
        {
            FxSingle fxProduct = FxSingle.of(CurrencyAmount.of(EUR, -NOTIONAL), CurrencyAmount.of(GBP, NOTIONAL * 0.9), PAYMENT_DATE);

            return(FxVanillaOption.builder().longShort(LongShort.SHORT).expiryDate(LocalDate.of(2015, 2, 15)).expiryTime(LocalTime.of(12, 45)).expiryZone(ZoneId.of("GMT")).underlying(fxProduct).build());
        }
예제 #5
0
        //-------------------------------------------------------------------------
        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));
        }