Beispiel #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);
                });
            }
        }
Beispiel #2
0
        /// <summary>
        /// Fills the arrays of coupon, pay date discount factors, standard deviations and coefficient by running through the cashflows
        /// </summary>
        private void GetSwapQuantities(Vector[] coupon, Vector[] stdDev, Vector[] coefficient, Vector[] df, double tValue, double tExpiry, double baseDate, Vector dfTExpiry)
        {
            int                count             = coupon.Length;
            double             tLastEnd          = double.NegativeInfinity;
            double             tLastPay          = double.NegativeInfinity;
            int                floatIndex        = 0;
            CFFloatingInterest cfFloating        = fFloatCashflowList[floatIndex];
            TDate              floatingStartDate = cfFloating.Resets[0].Rate_Start_Date;

            // We will minimise the number of discount factors we get.
            bool[] haveDF = new bool[count];

            using (var cache = Vector.CacheLike(dfTExpiry))
            {
                Vector bTExpiry = cache.Get();
                Vector rootZeta = cache.Get();
                Vector bT       = cache.Get();
                Vector dfTStart = cache.Get();
                Vector dfTPay   = cache.Get();
                Vector ffTStart = cache.Get();
                Vector ffTEnd   = cache.Get();
                Vector beta     = cache.Get();

                fModelParameters.GetB(bTExpiry, tValue, tExpiry);
                fModelParameters.GetZeta(rootZeta, tValue, tExpiry);
                rootZeta.AssignSqrt(rootZeta);

                // Loop over copuons calculating useful quantities.
                VectorEngine.For(0, count, i =>
                {
                    double tDf = CalcUtils.DaysToYears(fDates[i] - baseDate);

                    // if this date is associated with a floating start date include beta contribution
                    if (fDates[i] == floatingStartDate)
                    {
                        var floatingEndDate = cfFloating.Resets[0].Rate_End_Date;
                        var paymentDate     = cfFloating.Payment_Date;

                        double tStart = CalcUtils.DaysToYears(floatingStartDate - baseDate);
                        double tEnd   = CalcUtils.DaysToYears(floatingEndDate - baseDate);
                        double tPay   = CalcUtils.DaysToYears(paymentDate - baseDate);

                        GetDiscountAndForecastFactors(dfTStart, dfTPay, ffTStart, ffTEnd, tValue, tStart, tEnd, tPay, tLastEnd, tLastPay);

                        beta.Assign(dfTPay * ffTStart / (dfTStart * ffTEnd));

                        double rateYearFraction  = cfFloating.Resets[0].Rate_Year_Fraction;
                        double yearFractionRatio = (rateYearFraction < CalcUtils.TINY) ? 1.0 : cfFloating.Accrual_Year_Fraction / rateYearFraction;
                        coupon[i].Assign(-beta * yearFractionRatio * cfFloating.Notional);

                        // Store new discount factors.
                        int payIndex = fDates.IndexOf(paymentDate);
                        df[payIndex].Assign(dfTPay);
                        haveDF[payIndex] = true;

                        if (!haveDF[i])
                        {
                            df[i].Assign(dfTStart);
                            haveDF[i] = true;
                        }

                        // Update for next pass
                        tLastEnd = tEnd;
                        tLastPay = tPay;
                        floatIndex++;

                        if (floatIndex < fFloatCashflowList.Count())
                        {
                            cfFloating        = fFloatCashflowList[floatIndex];
                            floatingStartDate = cfFloating.Resets[0].Rate_Start_Date;
                        }
                        else
                        {
                            floatingStartDate = double.PositiveInfinity;
                        }
                    }

                    // Work out coupon, stdDev, coefficient and dfTPay
                    coupon[i].Add(fFloatingCouponWeight[i]);

                    if (fSwapRate != null)
                    {
                        coupon[i].Add(fSwapRate * fFixedCouponWeight[i]);
                    }
                    else
                    {
                        coupon[i].Add(fFixedCouponRate[i] * fFixedCouponWeight[i]);
                    }

                    fModelParameters.GetB(bT, tValue, tDf);
                    stdDev[i].Assign((bT - bTExpiry) * rootZeta);

                    // Make sure we get all the discount factors.
                    if (!haveDF[i])
                    {
                        fDiscountRate.GetValue(df[i], tValue, tDf);
                        haveDF[i] = true;
                    }

                    // Performs coefficient[i] = dfTPay[i] / dfTExpiry * Exp(-0.5 * stdDev[i] * stdDev[i])
                    coefficient[i].Assign(CalcUtils.SafeExpMultiply(-0.5 * stdDev[i] * stdDev[i], df[i] / dfTExpiry));

                    return(LoopAction.Continue);
                });
            }
        }