Example #1
0
 /// <summary>
 /// Adds the cap or floor option value.
 /// </summary>
 private static void AddOptionValue(Vector amount, OptionType optionType, Vector rate, double strike, Vector stdDev, double tau, double multiplier)
 {
     if (multiplier != 0.0 && tau > 0.0)
     {
         double optionStrike = 1.0 + tau * strike;
         amount.AddProduct(multiplier / tau, PricingFunctions.BlackFunction(optionType, rate, optionStrike, stdDev));
     }
 }
        /// <summary>
        /// Value the deal on all dates within the valuation grid (vectorised).
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            var    deal             = (AverageForwardExplicitDealBase)Deal;
            double tMaturity        = CalcUtils.DaysToYears(deal.Maturity_Date - factors.BaseDate); // Discount Factor and Forward Factor times are in Act365.
            int    numSamplingDates = fSamplingTimes.Length;

            PreValue(factors);

            PVProfiles       result = valuationResults.Profile;
            CashAccumulators cash   = valuationResults.Cash;
            var tgi = new TimeGridIterator(fT);

            using (var pricerCache = Vector.Cache(factors.NumScenarios))
            {
                double historicalObservations;
                double futureObservations;
                int    currentDateCount;
                Vector realisedSum  = pricerCache.GetClear();             // sum to value date.
                Vector forecastSum  = pricerCache.Get();
                Vector spotPrice    = pricerCache.Get();
                Vector forwardPrice = pricerCache.Get();

                double tSpotPrice = double.NegativeInfinity;
                GetForwardPrice(0.0, deal.Tenor, true, ref tSpotPrice, spotPrice, forwardPrice);
                fSamplingData.GetInitialSum(null, factors.BaseDate, forwardPrice, realisedSum, out historicalObservations, out futureObservations, out currentDateCount);

                VectorEngine.For(tgi, () =>
                {
                    using (var cache = Vector.Cache(factors.NumScenarios))
                    {
                        Vector overallAverage = cache.Get();
                        Vector value          = cache.Get();
                        Vector payoffRate     = cache.Get();

                        UpdateSum(tgi.Date, realisedSum, ref tSpotPrice, spotPrice, ref historicalObservations, ref futureObservations, ref currentDateCount);
                        forecastSum.Clear();

                        // all the sampling dates that are in the future (compared to our valuation date)
                        VectorEngine.For(currentDateCount, numSamplingDates, i =>
                        {
                            GetForwardPrice(tgi.T, fSamplingTimesPlusTenor[i], false, ref tSpotPrice, spotPrice,
                                            forwardPrice);
                            forecastSum.AddProduct(fSamplingData[i].Weight, forwardPrice);

                            return(LoopAction.Continue);
                        });

                        forecastSum.MultiplyBy(spotPrice);
                        double totalWeight = historicalObservations + futureObservations;
                        if (totalWeight > 0.0)
                        {
                            overallAverage.Assign((realisedSum + forecastSum) / totalWeight);
                        }
                        else
                        {
                            overallAverage.Clear();
                        }

                        PayoffRate(payoffRate, overallAverage, ref tSpotPrice, spotPrice, tgi.T, tMaturity);
                        value.Assign(fScale * fDiscountRate.Get(tgi.T, tMaturity) * payoffRate);

                        if (tgi.Date == deal.Maturity_Date)
                        {
                            cash.Accumulate(fPayoffFxRate, tgi.Date, value);
                        }

                        result.AppendVector(tgi.Date, value * fPayoffFxRate.Get(tgi.T));
                    }
                });

                result.Complete(fT);
            }
        }
Example #3
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);
                });
            }
        }
Example #4
0
        /// <summary>
        /// Calculate valuation profiles.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            PreValue(factors);

            TimeGridIterator tgi             = new TimeGridIterator(fT);
            PVProfiles       result          = valuationResults.Profile;
            CashAccumulators cashAccumulator = valuationResults.Cash;
            double           baseDate        = factors.BaseDate;

            CallableStructuredDeal deal = (CallableStructuredDeal)fDeal;

            int buySellSign = deal.Buy_Sell == BuySell.Buy ? +1 : -1;
            int callPutSign = deal.Option_Type == OptionType.Call ? 1 : -1;

            InterestRateOptionPricer optionPricer = CreateOptionPricer(factors);

            CalcUtils.CreateDealProfilesIfRequired(valuationResults, fItems, factors);

            bool needRating = Respect_Default == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer);

            using (var cache = Vector.Cache(factors.NumScenarios))
            {
                Vector exercised      = cache.GetClear(); // vector taking value 0 or 1 indicating exercise before tgi.date
                Vector exercisedToday = cache.Get();      // vector taking value 0 or 1 indicating exercise at tgi.date

                Vector optionPv = cache.Get();
                Vector pv       = cache.Get();
                Vector cash     = cache.Get();
                Vector settlementDateAtExercise = cache.GetClear();
                Vector defaultDate = needRating ? cache.Get(CalcUtils.DateTimeMaxValueAsDouble) : null;

                var defaultedBeforeBaseDate = needRating &&
                                              CreditRating.DefaultedBeforeBaseDate(fCreditRating, baseDate);

                while (tgi.Next())
                {
                    if (defaultedBeforeBaseDate)
                    {
                        pv.Clear();
                        result.AppendVector(tgi.Date, pv);
                        break;
                    }

                    if (needRating)
                    {
                        UpdateDefaultDate(fCreditRating, tgi.Date, tgi.T, defaultDate);
                    }

                    double val;
                    bool   allExercised = exercised.AllElementsTheSame(out val) && val == 1.0;

                    if (deal.Settlement_Style == SettlementType2.Physical)
                    {
                        // Calculate value of option (option value is zero after last exercise date)
                        if (!allExercised)
                        {
                            optionPricer.Value(baseDate, tgi.Date, optionPv, exercised, exercisedToday, settlementDateAtExercise, defaultDate);
                        }

                        // Calculate value of underlying cashflows after settlementDateAtExercise
                        pv.Clear();
                        cash.Clear();
                        InterestRateOptionPricer.ValueDeals(fItems, pv, cash, baseDate, tgi.Date, settlementDateAtExercise, defaultDate, fDiscountRate, fForecastRate, fRepoRate, fInterestRateVol, fInterestYieldVol, fSurvivalProb, fRecoveryRate);
                        pv.MultiplyBy(callPutSign);
                        cash.MultiplyBy(callPutSign);

                        if (!allExercised)
                        {
                            // If exercised today the cashflow is the value of the option minus the value of the physically settled part
                            // Else if already exercised, cash is the unnderlying cash.
                            // Else (before exercise) there is no cash.
                            cash.AssignConditional(exercisedToday, optionPv - pv, exercised * cash);

                            // If already exercised, pv is the unnderlying pv.
                            // Else (before exercise or exercised today), pv is the option pv.
                            pv.AssignConditional(exercised, pv, optionPv);
                            pv.AssignConditional(exercisedToday, optionPv, pv);
                        }
                    }
                    else
                    {
                        if (allExercised)
                        {
                            // Already exercised on all scenarios
                            result.AppendZeroVector(tgi.Date);
                            continue;
                        }

                        if (deal.Settlement_Style == SettlementType2.Cash)
                        {
                            // Calculate value of option
                            optionPricer.Value(baseDate, tgi.Date, pv, exercised, exercisedToday, settlementDateAtExercise, defaultDate);

                            // If exercised today then option pv is settled today, otherwise there is no cash
                            cash.AssignProduct(pv, exercisedToday);
                        }
                        else // Embedded option (callable or puttable)
                        {
                            // Calculate underlying value
                            pv.Clear();
                            cash.Clear();
                            InterestRateOptionPricer.ValueDeals(fItems, pv, cash, baseDate, tgi.Date, null, defaultDate, fDiscountRate, fForecastRate, fRepoRate, fInterestRateVol, fInterestYieldVol, fSurvivalProb, fRecoveryRate);

                            // Calculate value of option
                            optionPricer.Value(baseDate, tgi.Date, optionPv, exercised, exercisedToday, settlementDateAtExercise, defaultDate);

                            // Add or subtract value of embedded option
                            pv.AddProduct(-callPutSign, optionPv);

                            // Option payoff is Max(callPutSign * (underlyingPv - accruedInterest - discountedFee), 0)
                            // Callable/puttable payoff on exercise is
                            // underlyingPv - callPutSign * (callPutSign * (underlyingPv - accruedInterest - discountedFee))
                            // = accruedInterest + discountedFee

                            // Set pv and cash to zero if already exercised.
                            // If exercised today then the pv is settled today.
                            pv.AssignConditional(exercised, exercisedToday * pv, pv);
                            cash.AssignConditional(exercised, exercisedToday * pv, cash);
                        }
                    }

                    pv.MultiplyBy(buySellSign);
                    cash.MultiplyBy(buySellSign);
                    result.AppendVector(tgi.Date, fFxRate.Get(tgi.T) * pv);
                    cashAccumulator.Accumulate(fFxRate, tgi.Date, cash);
                }
            }

            result.Complete(fT);
        }