コード例 #1
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());
        }
コード例 #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 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());
        }