Example #1
0
        /// <summary>
        /// Calculate valuation profiles.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            base.Value(valuationResults, factors, baseTimes);

            var accruedResults = valuationResults.Results <AccruedInterest>();

            if (accruedResults == null)
            {
                return;
            }

            using (var cache = Vector.Cache(factors.NumScenarios))
            {
                Vector accruedInterest = cache.Get();
                var    deal            = (CFEquityFloatingInterestListDeal)Deal;
                var    tgi             = new TimeGridIterator(fT);

                var equityParams = new EquityCashflowParams((EquityPrice)fEquity, (EquityPriceVol)fEquityVol, fEquityFXRate, fEquityPayoffFXRate, deal.GetEquityPayoffType(), fEquityQuantoCompo, null, null);

                while (tgi.Next())
                {
                    deal.Cashflows.CalculateAccrual(accruedInterest, equityParams, factors.BaseDate, tgi.Date, accruedResults.AccrueFromToday, deal.GetHolidayCalendar(), deal.Accrual_Day_Count, fForecastRate, fFxRate);
                    accruedResults.SetValue(tgi.Date, fBuySellSign * accruedInterest);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Calculate valuation profiles.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            base.Value(valuationResults, factors, baseTimes);

            var deal = (CFFloatingInterestListDeal)Deal;

            CalculateMetrics(valuationResults, factors, deal);

            var accruedResults = valuationResults.Results <AccruedInterest>();

            if (accruedResults == null)
            {
                return;
            }

            using (var cache = Vector.Cache(factors.NumScenarios))
            {
                Vector accruedInterest = cache.Get();
                var    tgi             = new TimeGridIterator(fT);

                VectorEngine.For(tgi, () =>
                {
                    fCashflows.CalculateAccrual(accruedInterest, factors.BaseDate, tgi.Date, accruedResults.AccrueFromToday, deal.GetHolidayCalendar(), fForecastRate);
                    accruedResults.SetValue(tgi.Date, fBuySellSign * accruedInterest);
                });
            }
        }
Example #3
0
        /// <summary>
        /// Calculate valuation metrics requested by the Base Valuation calculation.
        /// </summary>
        private void CalculateMetrics(ValuationResults valuationResults, PriceFactorList factors, CFFixedInterestListDeal deal)
        {
            var results = valuationResults.Results <ValuationMetrics>();

            if (results == null)
            {
                return;
            }

            if (results.IsMetricRequested(ValuationMetricConstants.Duration))
            {
                using (var cache = Vector.Cache(factors.NumScenarios))
                {
                    Vector duration       = cache.GetClear();
                    Vector settlementDate = cache.Get(deal.Settlement_Date);
                    deal.Cashflows.Duration(duration, factors.BaseDate, factors.BaseDate, settlementDate, fDiscountRate, fCutoffDate);
                    results.SetMetricValue(ValuationMetricConstants.Duration, new ValuationId(this), duration[0]);
                }
            }

            if (results.IsMetricRequested(ValuationMetricConstants.AccruedInterest))
            {
                double?parameter       = results.GetMetricParameter(ValuationMetricParameterConstants.AccrueFromToday);
                bool   accrueFromToday = parameter.HasValue && parameter.Value == 1.0;
                double accruedInterest = deal.Cashflows.CalculateAccrual(factors.BaseDate, accrueFromToday, deal.GetHolidayCalendar());
                double buySellSign     = deal.Buy_Sell == BuySell.Buy ? 1.0 : -1.0;
                results.SetMetricValue(ValuationMetricConstants.AccruedInterest, new ValuationId(this), buySellSign * accruedInterest);
            }
        }
Example #4
0
        /// <summary>
        /// Calculate valuation metrics requested by the Base Valuation calculation.
        /// </summary>
        private void CalculateMetrics(ValuationResults valuationResults, PriceFactorList factors, CFFloatingInterestListDeal deal)
        {
            var results = valuationResults.Results <ValuationMetrics>();

            if (results == null)
            {
                return;
            }

            if (results.IsMetricRequested(ValuationMetricConstants.AccruedInterest))
            {
                using (var cache = Vector.Cache(factors.NumScenarios))
                {
                    double?parameter       = results.GetMetricParameter(ValuationMetricParameterConstants.AccrueFromToday);
                    bool   accrueFromToday = parameter.HasValue && parameter.Value == 1.0;
                    Vector accruedInterest = cache.GetClear();
                    fCashflows.CalculateAccrual(accruedInterest, factors.BaseDate, factors.BaseDate, accrueFromToday, deal.AccrualHolidayCalendar(), fForecastRate);
                    double buySellSign = deal.Buy_Sell == BuySell.Buy ? 1.0 : -1.0;
                    results.SetMetricValue(ValuationMetricConstants.AccruedInterest, new ValuationId(this), buySellSign * accruedInterest[0]);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Calculate valuation profiles.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            base.Value(valuationResults, factors, baseTimes);

            var deal = (CFFixedInterestListDeal)Deal;

            CalculateMetrics(valuationResults, factors, deal);

            var accruedResults = valuationResults.Results <AccruedInterest>();

            if (accruedResults == null)
            {
                return;
            }

            var tgi = new TimeGridIterator(fT);

            while (tgi.Next())
            {
                double accruedInterest = deal.Cashflows.CalculateAccrual(tgi.Date, accruedResults.AccrueFromToday, fDeal.GetHolidayCalendar());
                accruedResults.SetValue(tgi.Date, fBuySellSign * accruedInterest);
            }
        }
        /// <summary>
        /// Value the deal.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            PreValue(factors);

            CallableBondForward deal = (CallableBondForward)Deal;

            double baseDate       = factors.BaseDate;
            double settlementDate = deal.Settlement_Date;
            double tSettle        = CalcUtils.DaysToYears(settlementDate - baseDate);

            TimeGridIterator tgi = new TimeGridIterator(fT);

            PVProfiles      result  = valuationResults.Profile;
            AccruedInterest accrued = valuationResults.Results <AccruedInterest>();

            var intraValuationDiagnosticsWriter =
                IntraValuationDiagnosticsWriterFactory.GetOrCreate(IntraValuationDiagnosticsLevel.None);

            using (var outerCache = Vector.Cache(factors.NumScenarios))
            {
                // SwapOptionPricerObject is null when there are no valid exercise dates.
                SwaptionPricer.WorkingArrays arrays = fSwaptionPricer != null?fSwaptionPricer.PreValue(fDiscountRate, outerCache) : null;

                Vector tExercise = outerCache.Get(double.PositiveInfinity);                    // time of exercise
                int    numberScenariosExercised = 0;

                Vector defaultDate = fCreditRating != null?outerCache.Get(CalcUtils.DateTimeMaxValueAsDouble) : null;

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

                VectorEngine.For(tgi, () =>
                {
                    using (var cache = Vector.Cache(factors.NumScenarios))
                    {
                        Vector cash = cache.GetClear();
                        Vector pv   = cache.GetClear();

                        if (defaultedBeforeBaseDate || numberScenariosExercised == factors.NumScenarios)
                        {
                            // already defaulted before base date or All scenarios exercised
                            result.AppendVector(tgi.Date, pv);
                            return(LoopAction.Break);
                        }
                        else
                        {
                            // Value of the bond cashflows after the settlement.
                            fCashflowList.Value(pv, cash, null, baseDate, tgi.Date, null, fDiscountRate, fSurvivalProb, null,
                                                null, intraValuationDiagnosticsWriter, 0.0);

                            // Add the value of the principal and amortization cashflows.
                            fFixedCashflowList.Value(pv, cash, baseDate, tgi.Date, null, fDiscountRate, fSurvivalProb,
                                                     intraValuationDiagnosticsWriter, 0.0);

                            if (fSurvivalProb != null)
                            {
                                fRecoveryList.Value(pv, baseDate, tgi.Date, fDiscountRate, fSurvivalProb,
                                                    intraValuationDiagnosticsWriter);
                            }

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

                            // Add/subtract value of option
                            if (fSwaptionPricer != null)
                            {
                                using (var innerCache = Vector.Cache(factors.NumScenarios))
                                {
                                    Vector optionPv       = innerCache.Get();
                                    Vector exerciseStrike = innerCache.GetClear();    // strike of underlying at exercise
                                    Vector exerciseFee    = innerCache.GetClear();    // fee paid on exercise
                                    fSwaptionPricer.Value(optionPv, tgi.T, fDiscountRate, fInterestYieldVol, fSurvivalProb, arrays, tExercise,
                                                          exerciseStrike, exerciseFee, Early_Exercise_Today == YesNo.Yes, ref numberScenariosExercised);

                                    // Ignore optionality if in default.
                                    if (fNeedsCreditRating)
                                    {
                                        optionPv.AssignConditional(defaultDate > tgi.Date, optionPv, 0.0);
                                    }

                                    pv.Add(optionPv);
                                }
                            }

                            if (tgi.Date < settlementDate)
                            {
                                // Forward deal before settlement date
                                if (deal.Is_Defaultable == YesNo.No)
                                {
                                    pv.Assign((pv / fDiscountRate.Get(tgi.T, tSettle) - fSettlementAmount) * fRepoRate.Get(tgi.T, tSettle));
                                }
                                else
                                {
                                    pv.Subtract((fSettlementAmount - fAccrued) * fRepoRate.Get(tgi.T, tSettle) + fAccrued * fDiscountRate.Get(tgi.T, tSettle));   // discount accrued with bond rate; accrued interest must cancel
                                }
                            }
                            else if (tgi.Date == settlementDate)
                            {
                                // Forward deal at settlement date
                                pv.Subtract(fSettlementAmount);
                                cash.Subtract(fSettlementAmount);
                            }

                            if (deal.IsForward())
                            {
                                // Cash settled forward
                                if (tgi.Date == settlementDate)
                                {
                                    cash.Assign(pv);
                                }
                                else
                                {
                                    cash.Clear();
                                }
                            }
                            else if (tgi.Date >= settlementDate)
                            {
                                using (var innerCache = Vector.Cache(factors.NumScenarios))
                                {
                                    Vector afterExercise  = innerCache.Get(tExercise < tgi.T);
                                    Vector beforeExercise = innerCache.Get(tExercise > tgi.T);

                                    Vector exercisedToday = innerCache.GetClear();
                                    exercisedToday.Assign(afterExercise.Or(beforeExercise));
                                    exercisedToday.Assign(!exercisedToday);

                                    double callAmount = deal.Notional * Percentage.PercentagePoint * deal.Call_Prices.GetRate(tgi.Date);

                                    // Before exercise: pv is bondPV + optionPv and cash is bondCash.
                                    // On exercise: pv and cash are bondCash + callAmount.
                                    // After exercise: pv and cash are zero.
                                    cash.AssignConditional(exercisedToday, cash + callAmount, beforeExercise * cash);
                                    pv.AssignConditional(exercisedToday, cash, beforeExercise * pv);
                                }
                            }

                            // Apply leg sign to results
                            int buySellSign = deal.Buy_Sell == BuySell.Buy ? +1 : -1;
                            ApplySign(pv, cash, buySellSign);

                            if (fNeedsCreditRating)
                            {
                                Vector beforeExercise      = cache.Get(tExercise > tgi.T);
                                Vector modifiedDefaultDate = cache.Get();

                                // If default occurs after the call option has been exercise, default is irrelevant.
                                // If default occurs on the same date that the call option is exercised, the assumption
                                // is that the bond has been paid back in full, otherwise it wouldn''t be considered exercised.
                                modifiedDefaultDate.AssignConditional(beforeExercise, defaultDate, double.PositiveInfinity);
                                GetDefaultValue(baseDate, tgi.Date, modifiedDefaultDate, fRecoveryRate, pv, cash);
                            }

                            valuationResults.Cash.Accumulate(fFxRate, tgi.Date, cash);
                            result.AppendVector(tgi.Date, pv * fFxRate.Get(tgi.T));

                            if (accrued != null)
                            {
                                accrued.SetValue(tgi.Date, fCashflowList.CalculateAccrual(tgi.Date, accrued.AccrueFromToday, fDeal.GetHolidayCalendar()) * buySellSign);
                            }
                        }
                    }

                    return(LoopAction.Continue);
                });
            }

            result.Complete(fT);
        }
        /// <summary>
        /// Aggregate the valuation profile onto a set of result curves to support result partitioning.
        /// </summary>
        protected override void ProcessResults(ValuationResults valResults, DealPartitionAssociations assoc, PriceFactorList factors, BaseTimeGrid baseTimes, ValuationOptions options, int partition)
        {
            var pvProfiles          = valResults.Results <PVProfiles>();
            var addOnProfiles       = valResults.Results <AddOnProfiles>();
            var positiveMtmProfiles = valResults.Results <PositiveMtmProfiles>();

            Debug.Assert(addOnProfiles != null, "No Add-On profiles. Cannot proceed with valuation.");
            Debug.Assert(positiveMtmProfiles != null, "No Positive mtM profiles. Cannot proceed with valuation.");

            fT = Deal.ValuationGrid(factors, baseTimes, Deal.EndDate());
            var tgi = new TimeGridIterator(fT);

            var nettedExposure     = new PVProfiles(factors.NumScenarios);
            var collateralExposure = new PVProfiles(factors.NumScenarios);

            var addOnsProfile  = new PVProfiles(factors.NumScenarios);
            var mtmTermProfile = new PVProfiles(factors.NumScenarios);

            DealBaselNettingCollateralSet nettingSetDeal = Deal as DealBaselNettingCollateralSet;

            bool collateralised = nettingSetDeal.Collateralised == YesNo.Yes;

            using (var cache = Vector.Cache(factors.NumScenarios))
            {
                Vector sumMtm         = cache.Get();
                Vector sumPositiveMtm = cache.Get();
                Vector addOns         = cache.Get();
                Vector netGrossRatio  = cache.Get();
                Vector value          = cache.Get();
                Vector term1          = cache.Get();
                Vector term2          = cache.Get();

                // Collateral related vectors.
                Vector mtmTermStart = cache.Get();
                Vector addOnHp      = cache.Get();

                // Loop to get the netting set exposure.
                while (tgi.Next())
                {
                    sumMtm.Clear();
                    sumPositiveMtm.Clear();
                    addOns.Clear();
                    value.Clear();

                    double date = tgi.Date;

                    // For MtM Plus Add-On deals PV profiles represents the sum of the MtM profile and Add-On profile.
                    // Subtract the Add-On profile to recover the MtM profile before flooring.
                    sumMtm.Assign(VectorMath.Max(pvProfiles[date] - addOnProfiles[date], 0.0));

                    addOns.Assign(addOnProfiles[date]);
                    sumPositiveMtm.Assign(positiveMtmProfiles[date]);

                    netGrossRatio.AssignConditional(sumPositiveMtm > 0, sumMtm / sumPositiveMtm, 0.0);

                    netGrossRatio.MultiplyBy(this.fNetGrossRatioCorrelation);
                    netGrossRatio.Add(1 - this.fNetGrossRatioCorrelation);

                    term2.AssignProduct(addOns, netGrossRatio);

                    term1.Assign(VectorMath.Max(sumMtm, 0.0));

                    value.AssignSum(term1, term2);

                    nettedExposure.AppendVector(date, value);

                    if (collateralised)
                    {
                        mtmTermProfile.AppendVector(date, term1);
                        addOnsProfile.AppendVector(date, term2);
                    }
                }

                nettedExposure.Complete(this.fT);

                var exposureResults = valResults.Results <Exposure>();
                if (exposureResults != null)
                {
                    exposureResults.Assign(nettedExposure);
                }

                // Collateral cases.
                if (collateralised)
                {
                    mtmTermProfile.Complete(this.fT);
                    addOnsProfile.Complete(this.fT);

                    double date = factors.BaseDate;

                    mtmTermProfile.GetValue(mtmTermStart, date);
                    addOnsProfile.GetValue(addOnHp, date + nettingSetDeal.Holding_Period);

                    // Assume we have post haircut collateral.
                    double collateral = nettingSetDeal.Balance;
                    double threshold  = nettingSetDeal.Threshold;

                    tgi.Reset();

                    // Loop to get the netting set exposure.
                    while (tgi.Next())
                    {
                        bool inHoldingPeriod = tgi.T < CalcUtils.DaysToYears(nettingSetDeal.Holding_Period);

                        CollateralBasel3(mtmTermStart, collateral, addOnHp, threshold, inHoldingPeriod, tgi.Date,
                                         nettedExposure,
                                         collateralExposure);
                    }

                    collateralExposure.Complete(this.fT);

                    if (exposureResults != null)
                    {
                        exposureResults.Assign(collateralExposure);
                    }
                }
            }

            if (options.PartitionCollateralMode != PartitionCollateralMode.Suppress_Collateral_And_Flooring || partition < options.NumTotalPartitions)
            {
                valResults.FloorResult(assoc.AggregationMode, options);
            }

            CollateralPlugIn.CollateralBalancesContainer coProfiles = valResults.Results <CollateralPlugIn.CollateralBalancesContainer>();

            // Store collateral information according to diagnostic collection rules.
            if (coProfiles != null)
            {
                coProfiles.StoreInformation(this);
            }
        }
        /// <summary>
        /// Calculate valuation profiles.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            PreValue(factors);

            var    result          = valuationResults.Profile;
            var    cashAccumulator = valuationResults.Cash;
            var    accruedResults  = valuationResults.Results <AccruedInterest>();
            var    deal            = (IInflationCashflowListDeal)Deal;
            double sign            = deal.Buy_Sell == BuySell.Buy ? 1.0 : -1.0;
            var    cashflows       = deal.GetCashflows();
            var    calendar        = deal.GetHolidayCalendar();
            double baseDate        = factors.BaseDate;
            var    tgi             = new TimeGridIterator(fT);

            CalculateMetrics(valuationResults, factors, deal);

            using (IntraValuationDiagnosticsHelper.StartDeal(fIntraValuationDiagnosticsWriter, fDeal))
            {
                using (var cache = Vector.Cache(factors.NumScenarios))
                {
                    Vector defaultDate = null;

                    if (!fIsDefaultNever)
                    {
                        defaultDate = fCreditRating != null?cache.Get(CalcUtils.DateTimeMaxValueAsDouble) : null;
                    }

                    Vector pv              = cache.GetClear();
                    Vector cash            = cashAccumulator.Ignore ? null : cache.Get();
                    Vector accruedInterest = cache.GetClear();

                    VectorEngine.For(tgi, () =>
                    {
                        if (!fIsDefaultNever && CreditRating.DefaultedBeforeBaseDate(fCreditRating, baseDate))
                        {
                            result.AppendVector(tgi.Date, pv);
                            return(LoopAction.Break);
                        }

                        using (IntraValuationDiagnosticsHelper.StartCashflowsOnDate(fIntraValuationDiagnosticsWriter, tgi.Date))
                        {
                            using (IntraValuationDiagnosticsHelper.StartCashflows(fIntraValuationDiagnosticsWriter, fFxRate, tgi.T, fDeal))
                            {
                                cashflows.Value(pv, cash, baseDate, tgi.Date, deal.Settlement_Date, fInflationRate, fIndexVolatility,
                                                fDiscountRate, fRepoRate, fSurvivalProb, sign, fIntraValuationDiagnosticsWriter);
                                IntraValuationDiagnosticsHelper.AddCashflowsPV(fIntraValuationDiagnosticsWriter, pv);

                                if (fRecoveryCashflowList != null && fRecoveryCashflowList.Items.Count > 0)
                                {
                                    fRecoveryCashflowList.Value(pv, cash, baseDate, tgi.Date, deal.Settlement_Date, fDiscountRate, fRepoRate, fInflationRate, fSurvivalProb, sign);
                                }

                                // Temporary fix up to avoid calculating default when we know the model doesn't support default
                                if (!fIsDefaultNever)
                                {
                                    UpdateDefaultDate(fCreditRating, tgi.Date, tgi.T, defaultDate);
                                    GetDefaultValue(baseDate, tgi.Date, defaultDate, fInflationRate, fIndexVolatility, fRepoRate, pv, cash);
                                }

                                result.AppendVector(tgi.Date, fFxRate.Get(tgi.T) * pv);

                                if (cash != null)
                                {
                                    cashAccumulator.Accumulate(fFxRate, tgi.Date, cash);
                                }

                                if (accruedResults != null)
                                {
                                    cashflows.CalculateAccrual(accruedInterest, baseDate, tgi.Date, accruedResults.AccrueFromToday, calendar, fInflationRate, fIndexVolatility, sign);
                                    accruedResults.SetValue(tgi.Date, accruedInterest);
                                }
                                else if (fIntraValuationDiagnosticsWriter.Level > IntraValuationDiagnosticsLevel.None)
                                {
                                    cashflows.CalculateAccrual(accruedInterest, baseDate, tgi.Date, false, calendar, fInflationRate, fIndexVolatility, sign);
                                }

                                IntraValuationDiagnosticsHelper.AddCashflowsAccruedInterest(fIntraValuationDiagnosticsWriter, accruedInterest);
                            }
                        }

                        return(LoopAction.Continue);
                    });

                    // On investment horizon or a bond forward's Settlement Date, the deal value is liquidated as cash.
                    double endDate = Deal.EndDate();
                    if (cash != null && endDate <= fT.fHorizon)
                    {
                        // If endDate on a payment date, cashflow has already been accummulated (as cash), otherwise is 0.
                        // Value liquidated is the value of the pv remaining after accummulating the cashflow.
                        cash.AssignDifference(pv, cash);
                        cashAccumulator.Accumulate(fFxRate, endDate, cash);
                    }
                }

                result.Complete(fT);
            }
        }