Пример #1
0
        /// <summary>
        /// Value a caplet or floorlet under the 1 factor Hull-White model.
        /// </summary>
        public override void Value(Vector pv, Vector cash, double baseDate, double valueDate, ISACCRResult saccrResult,
                                   IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter)
        {
            int count = fCashflows.Count();

            bool forecastIsDiscount = ReferenceEquals(fForecastRate, fDiscountRate);

            // time of dfStart and dfEnd
            double tDfStart = double.NegativeInfinity;
            double tDfEnd   = double.NegativeInfinity;

            using (var cache = Vector.CacheLike(pv))
            {
                // Shared between loops
                Vector dfStart = cache.Get();
                Vector dfEnd   = cache.Get();

                VectorEngine.For(0, count, LoopDirection.Backwards, i =>
                {
                    using (var innerCache = Vector.CacheLike(pv))
                    {
                        CFFloatingInterest cashflow = fCashflows[i];

                        if (cashflow.Payment_Date < valueDate || cashflow.Payment_Date <= fCutoffDate)
                        {
                            return(LoopAction.Break);
                        }

                        Vector rate   = innerCache.Get();
                        Vector dfPay  = innerCache.Get();
                        Vector stdDev = innerCache.GetClear();
                        Vector amount = innerCache.GetClear();

                        GeneralCashflowProperties properties = fCashflows.GetCashflowProperties(i);

                        double tPay    = CalcUtils.DaysToYears(cashflow.Payment_Date - baseDate);
                        bool haveDfPay = false;
                        if (forecastIsDiscount && tPay == tDfStart)
                        {
                            dfPay.Assign(dfStart);
                            haveDfPay = true;
                        }

                        using (IntraValuationDiagnosticsHelper.StartCashflow(intraValuationDiagnosticsWriter))
                            using (var volatilitiesAtDateStore = IntraValuationDiagnosticsHelper.CreateVolatilitiesAtDateStore(intraValuationDiagnosticsWriter, pv.Count))
                            {
                                cashflow.AddPropertiesToIntraValuationDiagnostics(intraValuationDiagnosticsWriter);

                                // Standard Libor implies single reset.
                                var reset = cashflow.Resets.Single();

                                if (reset.IsKnown(baseDate))
                                {
                                    rate.Assign(reset.Known_Rate);
                                }
                                else
                                {
                                    double tValue = CalcUtils.DaysToYears(valueDate - baseDate);
                                    double tReset = CalcUtils.DaysToYears(reset.Reset_Date - baseDate);
                                    double tStart = CalcUtils.DaysToYears(reset.Rate_Start_Date - baseDate);
                                    double tEnd   = CalcUtils.DaysToYears(reset.Rate_End_Date - baseDate);

                                    // Reset is a historical or forward Libor rate.
                                    InterestRateUtils.LiborRate(rate, fForecastRate, tValue, tReset, tStart, tEnd, reset.Rate_Year_Fraction,
                                                                dfStart, ref tDfStart, dfEnd, ref tDfEnd);

                                    if (tReset > tValue)
                                    {
                                        GetStandardDeviation(stdDev, tValue, tReset, tStart, tEnd);
                                        volatilitiesAtDateStore.Add(valueDate, reset.Reset_Date, stdDev);
                                    }
                                }

                                if (!haveDfPay && forecastIsDiscount && tPay == tDfEnd)
                                {
                                    dfPay.Assign(dfEnd);
                                    haveDfPay = true;
                                }

                                // Add swaplet value
                                amount.AddProduct(properties.Swap_Multiplier, rate);

                                double tau = reset.Rate_Year_Fraction;
                                rate.Assign(1.0 + rate * tau);

                                // Add cap and floor option values.
                                AddOptionValue(amount, OptionType.Call, rate, properties.Cap_Strike, stdDev, tau, properties.Cap_Multiplier);
                                AddOptionValue(amount, OptionType.Put, rate, properties.Floor_Strike, stdDev, tau, properties.Floor_Multiplier);

                                amount.Assign(fBuySellSign * (cashflow.Fixed_Amount + cashflow.Notional * (amount + cashflow.Margin) * cashflow.Accrual_Year_Fraction));

                                IntraValuationDiagnosticsHelper.AddImpliedVolatilities(intraValuationDiagnosticsWriter, volatilitiesAtDateStore);
                                CFFixedList.RoundCashflow(amount, Cashflow_Rounding);
                                CFFixedList.UpdatePvAndCash(cashflow, baseDate, valueDate, haveDfPay ? null : fDiscountRate, null, amount,
                                                            dfPay, pv, cash, intraValuationDiagnosticsWriter);
                            }
                    }

                    return(LoopAction.Continue);
                });
            }
        }
Пример #2
0
        /// <summary>
        /// Value the deal from given base date, price factors and time grid.
        /// </summary>
        public void Value(PVProfiles pvResults, CashAccumulators cashResults, double baseDate, IInterestRate discountRate, IInterestRate forecastRate1, IInterestRate forecastRate2, IFxRate fxRate, TimeGrid timeGrid, int numScenarios)
        {
            var tgi  = new TimeGridIterator(timeGrid);
            var deal = (FloatingInterestCashflowInterpolatedDeal)Deal;

            bool   hasRate1          = deal.HasRate1();
            bool   hasRate2          = deal.HasRate2();
            double scale             = deal.Buy_Sell == BuySell.Buy ? +deal.Principal : -deal.Principal;
            double tPay              = CalcUtils.DaysToYears(fPaymentDate - baseDate);
            double tReset            = CalcUtils.DaysToYears(deal.Reset_Date - baseDate);
            double tRateStart        = CalcUtils.DaysToYears(deal.Rate_Start_Date - baseDate);
            double tRateEnd1         = hasRate1 ? CalcUtils.DaysToYears(fRate1EndDate - baseDate) : 0.0;
            double tRateEnd2         = hasRate2 ? CalcUtils.DaysToYears(fRate2EndDate - baseDate) : 0.0;
            double tRateEnd12        = tRateEnd2 - tRateEnd1;                                                                    // Time from rate 1 end date to rate 2 end date.
            double tAccrualEnd       = CalcUtils.DaysToYears(deal.Accrual_End_Date - baseDate);
            double interpCoefficient = Math.Abs(tRateEnd12) >= CalcUtils.MinTime ? (tAccrualEnd - tRateEnd1) / tRateEnd12 : 0.0; // Coefficient used to calculate interpolated rate.

            VectorEngine.For(tgi, () =>
            {
                using (var cache = Vector.Cache(numScenarios))
                {
                    Vector pv = cache.Get();

                    if (tgi.Date <= fPaymentDate && fPaymentDate > fCutoffDate)
                    {
                        Vector interpRate = cache.GetClear();
                        Vector rate1      = cache.GetClear();
                        Vector rate2      = cache.GetClear();

                        if (hasRate1)
                        {
                            if (fKnownResetRate1.HasValue)
                            {
                                rate1.Assign(fKnownResetRate1.Value);
                            }
                            else
                            {
                                InterestRateUtils.LiborRate(rate1, forecastRate1, tgi.T, tReset, tRateStart, tRateEnd1, fRate1YearFraction);
                            }
                        }

                        if (hasRate2)
                        {
                            if (fKnownResetRate2.HasValue)
                            {
                                rate2.Assign(fKnownResetRate2.Value);
                            }
                            else
                            {
                                InterestRateUtils.LiborRate(rate2, forecastRate2, tgi.T, tReset, tRateStart, tRateEnd2, fRate2YearFraction);
                            }
                        }

                        if (hasRate1 && hasRate2)
                        {
                            if (Math.Abs(tRateEnd12) >= CalcUtils.MinTime)
                            {
                                interpRate.Assign(rate1 + interpCoefficient * (rate2 - rate1));
                            }
                            else
                            {
                                interpRate.Assign(0.5 * rate1 + 0.5 * rate2);
                            }
                        }
                        else
                        {
                            interpRate.Assign(hasRate1 ? rate1 : rate2);
                        }

                        // Round the calculated rate, regardless whether the valuation date is before or after the reset date.
                        CFFloatingInterestList.RoundRateTo(deal.Interpolated_Rate_Rounding, interpRate);

                        pv.Assign(scale * (interpRate + deal.Margin) * fAccrualYearFraction);

                        CFFixedList.RoundCashflow(pv, Cashflow_Rounding);

                        if (tgi.Date < fPaymentDate)
                        {
                            pv.MultiplyBy(discountRate.Get(tgi.T, tPay));
                        }
                        else if (tgi.Date == fPaymentDate)
                        {
                            cashResults.Accumulate(fxRate, fPaymentDate, pv);
                        }
                    }
                    else
                    {
                        pv.Clear();
                    }

                    pvResults.AppendVector(tgi.Date, pv * fxRate.Get(tgi.T));
                }
            });

            // After maturity
            pvResults.Complete(timeGrid);
        }