Ejemplo n.º 1
0
        // Converts an FpML 'NonNegativeAmountSchedule' to a {@code ValueStepSequence}.
        private ValueStepSequence parseAmountSchedule(XmlElement scheduleEl, double initialValue, FpmlDocument document)
        {
            Frequency             freq        = document.parseFrequency(scheduleEl.getChild("stepFrequency"));
            LocalDate             start       = document.parseDate(scheduleEl.getChild("firstNotionalStepDate"));
            LocalDate             end         = document.parseDate(scheduleEl.getChild("lastNotionalStepDate"));
            Optional <XmlElement> amountElOpt = scheduleEl.findChild("notionalStepAmount");

            if (amountElOpt.Present)
            {
                double amount = document.parseDecimal(amountElOpt.get());
                return(ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaAmount(amount)));
            }
            double rate       = document.parseDecimal(scheduleEl.getChild("notionalStepRate"));
            string relativeTo = scheduleEl.findChild("stepRelativeTo").map(el => el.Content).orElse("Previous");

            if (relativeTo.Equals("Previous"))
            {
                return(ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaMultiplier(rate)));
            }
            else if (relativeTo.Equals("Initial"))
            {
                // data model does not support 'relative to initial' but can calculate amount here
                double amount = initialValue * rate;
                return(ValueStepSequence.of(start, end, freq, ValueAdjustment.ofDeltaAmount(amount)));
            }
            else
            {
                throw new FpmlParseException(Messages.format("Unknown 'stepRelativeTo' value '{}', expected 'Initial' or 'Previous'", relativeTo));
            }
        }
Ejemplo n.º 2
0
        // Converts an FpML 'Schedule' to a {@code ValueSchedule}.
        private ValueSchedule parseSchedule(XmlElement scheduleEl, double initialValue, ValueStepSequence seq, FpmlDocument document)
        {
            IList <XmlElement> stepEls = scheduleEl.getChildren("step");

            ImmutableList.Builder <ValueStep> stepBuilder = ImmutableList.builder();
            foreach (XmlElement stepEl in stepEls)
            {
                LocalDate stepDate  = document.parseDate(stepEl.getChild("stepDate"));
                double    stepValue = document.parseDecimal(stepEl.getChild("stepValue"));
                stepBuilder.add(ValueStep.of(stepDate, ValueAdjustment.ofReplace(stepValue)));
            }
            return(ValueSchedule.builder().initialValue(initialValue).steps(stepBuilder.build()).stepSequence(seq).build());
        }
Ejemplo n.º 3
0
        // parses the accrual schedule
        private PeriodicSchedule parseSwapAccrualSchedule(XmlElement legEl, FpmlDocument document)
        {
            // supported elements:
            //  'calculationPeriodDates/effectiveDate'
            //  'calculationPeriodDates/relativeEffectiveDate'
            //  'calculationPeriodDates/terminationDate'
            //  'calculationPeriodDates/relativeTerminationDate'
            //  'calculationPeriodDates/calculationPeriodDates'
            //  'calculationPeriodDates/calculationPeriodDatesAdjustments'
            //  'calculationPeriodDates/firstPeriodStartDate?'
            //  'calculationPeriodDates/firstRegularPeriodStartDate?'
            //  'calculationPeriodDates/lastRegularPeriodEndDate?'
            //  'calculationPeriodDates/stubPeriodType?'
            //  'calculationPeriodDates/calculationPeriodFrequency'
            // ignored elements:
            //  'calculationPeriodDates/firstCompoundingPeriodEndDate?'
            PeriodicSchedule.Builder accrualScheduleBuilder = PeriodicSchedule.builder();
            // calculation dates
            XmlElement calcPeriodDatesEl = legEl.getChild("calculationPeriodDates");
            // business day adjustments
            BusinessDayAdjustment bda = document.parseBusinessDayAdjustments(calcPeriodDatesEl.getChild("calculationPeriodDatesAdjustments"));

            accrualScheduleBuilder.businessDayAdjustment(bda);
            // start date
            AdjustableDate startDate = calcPeriodDatesEl.findChild("effectiveDate").map(el => document.parseAdjustableDate(el)).orElseGet(() => document.parseAdjustedRelativeDateOffset(calcPeriodDatesEl.getChild("relativeEffectiveDate")));

            accrualScheduleBuilder.startDate(startDate.Unadjusted);
            if (!bda.Equals(startDate.Adjustment))
            {
                accrualScheduleBuilder.startDateBusinessDayAdjustment(startDate.Adjustment);
            }
            // end date
            AdjustableDate endDate = calcPeriodDatesEl.findChild("terminationDate").map(el => document.parseAdjustableDate(el)).orElseGet(() => document.parseAdjustedRelativeDateOffset(calcPeriodDatesEl.getChild("relativeTerminationDate")));

            accrualScheduleBuilder.endDate(endDate.Unadjusted);
            if (!bda.Equals(endDate.Adjustment))
            {
                accrualScheduleBuilder.endDateBusinessDayAdjustment(endDate.Adjustment);
            }
            // first period start date
            calcPeriodDatesEl.findChild("firstPeriodStartDate").ifPresent(el =>
            {
                accrualScheduleBuilder.overrideStartDate(document.parseAdjustableDate(el));
            });
            // first regular date
            calcPeriodDatesEl.findChild("firstRegularPeriodStartDate").ifPresent(el =>
            {
                accrualScheduleBuilder.firstRegularStartDate(document.parseDate(el));
            });
            // last regular date
            calcPeriodDatesEl.findChild("lastRegularPeriodEndDate").ifPresent(el =>
            {
                accrualScheduleBuilder.lastRegularEndDate(document.parseDate(el));
            });
            // stub type
            calcPeriodDatesEl.findChild("stubPeriodType").ifPresent(el =>
            {
                accrualScheduleBuilder.stubConvention(parseStubConvention(el, document));
            });
            // frequency
            XmlElement freqEl      = calcPeriodDatesEl.getChild("calculationPeriodFrequency");
            Frequency  accrualFreq = document.parseFrequency(freqEl);

            accrualScheduleBuilder.frequency(accrualFreq);
            // roll convention
            accrualScheduleBuilder.rollConvention(document.convertRollConvention(freqEl.getChild("rollConvention").Content));
            return(accrualScheduleBuilder.build());
        }
Ejemplo n.º 4
0
        // parses the payment schedule
        private PaymentSchedule parseSwapPaymentSchedule(XmlElement legEl, XmlElement calcEl, FpmlDocument document)
        {
            // supported elements:
            //  'paymentDates/paymentFrequency'
            //  'paymentDates/payRelativeTo'
            //  'paymentDates/paymentDaysOffset?'
            //  'paymentDates/paymentDatesAdjustments'
            //  'calculationPeriodAmount/calculation/compoundingMethod'
            //  'paymentDates/firstPaymentDate?'
            //  'paymentDates/lastRegularPaymentDate?'
            // ignored elements:
            //  'paymentDates/calculationPeriodDatesReference'
            //  'paymentDates/resetDatesReference'
            //  'paymentDates/valuationDatesReference'
            PaymentSchedule.Builder paymentScheduleBuilder = PaymentSchedule.builder();
            // payment dates
            XmlElement paymentDatesEl = legEl.getChild("paymentDates");

            // frequency
            paymentScheduleBuilder.paymentFrequency(document.parseFrequency(paymentDatesEl.getChild("paymentFrequency")));
            //default for IRS is pay relative to period end; Strata model will apply the defaulting but the values is needed
            //here for first and last payment date checks
            PaymentRelativeTo payRelativeTo = paymentDatesEl.findChild("payRelativeTo").map(el => parsePayRelativeTo(el)).orElse(PaymentRelativeTo.PERIOD_END);

            paymentScheduleBuilder.paymentRelativeTo(payRelativeTo);
            // dates
            if (payRelativeTo == PaymentRelativeTo.PERIOD_END)
            {
                // ignore data if not PeriodEnd and hope schedule is worked out correctly by other means
                // this provides compatibility for old code that ignored these FpML fields
                paymentDatesEl.findChild("firstPaymentDate").map(el => document.parseDate(el)).ifPresent(date => paymentScheduleBuilder.firstRegularStartDate(date));
                paymentDatesEl.findChild("lastRegularPaymentDate").map(el => document.parseDate(el)).ifPresent(date => paymentScheduleBuilder.lastRegularEndDate(date));
            }
            // offset
            Optional <XmlElement> paymentOffsetEl = paymentDatesEl.findChild("paymentDaysOffset");
            BusinessDayAdjustment payAdjustment   = document.parseBusinessDayAdjustments(paymentDatesEl.getChild("paymentDatesAdjustments"));

            if (paymentOffsetEl.Present)
            {
                Period period = document.parsePeriod(paymentOffsetEl.get());
                if (period.toTotalMonths() != 0)
                {
                    throw new FpmlParseException("Invalid 'paymentDatesAdjustments' value, expected days-based period: " + period);
                }
                Optional <XmlElement> dayTypeEl = paymentOffsetEl.get().findChild("dayType");
                bool fixingCalendarDays         = period.Zero || (dayTypeEl.Present && dayTypeEl.get().Content.Equals("Calendar"));
                if (fixingCalendarDays)
                {
                    paymentScheduleBuilder.paymentDateOffset(DaysAdjustment.ofCalendarDays(period.Days, payAdjustment));
                }
                else
                {
                    paymentScheduleBuilder.paymentDateOffset(DaysAdjustment.ofBusinessDays(period.Days, payAdjustment.Calendar));
                }
            }
            else
            {
                paymentScheduleBuilder.paymentDateOffset(DaysAdjustment.ofCalendarDays(0, payAdjustment));
            }
            // compounding
            calcEl.findChild("compoundingMethod").ifPresent(compoundingEl =>
            {
                paymentScheduleBuilder.compoundingMethod(CompoundingMethod.of(compoundingEl.Content));
            });
            return(paymentScheduleBuilder.build());
        }
        //-------------------------------------------------------------------------
        public Trade parseTrade(FpmlDocument document, XmlElement tradeEl)
        {
            // supported elements:
            //  'buyerPartyReference'
            //  'sellerPartyReference'
            //  'adjustedTerminationDate'
            //  'paymentDate'
            //  'fixingDateOffset'
            //  'dayCountFraction'
            //  'notional'
            //  'fixedRate'
            //  'floatingRateIndex'
            //  'indexTenor+'
            //  'fraDiscounting'
            // ignored elements:
            //  'Product.model?'
            //  'buyerAccountReference?'
            //  'sellerAccountReference?'
            //  'calculationPeriodNumberOfDays'
            //  'additionalPayment*'
            TradeInfoBuilder tradeInfoBuilder = document.parseTradeInfo(tradeEl);
            XmlElement       fraEl            = tradeEl.getChild("fra");

            Fra.Builder fraBuilder = Fra.builder();
            // buy/sell and counterparty
            fraBuilder.buySell(document.parseBuyerSeller(fraEl, tradeInfoBuilder));
            // start date
            fraBuilder.startDate(document.parseDate(fraEl.getChild("adjustedEffectiveDate")));
            // end date
            fraBuilder.endDate(document.parseDate(fraEl.getChild("adjustedTerminationDate")));
            // payment date
            fraBuilder.paymentDate(document.parseAdjustableDate(fraEl.getChild("paymentDate")));
            // fixing offset
            fraBuilder.fixingDateOffset(document.parseRelativeDateOffsetDays(fraEl.getChild("fixingDateOffset")));
            // dateRelativeTo required to refer to adjustedEffectiveDate, so ignored here
            // day count
            fraBuilder.dayCount(document.parseDayCountFraction(fraEl.getChild("dayCountFraction")));
            // notional
            CurrencyAmount notional = document.parseCurrencyAmount(fraEl.getChild("notional"));

            fraBuilder.currency(notional.Currency);
            fraBuilder.notional(notional.Amount);
            // fixed rate
            fraBuilder.fixedRate(document.parseDecimal(fraEl.getChild("fixedRate")));
            // index
            IList <Index> indexes = document.parseIndexes(fraEl);

            switch (indexes.Count)
            {
            case 1:
                fraBuilder.index((IborIndex)indexes[0]);
                break;

            case 2:
                fraBuilder.index((IborIndex)indexes[0]);
                fraBuilder.indexInterpolated((IborIndex)indexes[1]);
                break;

            default:
                throw new FpmlParseException("Expected one or two indexes, but found " + indexes.Count);
            }
            // discounting
            fraBuilder.discounting(FraDiscountingMethod.of(fraEl.getChild("fraDiscounting").Content));

            return(FraTrade.builder().info(tradeInfoBuilder.build()).product(fraBuilder.build()).build());
        }