예제 #1
0
        private static void CalculateForecastPaymentAmount(Calculation calculation,
                                                           FloatingRateCalculation floatingRateCalculation,
                                                           PaymentCalculationPeriod paymentCalculationPeriod,
                                                           IRateCurve forecastCurve,
                                                           IRateCurve discountCurve,
                                                           DateTime valuationDate)
        {
            var      amountAccruedPerPaymentPeriod = new List <Money>();
            decimal  interestFromPreviousPeriods   = 0;
            Notional notionalSchedule = XsdClassesFieldResolver.CalculationGetNotionalSchedule(calculation);
            Currency notionalCurrency = notionalSchedule.notionalStepSchedule.currency;

            //  Cashflows
            //
            foreach (CalculationPeriod calculationPeriod in XsdClassesFieldResolver.GetPaymentCalculationPeriodCalculationPeriodArray(paymentCalculationPeriod))
            {
                decimal notional  = XsdClassesFieldResolver.CalculationPeriodGetNotionalAmount(calculationPeriod);
                decimal finalRate = 0.0m;
                //  If has a fixed rate (fixed rate coupon)
                //
                if (XsdClassesFieldResolver.CalculationPeriodHasFixedRate(calculationPeriod))
                {
                    finalRate = XsdClassesFieldResolver.CalculationPeriodGetFixedRate(calculationPeriod);
                }
                else if (XsdClassesFieldResolver.CalculationPeriodHasFloatingRateDefinition(calculationPeriod))
                {
                    if (null != forecastCurve)
                    {
                        FloatingRateDefinition floatingRateDefinition = XsdClassesFieldResolver.CalculationPeriodGetFloatingRateDefinition(calculationPeriod);
                        // Apply spread from schedule if it hasn't been specified yet.
                        //
                        if (!floatingRateDefinition.spreadSpecified)
                        {
                            floatingRateDefinition.spread          = floatingRateCalculation.spreadSchedule[0].initialValue;
                            floatingRateDefinition.spreadSpecified = true;
                        }
                        ForecastRateHelper.UpdateFloatingRateDefinition(floatingRateDefinition, floatingRateCalculation,
                                                                        calculation.dayCountFraction,
                                                                        calculationPeriod,
                                                                        forecastCurve);
                        calculationPeriod.Item1 = floatingRateDefinition;
                        decimal calculatedRate = floatingRateDefinition.calculatedRate;
                        //  final rate after application of Cap/Floor  rates
                        //
                        finalRate = calculatedRate;
                        //  If has a Cap rate, finalRate = MAX(0, FinalRate - CapRate)
                        //
                        if (null != floatingRateDefinition.capRate)
                        {
                            Strike strike = floatingRateDefinition.capRate[0];
                            finalRate = System.Math.Max(0, finalRate - strike.strikeRate);
                        }
                        //  If has a Floor rate, finalRate = MAX(0, FloorRate - FinalRate)
                        //
                        if (null != floatingRateDefinition.floorRate)
                        {
                            Strike strike = floatingRateDefinition.floorRate[0];
                            finalRate = System.Math.Max(0, strike.strikeRate - finalRate);
                        }
                    }
                }
                else
                {
                    throw new System.Exception("CalculationPeriod has neither fixedRate nor floatngRateDefinition.");
                }
                // Compound interest accrued during previos calculation periods in this payment period.
                //
                decimal notionalAdjustedForInterestFromPreviousPeriods = notional + interestFromPreviousPeriods;
                if (calculation.discounting == null)
                {
                    interestFromPreviousPeriods = notionalAdjustedForInterestFromPreviousPeriods * finalRate * calculationPeriod.dayCountYearFraction;
                }
                else if (calculation.discounting.discountingType == DiscountingTypeEnum.FRA || calculation.discounting.discountingType == DiscountingTypeEnum.Standard)
                {
                    interestFromPreviousPeriods = notionalAdjustedForInterestFromPreviousPeriods * (1.0m - 1.0m / (1.0m + finalRate * calculationPeriod.dayCountYearFraction));
                }
                else
                {
                    throw new NotSupportedException("The specified discountingType is not supported.");
                }
                Money amountAccruedPerCalculationPeriod = MoneyHelper.GetAmount(interestFromPreviousPeriods, notionalCurrency);
                amountAccruedPerPaymentPeriod.Add(amountAccruedPerCalculationPeriod);
            }
            paymentCalculationPeriod.forecastPaymentAmount   = MoneyHelper.Sum(amountAccruedPerPaymentPeriod);
            paymentCalculationPeriod.discountFactor          = (decimal)discountCurve.GetDiscountFactor(valuationDate, paymentCalculationPeriod.adjustedPaymentDate);
            paymentCalculationPeriod.discountFactorSpecified = true;
            paymentCalculationPeriod.presentValueAmount      = MoneyHelper.Mul(paymentCalculationPeriod.forecastPaymentAmount, paymentCalculationPeriod.discountFactor);
        }