示例#1
0
        /// <summary>
        /// Gets the discount rate used in the option valuation formula.
        /// </summary>
        protected override void GetDiscountRate(Vector r, IInterestRate discountRate, double t, double tPay)
        {
            Double date    = fBaseDate + CalcUtils.YearsToDays(t);
            Double payDate = fBaseDate + CalcUtils.YearsToDays(tPay);

            r.Assign(VectorMath.Log(discountRate.Get(t, tPay)) / CalcUtils.DayCountFraction(payDate, date, DayCount.BUS_252, ((IDIOptionDeal)Deal).Calendar()));
        }
示例#2
0
        /// <summary>
        /// Get price factors.
        /// </summary>
        private void PreValue(PriceFactorList factors)
        {
            var deal = (CalendarSpreadOption)Deal;

            // Get forward price samples.
            fForwardSample = factors.Get <ForwardPriceSample>(deal.Sampling_Type);

            // Get ReferencePrice price factors.
            fReferencePrice1 = factors.GetInterface <IReferencePrice>(deal.Reference_Type);
            fReferencePrice2 = factors.GetInterface <IReferencePrice>(deal.Reference_Type);

            // Get ReferenceVol price factors.
            // Default to Reference Type if Reference Vol Type is not set.
            if (string.IsNullOrEmpty(deal.Reference_Vol_Type))
            {
                fReferenceVol1 = factors.Get <ReferenceVol>(deal.Reference_Type);
                fReferenceVol2 = factors.Get <ReferenceVol>(deal.Reference_Type);
            }
            else
            {
                fReferenceVol1 = factors.Get <ReferenceVol>(deal.Reference_Vol_Type);
                fReferenceVol2 = factors.Get <ReferenceVol>(deal.Reference_Vol_Type);
            }

            // Get correlation price factor based on the ID of the forward price.
            fCorrelations = factors.Get <ForwardPriceCorrelations>(fReferencePrice1.GetForwardPrice());

            // Get FX rate price factors.
            fFxRate            = factors.GetInterface <IFxRate>(deal.Currency);
            fFxPayoffRate      = factors.GetInterface <IFxRate>(deal.DealCurrency());
            fPriceFactorFxRate = factors.GetInterface <IFxRate>(fReferencePrice1.DomesticCurrency());

            // Get discount rate price factor.
            fDiscountRate = factors.GetInterface <IInterestRate>(InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency));
        }
示例#3
0
 /// <summary>
 /// Value cashflow list with standard payoff, standard LIBOR cashflows without options.
 /// </summary>
 private void ValueSwap(Vector pv, Vector cash, double baseDate, double valueDate, Vector settlementDate,
                        IInterestRate discount, IInterestRate forecast, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter)
 {
     if (fCharacteristics.IsOIS && OIS_Cashflow_Group_Size <= 1 && settlementDate == null)
     {
         fCashflows.ValueOIS(pv, cash, baseDate, valueDate, fCutoffDate, discount, forecast, intraValuationDiagnosticsWriter);
     }
     else
     {
         fCashflows.ValueSwap(pv, cash, null, baseDate, valueDate, settlementDate, fCutoffDate, discount, forecast, fCharacteristics.IsVanillaSwap, intraValuationDiagnosticsWriter);
     }
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        public CreditValuationParameters(DealCreditBase deal, CreditBaseValuation valuation, PriceFactorList factors, VectorScopedCache.Scope cache)
        {
            DF          = DiscountRate.Get(factors, InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency));
            X           = factors.GetInterface <IFxRate>(deal.Currency);
            SP          = factors.GetInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Name : deal.Survival_Probability);
            RR          = null;
            CR          = null;
            DefaultTime = null;
            Weights     = null;
            NamesDefaultedBeforeBaseDate = null;

            if (valuation.Respect_Default == YesNo.Yes)
            {
                List <string> names = new List <string>();
                if (deal.ProtectionReferenceType() == DealCreditBase.ReferenceType.Single_Name)
                {
                    names.Add(deal.Name);
                    Weights = new double[] { 1.0 };
                }
                else
                {
                    IndexCDSPool indexCds = factors.Get <IndexCDSPool>(deal.Name);
                    Weights = new double[indexCds.Names.Count];
                    for (int i = 0; i < indexCds.Names.Count; ++i)
                    {
                        names.Add(indexCds.Names[i].Name);
                        Weights[i] = indexCds.Names[i].Weight;
                    }
                }

                if (valuation.RequiresRecoveryOnDefault())
                {
                    RR = new RecoveryRate[names.Count];
                    for (int i = 0; i < names.Count; ++i)
                    {
                        RR[i] = factors.Get <RecoveryRate>(string.IsNullOrEmpty(deal.Recovery_Rate) ? names[i] : deal.Recovery_Rate);
                    }
                }

                CR = new CreditRating[names.Count];
                NamesDefaultedBeforeBaseDate = new bool[names.Count];
                DefaultTime = new Vector[names.Count];
                for (int i = 0; i < names.Count; ++i)
                {
                    DefaultTime[i] = cache.Get();
                    CR[i]          = factors.Get <CreditRating>(names[i]);
                    NamesDefaultedBeforeBaseDate[i] = CreditRating.DefaultedBeforeBaseDate(CR[i], factors.BaseDate);
                    CR[i].DefaultTime(DefaultTime[i]);
                }
            }
        }
        /// <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;
        }
示例#6
0
文件: Account.cs 项目: Tolga/Bank
 public Account(ICustomer customer, AccountType type = AccountType.Normal, float balance = 0.0F, DateTime closeDate = default(DateTime), IInterestRate state = null, float allowedDebit = 250.00F)
 {
     AccountId = customer.NewAccountId();
     CustomerId = customer.CustomerId;
     Balance = balance;
     OpenDate = DateTime.Now;
     CloseDate = closeDate;
     History = new List<IOperationHistory>();
     AllowedDebit = allowedDebit;
     Debits = 0.0F;
     Type = type;
     State = state ?? new Normal(this);
     State.Check();
 }
        /// <summary>
        /// Value the deal using the cashflow list.
        /// </summary>
        /// <param name="pv">Present value to be updated.</param>
        /// <param name="cash">Realised cash to be updated.</param>
        public void Value(Vector pv, Vector cash, double baseDate, double valueDate, Vector settlementDate, IInterestRate discount,
                          IInterestRate forecast, IInterestRate repo, IInterestRateVol interestRateVol, IInterestYieldVol interestYieldVol,
                          ISurvivalProb survivalProb, ISACCRResult saccrResult, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter)
        {
            CFFixedListDeal deal = (CFFixedListDeal)Deal;

            pv.Clear();
            if (cash != null)
            {
                cash.Clear();
            }

            deal.Cashflows.Value(pv, cash, baseDate, valueDate, settlementDate, discount, survivalProb, intraValuationDiagnosticsWriter, fCutoffDate);
            ApplySign(pv, cash, fBuySellSign);
        }
示例#8
0
        /// <inheritdoc />
        public void PreValue(PriceFactorList factors)
        {
            var deal = (SwaptionDeal)Deal;

            var discountId = InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency);
            var forecastId = InterestRateUtils.GetRateId(deal.Forecast_Rate, discountId);

            fModelParameters = factors.Get <HullWhite1FactorModelParameters>(fModelParametersId);

            fFxRate       = factors.GetInterface <IFxRate>(deal.Currency);
            fDiscountRate = DiscountRate.Get(factors, discountId);
            fForecastRate = factors.GetInterface <IInterestRate>(forecastId);

            fQuadrature = new Lazy <GaussHermiteNormalQuadrature>(() => new GaussHermiteNormalQuadrature(30));
        }
        /// <summary>
        /// Single date valuation function.
        /// </summary>
        public void Value(Vector pv, Vector cash, double baseDate, double valueDate, Vector settlementDate, IInterestRate discount,
                          IInterestRate forecast, IInterestRate repo, IInterestRateVol interestRateVol, IInterestYieldVol interestYieldVol,
                          ISurvivalProb survivalProb, ISACCRResult saccrResult, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter)
        {
            FixedCashflowBaseDeal deal = (FixedCashflowBaseDeal)fDeal;
            double payDate             = deal.Payment_Date;

            if (payDate < valueDate)
            {
                return;
            }

            using (var cache = Vector.CacheLike(pv))
            {
                Vector amount = cache.Get(fAmount);
                if (settlementDate != null)
                {
                    amount.MultiplyBy(settlementDate < payDate);
                }

                if (payDate == valueDate)
                {
                    pv.Assign(amount);
                    if (cash != null)
                    {
                        cash.Assign(amount);
                    }
                }
                else
                {
                    double t    = CalcUtils.DaysToYears(valueDate - baseDate);
                    double tPay = CalcUtils.DaysToYears(payDate - baseDate);
                    if (survivalProb != null)
                    {
                        pv.Assign(amount * discount.Get(t, tPay) * survivalProb.Get(t, tPay));
                    }
                    else
                    {
                        pv.Assign(amount * discount.Get(t, tPay));
                    }
                }
            }
        }
示例#10
0
        /// <summary>
        /// This method Adjusts the bond price vector by taking the default into account give the default time vector.
        /// </summary>
        public static void AdjustForDefault(double baseDate, double valueDate, Vector bondPrice, TDate expiryDate, bool respectDefault, Vector underlyingIsAlive, Vector historicalRecovery, Vector defaultTime, IInterestRate discountRate, RecoveryRate recoveryRate)
        {
            // Adjust the bond price for default: check scenario by scenario for defaults, overwriting bondPrice as necessary
            if (!respectDefault)
            {
                return;
            }

            double currentTime = CalcUtils.DaysToYears(valueDate - baseDate);
            double tExpiry     = CalcUtils.DaysToYears(expiryDate - baseDate);

            BondOptionValuation.AdjustBondValueForDefault(1.0, tExpiry, bondPrice, underlyingIsAlive,
                                                          historicalRecovery, defaultTime, currentTime, discountRate,
                                                          recoveryRate);
        }
示例#11
0
        /// <summary>
        /// Value the deal using the cashflow list.
        /// </summary>
        /// <param name="pv">Present value to be updated.</param>
        /// <param name="cash">Realised cash to be updated.</param>
        public void Value(Vector pv, Vector cash, double baseDate, double valueDate, Vector settlementDate, IInterestRate discount,
                          IInterestRate forecast, IInterestRate repo, IInterestRateVol interestRateVol, IInterestYieldVol interestYieldVol,
                          ISurvivalProb survivalProb, ISACCRResult saccrResult, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter)
        {
            CFFixedInterestListDeal deal = (CFFixedInterestListDeal)Deal;

            pv.Clear();
            if (cash != null)
            {
                cash.Clear();
            }

            deal.Cashflows.Value(pv, cash, null, baseDate, valueDate, settlementDate, discount, survivalProb, fFxRate, fRateFxRate, intraValuationDiagnosticsWriter, fCutoffDate);

            using (var cache = Vector.CacheLike(pv))
            {
                Vector sp = cache.Get(1.0);

                double dealSettlementDate = deal.Settlement_Date;
                double t       = CalcUtils.DaysToYears(valueDate - baseDate);
                double tSettle = CalcUtils.DaysToYears(dealSettlementDate - baseDate);

                if (Use_Survival_Probability == YesNo.Yes && survivalProb != null)
                {
                    survivalProb.GetValue(sp, t, tSettle);
                    fRecoveryList.Value(pv, baseDate, valueDate, discount, survivalProb, intraValuationDiagnosticsWriter);
                }

                if (valueDate < dealSettlementDate)
                {
                    // Forward deal before settlement date
                    if (deal.Is_Defaultable == YesNo.No)
                    {
                        pv.Assign((pv / discount.Get(t, tSettle) - fSettlementAmount) * repo.Get(t, tSettle));
                    }
                    else
                    {
                        pv.Subtract(fAccruedInterest * discount.Get(t, tSettle) * sp + (fSettlementAmount - fAccruedInterest) * repo.Get(t, tSettle));
                    }
                }
                else if (valueDate == dealSettlementDate)
                {
                    // Forward deal at settlement date
                    pv.Subtract(fSettlementAmount);
                    if (cash != null)
                    {
                        if (deal.Settlement_Style == SettlementType.Cash)
                        {
                            cash.Assign(pv);
                        }
                        else
                        {
                            cash.Subtract(fSettlementAmount);
                        }
                    }
                }
            }

            pv.AssignProduct(fBuySellSign, pv);
            if (cash != null)
            {
                cash.AssignProduct(fBuySellSign, cash);
            }
        }
示例#12
0
        /// <summary>
        /// This method check scenario by scenario for defaults, overwriting bondValue as necessary
        /// </summary>
        public static void AdjustBondValueForDefault(double notional, double expiryTime, Vector bondValue, Vector bondIsAlive,
                                                     Vector historicalRecovery, Vector defaultTime, double currentTime, IInterestRate discountRate, RecoveryRate recoveryRate)
        {
            using (var cache = Vector.CacheLike(bondValue))
            {
                Vector recoveryValue = cache.Get();
                Vector expiryDf      = cache.Get();

                discountRate.GetValue(expiryDf, currentTime, expiryTime);
                recoveryRate.GetValue(recoveryValue, currentTime);

                // If this is the period when the bond defaults fill in the historical recovery amount.
                historicalRecovery.AssignConditional((defaultTime <= currentTime).And(bondIsAlive), recoveryValue * notional, historicalRecovery);

                bondValue.AssignConditional((defaultTime <= currentTime), expiryDf * historicalRecovery, bondValue);

                bondIsAlive.AssignConditional((defaultTime <= currentTime), 0.0, bondIsAlive);
            }
        }
示例#13
0
        /// <summary>
        /// Value the deal from given base date, price factors and time grid.
        /// </summary>
        public void Value(PVProfiles pvResults, CashAccumulators cashResults, double baseDate, IInterestRate discountRate, IInterestRate forecastRate1, IInterestRate forecastRate2, IFxRate fxRate, TimeGrid timeGrid, int numScenarios)
        {
            var tgi  = new TimeGridIterator(timeGrid);
            var deal = (FloatingInterestCashflowInterpolatedDeal)Deal;

            bool   hasRate1          = deal.HasRate1();
            bool   hasRate2          = deal.HasRate2();
            double scale             = deal.Buy_Sell == BuySell.Buy ? +deal.Principal : -deal.Principal;
            double tPay              = CalcUtils.DaysToYears(fPaymentDate - baseDate);
            double tReset            = CalcUtils.DaysToYears(deal.Reset_Date - baseDate);
            double tRateStart        = CalcUtils.DaysToYears(deal.Rate_Start_Date - baseDate);
            double tRateEnd1         = hasRate1 ? CalcUtils.DaysToYears(fRate1EndDate - baseDate) : 0.0;
            double tRateEnd2         = hasRate2 ? CalcUtils.DaysToYears(fRate2EndDate - baseDate) : 0.0;
            double tRateEnd12        = tRateEnd2 - tRateEnd1;                                                                    // Time from rate 1 end date to rate 2 end date.
            double tAccrualEnd       = CalcUtils.DaysToYears(deal.Accrual_End_Date - baseDate);
            double interpCoefficient = Math.Abs(tRateEnd12) >= CalcUtils.MinTime ? (tAccrualEnd - tRateEnd1) / tRateEnd12 : 0.0; // Coefficient used to calculate interpolated rate.

            VectorEngine.For(tgi, () =>
            {
                using (var cache = Vector.Cache(numScenarios))
                {
                    Vector pv = cache.Get();

                    if (tgi.Date <= fPaymentDate && fPaymentDate > fCutoffDate)
                    {
                        Vector interpRate = cache.GetClear();
                        Vector rate1      = cache.GetClear();
                        Vector rate2      = cache.GetClear();

                        if (hasRate1)
                        {
                            if (fKnownResetRate1.HasValue)
                            {
                                rate1.Assign(fKnownResetRate1.Value);
                            }
                            else
                            {
                                InterestRateUtils.LiborRate(rate1, forecastRate1, tgi.T, tReset, tRateStart, tRateEnd1, fRate1YearFraction);
                            }
                        }

                        if (hasRate2)
                        {
                            if (fKnownResetRate2.HasValue)
                            {
                                rate2.Assign(fKnownResetRate2.Value);
                            }
                            else
                            {
                                InterestRateUtils.LiborRate(rate2, forecastRate2, tgi.T, tReset, tRateStart, tRateEnd2, fRate2YearFraction);
                            }
                        }

                        if (hasRate1 && hasRate2)
                        {
                            if (Math.Abs(tRateEnd12) >= CalcUtils.MinTime)
                            {
                                interpRate.Assign(rate1 + interpCoefficient * (rate2 - rate1));
                            }
                            else
                            {
                                interpRate.Assign(0.5 * rate1 + 0.5 * rate2);
                            }
                        }
                        else
                        {
                            interpRate.Assign(hasRate1 ? rate1 : rate2);
                        }

                        // Round the calculated rate, regardless whether the valuation date is before or after the reset date.
                        CFFloatingInterestList.RoundRateTo(deal.Interpolated_Rate_Rounding, interpRate);

                        pv.Assign(scale * (interpRate + deal.Margin) * fAccrualYearFraction);

                        CFFixedList.RoundCashflow(pv, Cashflow_Rounding);

                        if (tgi.Date < fPaymentDate)
                        {
                            pv.MultiplyBy(discountRate.Get(tgi.T, tPay));
                        }
                        else if (tgi.Date == fPaymentDate)
                        {
                            cashResults.Accumulate(fxRate, fPaymentDate, pv);
                        }
                    }
                    else
                    {
                        pv.Clear();
                    }

                    pvResults.AppendVector(tgi.Date, pv * fxRate.Get(tgi.T));
                }
            });

            // After maturity
            pvResults.Complete(timeGrid);
        }
示例#14
0
        /// <summary>
        /// Value the deal using the cashflow list.
        /// </summary>
        public void Value(Vector pv, Vector cash, double baseDate, double valueDate, Vector settlementDate, IInterestRate discount,
                          IInterestRate forecast, IInterestRate repo, IInterestRateVol interestRateVol, IInterestYieldVol interestYieldVol,
                          ISurvivalProb survivalProb, ISACCRResult saccrResult, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter)
        {
            var deal = (CFFloatingInterestListDeal)Deal;

            pv.Clear();
            if (cash != null)
            {
                cash.Clear();
            }

            bool valued = false;

            if (Use_Survival_Probability == YesNo.Yes && survivalProb != null)
            {
                fRecoveryList.Value(pv, baseDate, valueDate, discount, survivalProb, intraValuationDiagnosticsWriter);
            }
            else if (!fForecastIsForeign && fCharacteristics.IsStandardPayoff && fCharacteristics.IsStandardLibor && fCashflows.Compounding_Method != CompoundingMethod.Exponential)
            {
                if (fCharacteristics.HasSwaplet && !fCharacteristics.HasOptionlet)
                {
                    ValueSwap(pv, cash, baseDate, valueDate, settlementDate, discount, forecast, intraValuationDiagnosticsWriter);
                    valued = true;
                }
                else if (fCharacteristics.HasOptionlet && !fCharacteristics.HasSwaplet && fCashflows.Compounding_Method == CompoundingMethod.None)
                {
                    fCashflows.ValueCap(pv, cash, baseDate, valueDate, settlementDate, discount, forecast,
                                        fForecastRateVol, saccrResult, intraValuationDiagnosticsWriter, fCutoffDate);
                    valued = true;
                }
            }

            if (!valued)
            {
                // Use general cashflow list valuation
                if (fCashflows.Averaging_Method == AveragingMethod.Average_Rate)
                {
                    fCashflows.ValueAverageRate(pv, cash, baseDate, valueDate, settlementDate, discount, forecast, fForecastRateVol, fForecastYieldVol,
                                                fFxRate, fForecastFxRate, fForecastFxVol, fForecastFxCorrel, survivalProb, intraValuationDiagnosticsWriter, fCutoffDate);
                }
                else
                {
                    fCashflows.Value(pv, cash, baseDate, valueDate, settlementDate, discount, forecast, fDiscountRateVol, fDiscountYieldVol, interestRateVol, interestYieldVol,
                                     fFxRate, fForecastFxRate, fForecastFxVol, fForecastFxCorrel, fForecastDiscountCorrel, survivalProb, intraValuationDiagnosticsWriter, fCutoffDate);
                }
            }

            double dealSettlementDate = deal.Settlement_Date;

            if (valueDate <= dealSettlementDate)
            {
                using (var cache = Vector.CacheLike(pv))
                {
                    Vector accruedInterest = cache.Get();
                    fCashflows.CalculateAccrual(accruedInterest, baseDate, dealSettlementDate, false, deal.AccrualHolidayCalendar(), forecast);
                    Vector settlementAmount = cache.Get(deal.Settlement_Amount);
                    if (deal.Settlement_Amount_Is_Clean == YesNo.Yes)
                    {
                        settlementAmount.Add(accruedInterest);
                    }

                    if (valueDate < dealSettlementDate)
                    {
                        // Forward deal before settlement date
                        double t       = CalcUtils.DaysToYears(valueDate - baseDate);
                        double tSettle = CalcUtils.DaysToYears(dealSettlementDate - baseDate);
                        if (deal.Is_Defaultable == YesNo.No)
                        {
                            pv.Assign((pv / discount.Get(t, tSettle) - settlementAmount) * repo.Get(t, tSettle));
                        }
                        else
                        {
                            pv.Subtract(accruedInterest * discount.Get(t, tSettle) + (settlementAmount - accruedInterest) * repo.Get(t, tSettle));
                        }
                    }
                    else if (valueDate == dealSettlementDate)
                    {
                        // Forward deal at settlement date
                        pv.Subtract(settlementAmount);
                        if (cash != null)
                        {
                            if (deal.Settlement_Style == SettlementType.Cash)
                            {
                                cash.Assign(pv);
                            }
                            else
                            {
                                cash.Subtract(settlementAmount);
                            }
                        }
                    }
                }
            }

            pv.AssignProduct(fBuySellSign, pv);
            if (cash != null)
            {
                cash.AssignProduct(fBuySellSign, cash);
            }
        }
        /// <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);
                    }
                }
            }
        }