/// <summary>
        /// Prepare for valuation anything that is dependent upon the scenario.
        /// </summary>
        /// <param name="factors">Price factors.</param>
        public override void PreValue(PriceFactorList factors)
        {
            base.PreValue(factors);

            IInflationCashflowListDeal deal = (IInflationCashflowListDeal)Deal;

            fIsDefaultNever  = !NeedCreditRating();
            fCreditRating    = NeedCreditRating()                      ? factors.Get <CreditRating>(deal.Issuer)                       : null;
            fRecoveryRate    = NeedRecoveryRate()                      ? factors.Get <RecoveryRate>(GetRecoveryRateID())               : null;
            fSurvivalProb    = NeedSurvivalProb()                      ? factors.GetInterface <ISurvivalProb>(GetSurvivalProbID())     : null;
            fInflationRate   = !string.IsNullOrEmpty(deal.Index)       ? factors.GetInterface <IInflationRate>(deal.Index)             : null;
            fRepoRate        = !string.IsNullOrEmpty(deal.Repo_Rate)   ? factors.GetInterface <IInterestRate>(deal.Repo_Rate)          : fDiscountRate;
            fIndexVolatility = deal is InflationOptionCashflowListDeal?factors.GetInterface <IPriceIndexVolatility>(GetPriceIndexVolatility()) : null;
        }
        /// <summary>
        /// Returns the payment amount on settlement date based on the cashflowlist.
        /// </summary>
        /// <remarks>
        /// The payment amount on settlement date will be either the dirty price of the bond or the clean price of the bond plus
        /// the accrued interest (two cashflows). Note that for a long position in a bond forward, this value is negative
        /// (indicating outgoing cashflow).
        /// </remarks>
        protected virtual void GetSettlementAmount(Vector amount, double valueDate, double baseDate, IInflationRate inflationRate, IPriceIndexVolatility indexVolatility)
        {
            amount.Clear();
            using (var cache = Vector.CacheLike(amount))
            {
                var    deal          = (IInflationCashflowListDeal)Deal;
                var    cashflows     = deal.GetCashflows();
                Vector settlementPay = cache.Get();

                for (int i = 0; i < cashflows.Count(); ++i)
                {
                    if (cashflows.GetCashflow(i).Payment_Date < deal.Settlement_Date)
                    {
                        continue;
                    }
                    else if (cashflows.GetCashflow(i).Payment_Date == deal.Settlement_Date)
                    {
                        cashflows.GetCashflow(i).ExpectedAmount(settlementPay, CalcUtils.DaysToYears(valueDate - baseDate), inflationRate, indexVolatility,
                                                                IntraValuationDiagnosticsWriterFactory.GetOrCreate(IntraValuationDiagnosticsLevel.None));
                        amount.Add(settlementPay);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// Modify the pv and cash taking the date of default into account.
        /// </summary>
        protected void GetDefaultValue(double baseDate, double valueDate, Vector defaultDate, IInflationRate inflationRate, IPriceIndexVolatility indexVolatility, IInterestRate repo, Vector pv, Vector cash)
        {
            IInflationCashflowListDeal deal = (IInflationCashflowListDeal)Deal;

            double settlementDate = deal.Settlement_Date;
            double t           = CalcUtils.DaysToYears(valueDate - baseDate);
            double buySellSign = deal.Buy_Sell == BuySell.Buy ? 1.0 : -1.0;

            if (repo == null)
            {
                repo = fDiscountRate;
            }

            using (var cache = Vector.CacheLike(pv))
            {
                Vector principal = cache.Get();
                GetCurrentExposure(principal, t, valueDate, inflationRate);

                // Approximation: recover only principal, neglecting accrued interest.
                Vector recovery = cache.Get(buySellSign * principal * fRecoveryRate.Get(t));

                if (valueDate <= settlementDate)
                {
                    // Set the pv to (recovery - |settlementAmount|) * df when defaultDate <= valueDate <= settlementDate.
                    // Set cash to (recovery - |settlementAmount|) when defaultDate <= valueDate = settlementDate (cash is always zero before settlementDate).
                    // Note that GetSettlementAmount(...) will return a negative value for a long bond position, indicating an outgoing cashflow.
                    double tSettle          = CalcUtils.DaysToYears(settlementDate - baseDate);
                    Vector settlementAmount = cache.Get();
                    GetSettlementAmount(settlementAmount, valueDate, baseDate, inflationRate, indexVolatility);
                    settlementAmount.MultiplyBy(buySellSign);

                    Vector hasDefaulted = cache.Get(defaultDate <= valueDate);

                    pv.AssignConditional(hasDefaulted, repo.Get(t, tSettle) * (recovery + settlementAmount), pv);

                    if (cash != null && valueDate == settlementDate)
                    {
                        cash.AssignConditional(hasDefaulted, pv, cash);
                    }
                }
                else
                {
                    // after settlement date
                    recovery.MultiplyBy(defaultDate >= valueDate); // set to zero if already defaulted
                    Vector notDefaulted = cache.Get(defaultDate > valueDate);

                    pv.AssignConditional(notDefaulted, pv, recovery);

                    if (cash != null)
                    {
                        cash.AssignConditional(notDefaulted, cash, recovery);
                    }
                }
            }
        }