/// <summary>
        /// Calculate a valuation profile for the deal for the current scenario.
        /// </summary>
        public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes)
        {
            PreValue(factors);

            var deal = (CFListBaseDeal <TCashflowList>)fDeal;

            double baseDate = factors.BaseDate;

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

            double endDate = deal.EndDate();

            using (IntraValuationDiagnosticsHelper.StartDeal(fIntraValuationDiagnosticsWriter, fDeal))
            {
                using (var outerCache = Vector.Cache(factors.NumScenarios))
                {
                    Vector defaultDate = fCreditRating != null?outerCache.Get(CalcUtils.DateTimeMaxValueAsDouble) : null;

                    var  defaultedBeforeBaseDate = CreditRating.DefaultedBeforeBaseDate(fCreditRating, baseDate);
                    bool collectCash             = ValueOnCashflowDates();

                    var saccrResult = SACCRResultFactory.Create(valuationResults, deal.GetDealReferenceProvider().DealReference,
                                                                () => new SACCROptionResult(factors.NumScenarios));

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

                            if (!defaultedBeforeBaseDate)
                            {
                                using (IntraValuationDiagnosticsHelper.StartCashflowsOnDate(fIntraValuationDiagnosticsWriter, tgi.Date))
                                {
                                    using (IntraValuationDiagnosticsHelper.StartCashflows(fIntraValuationDiagnosticsWriter, fFxRate, tgi.T, deal))
                                    {
                                        Value(pv, cash, baseDate, tgi.Date, saccrResult, fIntraValuationDiagnosticsWriter);
                                        IntraValuationDiagnosticsHelper.AddCashflowsPV(fIntraValuationDiagnosticsWriter, pv);
                                    }
                                }

                                if (fCreditRating != null)
                                {
                                    UpdateDefaultDate(fCreditRating, tgi.Date, tgi.T, defaultDate);
                                    GetDefaultValue(baseDate, tgi.Date, defaultDate, fRecoveryRate, pv, cash);
                                }
                            }

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

                            if (!cashAccumulators.Ignore && cash != null)
                            {
                                // Realise all value as cash on deal end date
                                if (tgi.Date == endDate)
                                {
                                    cash.Assign(pv);
                                }

                                cashAccumulators.Accumulate(fFxRate, tgi.Date, cash);
                            }
                        }
                    });

                    if (!cashAccumulators.Ignore && !collectCash)
                    {
                        CollectCashflows(cashAccumulators, baseDate, fT.fHorizon);

                        // Consolidate and net in order to avoid getting Net incoming and outgoing cashflows with the same payment date,
                        // e.g. for compounding swaps with both positive and negative rates.
                        cashAccumulators.ConsolidateAndNet(fCurrency, factors);
                    }

                    result.Complete(fT);
                }
            }
        }