Пример #1
0
        // Converts an FpML 'InflationRateCalculation' to a {@code RateCalculation}.
        private RateCalculation parseInflation(XmlElement legEl, XmlElement calcEl, XmlElement inflationEl, PeriodicSchedule accrualSchedule, FpmlDocument document)
        {
            // supported elements:
            //  'calculationPeriodAmount/calculation/inflationRateCalculation'
            //  'calculationPeriodAmount/calculation/inflationRateCalculation/floatingRateIndex'
            //  'calculationPeriodAmount/calculation/inflationRateCalculation/indexTenor?'
            //  'calculationPeriodAmount/calculation/inflationRateCalculation/floatingRateMultiplierSchedule?'
            //  'calculationPeriodAmount/calculation/inflationRateCalculation/inflationLag'
            //  'calculationPeriodAmount/calculation/inflationRateCalculation/interpolationMethod'
            //  'calculationPeriodAmount/calculation/inflationRateCalculation/initialIndexLevel?'
            //  'calculationPeriodAmount/calculation/dayCountFraction'
            // ignored elements:
            // 'calculationPeriodAmount/calculation/inflationRateCalculation/indexSource'
            // 'calculationPeriodAmount/calculation/inflationRateCalculation/mainPublication'
            // 'calculationPeriodAmount/calculation/inflationRateCalculation/fallbackBondApplicable'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/initialRate?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/finalRateRounding?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/averagingMethod?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/negativeInterestRateTreatment?'
            //  'resetDates'
            // rejected elements:
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/spreadSchedule*'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/rateTreatment?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/capRateSchedule?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/floorRateSchedule?'
            //  'stubCalculationPeriodAmount'
            document.validateNotPresent(inflationEl, "spreadSchedule");
            document.validateNotPresent(inflationEl, "rateTreatment");
            document.validateNotPresent(inflationEl, "capRateSchedule");
            document.validateNotPresent(inflationEl, "floorRateSchedule");
            document.validateNotPresent(legEl, "stubCalculationPeriodAmount");     // TODO: parse fixed stub rate
            InflationRateCalculation.Builder builder = InflationRateCalculation.builder();
            // index
            builder.index(document.parsePriceIndex(inflationEl));
            // lag
            builder.lag(document.parsePeriod(inflationEl.getChild("inflationLag")));
            // interpolation
            string interpStr = inflationEl.getChild("interpolationMethod").Content;

            builder.indexCalculationMethod(interpStr.ToLower(Locale.ENGLISH).Contains("linear") ? PriceIndexCalculationMethod.INTERPOLATED : PriceIndexCalculationMethod.MONTHLY);
            // initial index
            inflationEl.findChild("initialIndexLevel").ifPresent(el =>
            {
                builder.firstIndexValue(document.parseDecimal(el));
            });
            // gearing
            inflationEl.findChild("floatingRateMultiplierSchedule").ifPresent(el =>
            {
                builder.gearing(parseSchedule(el, document));
            });
            return(builder.build());
        }
Пример #2
0
        // Converts an FpML 'FloatingRateCalculation' to a {@code RateCalculation}.
        private RateCalculation parseFloat(XmlElement legEl, XmlElement calcEl, XmlElement floatingEl, PeriodicSchedule accrualSchedule, FpmlDocument document)
        {
            // supported elements:
            //  'calculationPeriodAmount/calculation/floatingRateCalculation'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/floatingRateIndex'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/indexTenor?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/floatingRateMultiplierSchedule?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/spreadSchedule*'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/initialRate?' (Ibor only)
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/averagingMethod?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/negativeInterestRateTreatment?'
            //  'calculationPeriodAmount/calculation/dayCountFraction'
            //  'resetDates/resetRelativeTo'
            //  'resetDates/fixingDates'
            //  'resetDates/rateCutOffDaysOffset' (OIS only)
            //  'resetDates/resetFrequency'
            //  'resetDates/resetDatesAdjustments'
            //  'stubCalculationPeriodAmount/initalStub' (Ibor only, Overnight must match index)
            //  'stubCalculationPeriodAmount/finalStub' (Ibor only, Overnight must match index)
            // ignored elements:
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/finalRateRounding?'
            //  'calculationPeriodAmount/calculation/discounting?'
            //  'resetDates/calculationPeriodDatesReference'
            // rejected elements:
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/spreadSchedule/type?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/rateTreatment?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/capRateSchedule?'
            //  'calculationPeriodAmount/calculation/floatingRateCalculation/floorRateSchedule?'
            //  'resetDates/initialFixingDate'
            document.validateNotPresent(floatingEl, "rateTreatment");
            document.validateNotPresent(floatingEl, "capRateSchedule");
            document.validateNotPresent(floatingEl, "floorRateSchedule");
            Index index = document.parseIndex(floatingEl);

            if (index is IborIndex)
            {
                IborRateCalculation.Builder iborRateBuilder = IborRateCalculation.builder();
                // day count
                iborRateBuilder.dayCount(document.parseDayCountFraction(calcEl.getChild("dayCountFraction")));
                // index
                iborRateBuilder.index((IborIndex)document.parseIndex(floatingEl));
                // gearing
                floatingEl.findChild("floatingRateMultiplierSchedule").ifPresent(el =>
                {
                    iborRateBuilder.gearing(parseSchedule(el, document));
                });
                // spread
                if (floatingEl.getChildren("spreadSchedule").size() > 1)
                {
                    throw new FpmlParseException("Only one 'spreadSchedule' is supported");
                }
                floatingEl.findChild("spreadSchedule").ifPresent(el =>
                {
                    document.validateNotPresent(el, "type");
                    iborRateBuilder.spread(parseSchedule(el, document));
                });
                // initial fixed rate
                floatingEl.findChild("initialRate").ifPresent(el =>
                {
                    iborRateBuilder.firstRegularRate(document.parseDecimal(el));
                });
                // negative rates
                floatingEl.findChild("negativeInterestRateTreatment").ifPresent(el =>
                {
                    iborRateBuilder.negativeRateMethod(parseNegativeInterestRateTreatment(el));
                });
                // resets
                legEl.findChild("resetDates").ifPresent(resetDatesEl =>
                {
                    document.validateNotPresent(resetDatesEl, "initialFixingDate");
                    document.validateNotPresent(resetDatesEl, "rateCutOffDaysOffset");
                    resetDatesEl.findChild("resetRelativeTo").ifPresent(el =>
                    {
                        iborRateBuilder.fixingRelativeTo(parseResetRelativeTo(el));
                    });
                    iborRateBuilder.fixingDateOffset(document.parseRelativeDateOffsetDays(resetDatesEl.getChild("fixingDates")));
                    Frequency resetFreq = document.parseFrequency(resetDatesEl.getChild("resetFrequency"));
                    if (!accrualSchedule.Frequency.Equals(resetFreq))
                    {
                        ResetSchedule.Builder resetScheduleBuilder = ResetSchedule.builder();
                        resetScheduleBuilder.resetFrequency(resetFreq);
                        floatingEl.findChild("averagingMethod").ifPresent(el =>
                        {
                            resetScheduleBuilder.resetMethod(parseAveragingMethod(el));
                        });
                        resetScheduleBuilder.businessDayAdjustment(document.parseBusinessDayAdjustments(resetDatesEl.getChild("resetDatesAdjustments")));
                        iborRateBuilder.resetPeriods(resetScheduleBuilder.build());
                    }
                });

                // stubs
                legEl.findChild("stubCalculationPeriodAmount").ifPresent(stubsEl =>
                {
                    stubsEl.findChild("initialStub").ifPresent(el =>
                    {
                        iborRateBuilder.initialStub(parseStubCalculation(el, document));
                    });
                    stubsEl.findChild("finalStub").ifPresent(el =>
                    {
                        iborRateBuilder.finalStub(parseStubCalculation(el, document));
                    });
                });
                return(iborRateBuilder.build());
            }
            else if (index is OvernightIndex)
            {
                OvernightRateCalculation.Builder overnightRateBuilder = OvernightRateCalculation.builder();
                document.validateNotPresent(floatingEl, "initialRate");   // TODO: should support this in the model
                // stubs
                legEl.findChild("stubCalculationPeriodAmount").ifPresent(stubsEl =>
                {
                    stubsEl.findChild("initialStub").ifPresent(el =>
                    {
                        checkStubForOvernightIndex(el, document, (OvernightIndex)index);
                    });
                    stubsEl.findChild("finalStub").ifPresent(el =>
                    {
                        checkStubForOvernightIndex(el, document, (OvernightIndex)index);
                    });
                });
                // day count
                overnightRateBuilder.dayCount(document.parseDayCountFraction(calcEl.getChild("dayCountFraction")));
                // index
                overnightRateBuilder.index((OvernightIndex)document.parseIndex(floatingEl));
                // accrual method
                FloatingRateName idx = FloatingRateName.of(floatingEl.getChild("floatingRateIndex").Content);
                if (idx.Type == FloatingRateType.OVERNIGHT_COMPOUNDED)
                {
                    overnightRateBuilder.accrualMethod(OvernightAccrualMethod.COMPOUNDED);
                }
                // gearing
                floatingEl.findChild("floatingRateMultiplierSchedule").ifPresent(el =>
                {
                    overnightRateBuilder.gearing(parseSchedule(el, document));
                });
                // spread
                if (floatingEl.getChildren("spreadSchedule").size() > 1)
                {
                    throw new FpmlParseException("Only one 'spreadSchedule' is supported");
                }
                floatingEl.findChild("spreadSchedule").ifPresent(el =>
                {
                    document.validateNotPresent(el, "type");
                    overnightRateBuilder.spread(parseSchedule(el, document));
                });
                // negative rates
                floatingEl.findChild("negativeInterestRateTreatment").ifPresent(el =>
                {
                    overnightRateBuilder.negativeRateMethod(parseNegativeInterestRateTreatment(el));
                });
                // rate cut off
                legEl.findChild("resetDates").ifPresent(resetDatesEl =>
                {
                    document.validateNotPresent(resetDatesEl, "initialFixingDate");
                    resetDatesEl.findChild("rateCutOffDaysOffset").ifPresent(el =>
                    {
                        Period cutOff = document.parsePeriod(el);
                        if (cutOff.toTotalMonths() != 0)
                        {
                            throw new FpmlParseException("Invalid 'rateCutOffDaysOffset' value, expected days-based period: " + cutOff);
                        }
                        overnightRateBuilder.rateCutOffDays(-cutOff.Days);
                    });
                });
                return(overnightRateBuilder.build());
            }
            else
            {
                throw new FpmlParseException("Invalid 'floatingRateIndex' type, not Ibor or Overnight");
            }
        }
Пример #3
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());
        }