/// <summary> /// Prepare for valuation anything that is dependent upon the scenario. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); CFFixedInterestListDeal deal = (CFFixedInterestListDeal)fDeal; // Get factor for translation from rate currency to settlement currency for cashflows with FX reset date if (!string.IsNullOrEmpty(deal.Rate_Currency) && deal.Rate_Currency != fCurrency) { fRateFxRate = factors.GetInterface <IFxRate>(deal.Rate_Currency); } }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); CFFixedInterestListDeal deal = (CFFixedInterestListDeal)fDeal; // Register factor for translation from rate currency to settlement currency for cashflows with FX reset date if (!string.IsNullOrEmpty(deal.Rate_Currency) && deal.Rate_Currency != fCurrency) { factors.RegisterInterface <IFxRate>(deal.Rate_Currency); } }
/// <summary> /// Collect cashflows realised along the scenario path up to endDate. /// </summary> public override void CollectCashflows(CashAccumulators cashAccumulators, double baseDate, double endDate) { CFFixedInterestListDeal deal = (CFFixedInterestListDeal)Deal; deal.Cashflows.CollectCashflows(cashAccumulators, fFxRate, fRateFxRate, baseDate, endDate, fBuySellSign, fCutoffDate); double settlementDate = deal.Settlement_Date; if (settlementDate >= baseDate && settlementDate <= endDate) { cashAccumulators.Accumulate(fFxRate, settlementDate, -fBuySellSign * fSettlementAmount); } }
/// <summary> /// Prepare for valuation anything that is not dependent upon the scenario. /// </summary> public override void PreCloneInitialize(PriceFactorList factors, BaseTimeGrid baseTimes, RequiredResults requiredResults) { base.PreCloneInitialize(factors, baseTimes, requiredResults); CFFixedInterestListDeal deal = (CFFixedInterestListDeal)Deal; // Set up cashflow list deal.Cashflows.CalculateInterest(factors.BaseDate); // Add to valuation time grid bool payDatesRequired = ValueOnCashflowDates() && requiredResults.CashRequired(); fT.AddPayDates <CFFixedInterest>(deal.Cashflows, payDatesRequired); double baseDate = factors.BaseDate; double settlementDate = deal.Settlement_Date; if (settlementDate >= baseDate) { fT.AddPayDate(settlementDate, payDatesRequired); var accrualCalendar = deal.GetHolidayCalendar(); fAccruedInterest = deal.Cashflows.CalculateAccrual(settlementDate, false, accrualCalendar); fSettlementAmount = deal.Settlement_Amount; if (deal.Settlement_Amount_Is_Clean == YesNo.Yes) { fSettlementAmount += fAccruedInterest; } } // Settlement date takes precedence. if (Use_Settlement_Offset == YesNo.Yes && settlementDate != 0.0) { fCutoffDate = 0.0; } if (deal.Investment_Horizon > 0.0) { fT.AddPayDate(deal.Investment_Horizon, payDatesRequired); } if (Use_Survival_Probability == YesNo.Yes) { fRecoveryList = new CFRecoveryList(); fRecoveryList.PopulateRecoveryCashflowList(baseDate, settlementDate, deal.Cashflows); } }
/// <summary> /// Value the deal. /// </summary> /// <param name="pv">Present value to be updated.</param> /// <param name="cash">Realised cash to be updated.</param> public override void Value(Vector pv, Vector cash, double baseDate, double valueDate, ISACCRResult saccrResult, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter) { Value(pv, cash, baseDate, valueDate, null, fDiscountRate, null, fRepoRate, null, null, fSurvivalProb, saccrResult, intraValuationDiagnosticsWriter); // Add accruedInterest to Intra-valuation diagnostics if (intraValuationDiagnosticsWriter.Level > IntraValuationDiagnosticsLevel.None) { CFFixedInterestListDeal deal = (CFFixedInterestListDeal)Deal; using (var cache = Vector.CacheLike(pv)) { Vector accruedInterest = cache.Get(deal.Cashflows.CalculateAccrual(valueDate, false, deal.GetHolidayCalendar())); IntraValuationDiagnosticsHelper.AddCashflowsAccruedInterest(fIntraValuationDiagnosticsWriter, accruedInterest); } } }
/// <summary> /// Modify the pv and cash taking the date of default into account. /// </summary> public override void GetDefaultValue(double baseDate, double valueDate, Vector defaultDate, RecoveryRate recoveryRate, Vector pv, Vector cash) { CFFixedInterestListDeal deal = (CFFixedInterestListDeal)fDeal; double principal = GetPrincipal(deal.Cashflows, valueDate); double settlementDate = deal.Settlement_Date; double t = CalcUtils.DaysToYears(valueDate - baseDate); using (var cache = Vector.CacheLike(pv)) { // Approximation: recover only principal, neglecting accrued interest Vector recovery = cache.Get(fBuySellSign * principal * recoveryRate.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). double tSettle = CalcUtils.DaysToYears(settlementDate - baseDate); double settlementAmount = fBuySellSign * fSettlementAmount; Vector hasDefaulted = cache.Get(defaultDate <= valueDate); pv.AssignConditional(hasDefaulted, fRepoRate.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); } } } }
/// <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); } }
/// <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); } }