/// <summary> /// Prepare for valuation anything that is dependent upon the scenario. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); BondFutureOption deal = (BondFutureOption)Deal; fInterestYieldVol = InterestVolBase.GetYieldVol(factors, deal.Yield_Volatility, fCurrency); var bfb = (BondFuturesBasis)fFuturesBasis; GenerateCTD(factors.BaseDate, bfb.CTD_Issue_Date, bfb.CTD_Maturity_Date, bfb.CTD_Coupon_Interval, bfb.CTD_First_Coupon_Date, bfb.CTD_Penultimate_Coupon_Date, bfb.CTD_Day_Count, Deal.GetHolidayCalendar(), bfb.CTD_Coupon_Rate, bfb.CTD_Conversion_Factor); if (NeedRating(Respect_Default, deal.Issuer)) { fCreditRating = factors.Get <CreditRating>(deal.Issuer); fRecoveryRate = factors.Get <RecoveryRate>(InterestRateUtils.GetRateId(deal.Recovery_Rate, deal.Issuer)); } else { fCreditRating = null; fRecoveryRate = null; } if (NeedSurvivalProbability(Use_Survival_Probability, deal.Issuer)) { fSurvivalProb = factors.GetInterface <ISurvivalProb>(InterestRateUtils.GetRateId(deal.Survival_Probability, deal.Issuer)); } else { fSurvivalProb = null; } }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); BondOptionDeal deal = (BondOptionDeal)Deal; InterestVolBase.RegisterInterestYieldVol(factors, deal.Yield_Volatility, fCurrency); bool needRating = Respect_Default == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); bool needSurvival = Use_Survival_Probability == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); bool needRecovery = needRating; if (needRating) { factors.Register <CreditRating>(deal.Issuer); } if (needRecovery) { factors.Register <RecoveryRate>(string.IsNullOrEmpty(deal.Recovery_Rate) ? deal.Issuer : deal.Recovery_Rate); } if (needSurvival) { factors.RegisterInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Issuer : deal.Survival_Probability); } }
/// <summary> /// Prepare for valuation anything that is dependent upon the scenario. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); CallableBondForward deal = (CallableBondForward)Deal; fInterestYieldVol = InterestVolBase.GetYieldVol(factors, deal.Yield_Volatility, fCurrency); fNeedsCreditRating = NeedCreditRating(); fCreditRating = NeedCreditRating() ? factors.Get <CreditRating>(deal.Issuer) : null; fRecoveryRate = NeedRecovery() ? factors.Get <RecoveryRate>(string.IsNullOrEmpty(deal.Recovery_Rate) ? deal.Issuer : deal.Recovery_Rate) : null; fSurvivalProb = NeedSurvivalProb() ? factors.GetInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Issuer : deal.Survival_Probability) : null; }
/// <summary> /// Prepare for valuation. /// </summary> public override void PreValue(PriceFactorList factors) { var deal = (CFFloatingInterestListDeal)Deal; base.PreValue(factors); bool quanto = fForecastIsForeign && fCharacteristics.HasQuanto && Quanto_Correction == YesNo.Yes; bool convexity = !fCharacteristics.IsStandardLibor && Convexity_Correction == YesNo.Yes; // volatility surfaces for forecast rate if (fCharacteristics.HasCms) { fForecastYieldVol = InterestVolBase.GetYieldVol(factors, deal.Forecast_Rate_Swaption_Volatility, fForecastCurrency); } if (fCharacteristics.HasLibor && (fCharacteristics.HasOptionlet || convexity || quanto)) { fForecastRateVol = InterestVolBase.GetRateVol(factors, deal.Forecast_Rate_Cap_Volatility, fForecastCurrency); } // volatility surfaces for discount rate if (convexity) { // Discount rate volatility and correlation for convexity correction if (fCharacteristics.HasCms) { fDiscountYieldVol = InterestVolBase.GetYieldVol(factors, deal.Discount_Rate_Swaption_Volatility, fCurrency); } if (fCharacteristics.HasLibor) { fDiscountRateVol = InterestVolBase.GetRateVol(factors, deal.Discount_Rate_Cap_Volatility, fCurrency); } } if (fForecastIsForeign) { // Get factor for translation from forecast rate currency to settlement currency for cashflows with FX reset date if (fCharacteristics.HasFXReset) { fForecastFxRate = factors.GetInterface <IFxRate>(fForecastCurrency); } if (quanto) { fForecastFxVol = FXVolHelper.Get(factors, fForecastCurrency, fCurrency); fForecastFxCorrel = CorrelationHelper.Get(factors, typeof(InterestRate), fForecastCurrency, null, typeof(FxRate), fForecastCurrency, fCurrency); fForecastDiscountCorrel = CorrelationHelper.Get(factors, typeof(InterestRate), fForecastCurrency, null, typeof(InterestRate), fCurrency, null); } } }
/// <summary> /// Register price factors used in valuation. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); var deal = (CFEquityFloatingInterestListDeal)Deal; deal.GetDealHelper().RegisterFactors(factors, errors); fEquityCurrency = deal.Equity_Currency; factors.RegisterInterface <IFxRate>(fEquityCurrency); fEquityPayoffCurrency = string.IsNullOrEmpty(deal.Equity_Payoff_Currency) ? fEquityCurrency : deal.Equity_Payoff_Currency; if (fEquityPayoffCurrency != fEquityCurrency) { factors.RegisterInterface <IFxRate>(fEquityPayoffCurrency); } // Get characteristics EquityCashflowListCharacteristics characteristics = deal.Cashflows.Analyze(factors.BaseDate); bool quanto = fForecastIsForeign && Quanto_Correction == YesNo.Yes; if (characteristics.fHasLibor) { if ((!characteristics.fIsStandardLibor && Convexity_Correction == YesNo.Yes) || quanto) { var forecastRateVol = InterestVolBase.RegisterInterestRateVol(factors, deal.Forecast_Rate_Cap_Volatility, fForecastCurrency); InterestVolBase.Validate(deal, forecastRateVol, ProbabilityDistribution.Lognormal, errors); } if (!characteristics.fIsStandardLibor && Convexity_Correction == YesNo.Yes) { var discountRateVol = InterestVolBase.RegisterInterestRateVol(factors, deal.Discount_Rate_Cap_Volatility, fCurrency); InterestVolBase.Validate(deal, discountRateVol, ProbabilityDistribution.Lognormal, errors); } } if (quanto) { FXVolHelper.Register(factors, fForecastCurrency, fCurrency); CorrelationHelper.Register(factors, typeof(IInterestRate), fForecastCurrency, null, typeof(IFxRate), fForecastCurrency, fCurrency); CorrelationHelper.Register(factors, typeof(IInterestRate), fForecastCurrency, null, typeof(IInterestRate), fCurrency, null); } deal.Cashflows.RegisterFactorsValidate(factors.BaseDate, deal.GetEquityPayoffType() == PayoffType.Compo, deal.IsCrossCurrency(), errors); }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { BondFutureOption deal = (BondFutureOption)Deal; base.RegisterFactors(factors, errors); InterestVolBase.RegisterInterestYieldVol(factors, deal.Yield_Volatility, fCurrency); if (NeedRating(Respect_Default, deal.Issuer)) { factors.Register <CreditRating>(deal.Issuer); // register realized recovery rate. factors.Register <RecoveryRate>(InterestRateUtils.GetRateId(deal.Recovery_Rate, deal.Issuer)); } if (NeedSurvivalProbability(Use_Survival_Probability, deal.Issuer)) { factors.RegisterInterface <ISurvivalProb>(InterestRateUtils.GetRateId(deal.Survival_Probability, deal.Issuer)); } }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); CallableBondForward deal = (CallableBondForward)Deal; InterestVolBase.RegisterInterestYieldVol(factors, deal.Yield_Volatility, deal.Currency); if (NeedCreditRating()) { factors.Register <CreditRating>(deal.Issuer); } if (NeedRecovery()) { factors.Register <RecoveryRate>(string.IsNullOrEmpty(deal.Recovery_Rate) ? deal.Issuer : deal.Recovery_Rate); } if (NeedSurvivalProb()) { factors.RegisterInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Issuer : deal.Survival_Probability); } }
/// <summary> /// Prepare for valuation. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); var deal = (CFEquityFloatingInterestListDeal)Deal; deal.GetDealHelper().PreValueAsset(out fEquity, out fEquityVol, ref fEquityQuantoCompo, factors); // Get FX rate price factors fEquityCurrency = deal.Equity_Currency; fEquityPayoffCurrency = string.IsNullOrEmpty(deal.Equity_Payoff_Currency) ? fEquityCurrency : deal.Equity_Payoff_Currency; fEquityFXRate = factors.GetInterface <IFxRate>(fEquityCurrency); fEquityPayoffFXRate = fEquityPayoffCurrency != fEquityCurrency?factors.GetInterface <IFxRate>(fEquityPayoffCurrency) : fEquityFXRate; bool quanto = fForecastIsForeign && Quanto_Correction == YesNo.Yes; if (fCharacteristics.fHasLibor) { // volatility surfaces for forecast rate if ((!fCharacteristics.fIsStandardLibor && Convexity_Correction == YesNo.Yes) || quanto) { fForecastRateVol = InterestVolBase.GetRateVol(factors, deal.Forecast_Rate_Cap_Volatility, fForecastCurrency); } // volatility surfaces for discount rate if (!fCharacteristics.fIsStandardLibor && Convexity_Correction == YesNo.Yes) { fDiscountRateVol = InterestVolBase.GetRateVol(factors, deal.Discount_Rate_Cap_Volatility, fCurrency); } } if (quanto) { fForecastFXVol = FXVolHelper.Get(factors, fForecastCurrency, fCurrency); fForecastFXCorrel = CorrelationHelper.Get(factors, typeof(InterestRate), fForecastCurrency, null, typeof(FxRate), fForecastCurrency, fCurrency); fForecastDiscountCorrel = CorrelationHelper.Get(factors, typeof(InterestRate), fForecastCurrency, null, typeof(InterestRate), fCurrency, null); } }
/// <summary> /// Calculate valuation profiles. /// </summary> public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes) { PreValue(factors); TimeGridIterator tgi = new TimeGridIterator(fT); PVProfiles result = valuationResults.Profile; CashAccumulators cashAccumulators = valuationResults.Cash; BondOptionDeal deal = (BondOptionDeal)Deal; double baseDate = factors.BaseDate; double notional = deal.Notional; double interval = deal.Coupon_Interval; double buySign = (deal.Buy_Sell == BuySell.Buy) ? +1 : -1; double paySign = (deal.Option_Type == OptionType.Call) ? +1 : -1; double coupon = Percentage.PercentagePoint * deal.Coupon_Rate; double tExpiry = CalcUtils.DaysToYears(deal.Expiry_Date - baseDate); double tMaturity = CalcUtils.DaysToYears(deal.Bond_Maturity_Date - baseDate); IInterestYieldVol interestYieldVol = InterestVolBase.GetYieldVol(factors, deal.Yield_Volatility, fCurrency); if ((deal.Amortisation) != null && (deal.Amortisation.Count > 0)) { notional = deal.Amortisation.GetPrincipal(notional, deal.Expiry_Date); } bool respectDefault = Respect_Default == YesNo.Yes && fCreditRating != null; using (IntraValuationDiagnosticsHelper.StartDeal(fIntraValuationDiagnosticsWriter, Deal)) { using (var pricerCache = Vector.Cache(factors.NumScenarios)) { Vector defaultTime = null; Vector bondIsAlive = null; Vector historicalRecovery = null; if (respectDefault) { defaultTime = pricerCache.Get(); bondIsAlive = pricerCache.Get(1.0); historicalRecovery = pricerCache.GetClear(); fCreditRating.DefaultTime(defaultTime); } var defaultedBeforeBaseDate = respectDefault && CreditRating.DefaultedBeforeBaseDate(fCreditRating, baseDate); VectorEngine.For(tgi, () => { using (IntraValuationDiagnosticsHelper.StartValuation(fIntraValuationDiagnosticsWriter, tgi.Date)) { using (var cache = Vector.Cache(factors.NumScenarios)) { Vector optionValue = cache.GetClear(); Vector stdDev = cache.Get(); // Std.Dev of Price Vector stdDevYield = cache.Get(); //Std.Dev of Yield Vector price = cache.Get(); Vector yield = cache.Get(); Vector macaulayDuration = cache.Get(); Vector bondValue = cache.Get(); Vector df = cache.Get(); Vector dfr = fRepoIsDiscount ? null : cache.Get(); if (defaultedBeforeBaseDate) { result.AppendVector(tgi.Date, optionValue); return(LoopAction.Break); } // This BondPrice function returns the value of the bond cashflows after ExpiryDate, including accrual, discounted back to T.date double accrual, cash; PricingFunctions.BondPrice(bondValue, out accrual, out cash, baseDate, tgi.Date, deal.Expiry_Date, deal.Issue_Date, deal.Bond_Maturity_Date, notional, coupon, fPayDates, fAccruals, fDiscountRate, deal.Amortisation, fPrincipals, fFinalPrincipal, fSurvivalProb, +1.0); // Now check scenario by scenario for defaults, overwriting bondValue as necessary if (respectDefault) { AdjustBondValueForDefault(notional, tExpiry, bondValue, bondIsAlive, historicalRecovery, defaultTime, tgi.T, fDiscountRate, fRecoveryRate); } // convert price and duration to forward (tExpiry) basis if (tgi.Date == deal.Expiry_Date) { optionValue.Assign(buySign * VectorMath.Max(0.0, paySign * (bondValue - notional * fStrike))); cashAccumulators.Accumulate(fFxRate, tgi.Date, optionValue); } else { fDiscountRate.GetValue(df, tgi.T, tExpiry); if (fRepoIsDiscount) { dfr = df; } else { fRepoRate.GetValue(dfr, tgi.T, tExpiry); } // Need yield and duration to convert yield vol to price vol. PricingFunctions.BondForwardPriceAndAdjustedMacaulayDuration(price, macaulayDuration, tgi.T, tExpiry, tMaturity, coupon, interval, df, fDiscountRate, fSurvivalProb); PricingFunctions.BondYieldFromPrice(yield, tExpiry, tMaturity, coupon, interval, price); // Calculate Modified Duration from Macaulay Duration. Vector modifiedDuration = cache.GetClear(); PricingFunctions.GetModifiedDuration(modifiedDuration, macaulayDuration, yield, interval); // Calculate Std.Dev of Yield and Price interestYieldVol.GetStdDev(stdDevYield, tgi.T, yield, fStrikeYield, tExpiry, tMaturity - tExpiry); stdDev.Assign(modifiedDuration * stdDevYield); if (interestYieldVol.GetDistributionType() == ProbabilityDistribution.Lognormal) { stdDev.MultiplyBy(yield); } price.AssignQuotient(bondValue, df); PricingFunctions.BlackFunction(optionValue, deal.Option_Type, price, notional * fStrike, stdDev); optionValue.MultiplyBy(buySign * dfr); if (fIntraValuationDiagnosticsWriter.Level > IntraValuationDiagnosticsLevel.None) { // Add Intra-valuation Diagnostics using (var volatilitiesAtDateStore = IntraValuationDiagnosticsHelper.CreateVolatilitiesAtDateStore(fIntraValuationDiagnosticsWriter, factors.NumScenarios)) using (var volatilitiesYieldAtDateStore = IntraValuationDiagnosticsHelper.CreateVolatilitiesAtDateStore(fIntraValuationDiagnosticsWriter, factors.NumScenarios)) { volatilitiesAtDateStore.Add(tgi.Date, tgi.TimeGrid.fEndDate, stdDev); volatilitiesYieldAtDateStore.Add(tgi.Date, tgi.TimeGrid.fEndDate, stdDevYield); IntraValuationDiagnosticsHelper.AddBondOptionProperties(fIntraValuationDiagnosticsWriter, price, dfr, bondValue, accrual, volatilitiesAtDateStore, volatilitiesYieldAtDateStore); IntraValuationDiagnosticsHelper.AddCashflowsPV(fIntraValuationDiagnosticsWriter, optionValue); } } } result.AppendVector(tgi.Date, fFxRate.Get(tgi.T) * optionValue); return(LoopAction.Continue); } } }); } result.Complete(fT); } }
/// <summary> /// Prepare for valuation. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); CFGeneralInterestSpreadListDeal deal = (CFGeneralInterestSpreadListDeal)Deal; // Get spread flow characteristics SpreadCashflowListCharacteristics spreadCashflowCharacteristics = fCashflows.ValuationPriceFactorDependencies(factors.BaseDate, fCurrency, fForecastCurrency, fForecast2Currency); // vols for first forecast rate if (spreadCashflowCharacteristics.NeedForecast1YieldVol) { fForecast1YieldVol = InterestVolBase.GetYieldVol(factors, deal.Forecast_Rate1_Swaption_Volatility, fForecastCurrency); } if (spreadCashflowCharacteristics.NeedForecast1RateVol) { fForecast1RateVol = InterestVolBase.GetRateVol(factors, deal.Forecast_Rate1_Cap_Volatility, fForecastCurrency); } // vols for second forecast rate if (spreadCashflowCharacteristics.NeedForecast2YieldVol) { fForecast2YieldVol = InterestVolBase.GetYieldVol(factors, deal.Forecast_Rate2_Swaption_Volatility, fForecast2Currency); } if (spreadCashflowCharacteristics.NeedForecast2RateVol) { fForecast2RateVol = InterestVolBase.GetRateVol(factors, deal.Forecast_Rate2_Cap_Volatility, fForecast2Currency); } // vols for discount rate if (spreadCashflowCharacteristics.NeedDiscountYieldVol) { fDiscountYieldVol = InterestVolBase.GetYieldVol(factors, deal.Discount_Rate_Swaption_Volatility, fCurrency); } if (spreadCashflowCharacteristics.NeedDiscountRateVol) { fDiscountRateVol = InterestVolBase.GetRateVol(factors, deal.Discount_Rate_Cap_Volatility, fCurrency); } bool convexity = spreadCashflowCharacteristics.NeedDiscountYieldVol || spreadCashflowCharacteristics.NeedDiscountRateVol; if (fForecastCurrency != fCurrency) { if (Quanto_Correction == YesNo.Yes) { // fx vol, fx/ir correl and forecast/discount correl fFx1Vol = FXVolHelper.Get(factors, fForecastCurrency, fCurrency); fForecast1Fx1Correl = CorrelationHelper.Get(factors, typeof(InterestRate), fForecastCurrency, null, typeof(FxRate), fForecastCurrency, fCurrency); } if (convexity) { fForecast1DiscountCorrel = CorrelationHelper.Get(factors, typeof(InterestRate), fCurrency, null, typeof(InterestRate), fForecastCurrency, null); } } if (fForecast2Currency != fCurrency) { if (Quanto_Correction == YesNo.Yes) { // fx vol, fx/ir correl and forecast/discount correl fFx2Vol = FXVolHelper.Get(factors, fForecast2Currency, fCurrency); fForecast2Fx2Correl = CorrelationHelper.Get(factors, typeof(InterestRate), fForecast2Currency, null, typeof(FxRate), fForecast2Currency, fCurrency); } if (convexity) { fForecast2DiscountCorrel = CorrelationHelper.Get(factors, typeof(InterestRate), fCurrency, null, typeof(InterestRate), fForecast2Currency, null); } } if (spreadCashflowCharacteristics.NeedForecast1Forecast2Correlation) { if (fForecastCurrency == fForecast2Currency) { // correl between forecast rates in same currency fForecast1Forecast2Correls = factors.Get <CMSRateCorrelations>(fForecastCurrency); } else { fForecast1Forecast2Correl = CorrelationHelper.Get(factors, typeof(InterestRate), fForecastCurrency, null, typeof(InterestRate), fForecast2Currency, null); } } }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); CFGeneralInterestSpreadListDeal deal = (CFGeneralInterestSpreadListDeal)Deal; // Collect registered volatility price factors to check they have the same distribution type var volPriceFactors = new List <IInterestVol>(); // Get spread flow characteristics SpreadCashflowListCharacteristics spreadCashflowCharacteristics = deal.Cashflows.ValuationPriceFactorDependencies(factors.BaseDate, fCurrency, fForecastCurrency, fForecast2Currency); // register volatility surfaces for forecast rate1 if (spreadCashflowCharacteristics.NeedForecast1YieldVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestYieldVol(factors, deal.Forecast_Rate1_Swaption_Volatility, fForecastCurrency)); } if (spreadCashflowCharacteristics.NeedForecast1RateVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestRateVol(factors, deal.Forecast_Rate1_Cap_Volatility, fForecastCurrency)); } // register volatility surfaces for forecast rate2 if (spreadCashflowCharacteristics.NeedForecast2YieldVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestYieldVol(factors, deal.Forecast_Rate2_Swaption_Volatility, fForecast2Currency)); } if (spreadCashflowCharacteristics.NeedForecast2RateVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestRateVol(factors, deal.Forecast_Rate2_Cap_Volatility, fForecast2Currency)); } // vol surfaces for discount rate if (spreadCashflowCharacteristics.NeedDiscountYieldVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestYieldVol(factors, deal.Discount_Rate_Swaption_Volatility, fCurrency)); } if (spreadCashflowCharacteristics.NeedDiscountRateVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestRateVol(factors, deal.Discount_Rate_Cap_Volatility, fCurrency)); } bool convexity = spreadCashflowCharacteristics.NeedDiscountYieldVol || spreadCashflowCharacteristics.NeedDiscountRateVol; if (fForecastCurrency != fCurrency) { if (Quanto_Correction == YesNo.Yes) { // fx vol, fx/ir correl and forecast/discount correl FXVolHelper.Register(factors, fForecastCurrency, fCurrency); CorrelationHelper.Register(factors, typeof(IInterestRate), fForecastCurrency, null, typeof(IFxRate), fForecastCurrency, fCurrency); } if (convexity) { CorrelationHelper.Register(factors, typeof(IInterestRate), fCurrency, null, typeof(IInterestRate), fForecastCurrency, null); } } if (fForecast2Currency != fCurrency) { if (Quanto_Correction == YesNo.Yes) { // fx vol, fx/ir correl and forecast/discount correl FXVolHelper.Register(factors, fForecast2Currency, fCurrency); CorrelationHelper.Register(factors, typeof(IInterestRate), fForecast2Currency, null, typeof(IFxRate), fForecast2Currency, fCurrency); } if (convexity) { CorrelationHelper.Register(factors, typeof(IInterestRate), fCurrency, null, typeof(IInterestRate), fForecast2Currency, null); } } if (spreadCashflowCharacteristics.NeedForecast1Forecast2Correlation) { if (fForecastCurrency == fForecast2Currency) { // correl between forecast rates in same currency factors.Register <CMSRateCorrelations>(fForecastCurrency); } else { CorrelationHelper.Register(factors, typeof(IInterestRate), fForecastCurrency, null, typeof(IInterestRate), fForecast2Currency, null); } } if (volPriceFactors.Select(pf => pf.GetDistributionType()).Distinct().Count() > 1) { Deal.AddToErrors(errors, "Volatility price factors must have the same distribution type."); } ValidateUnnecessaryVolatilities(deal, spreadCashflowCharacteristics, errors); }
/// <summary> /// Register price factors used in valuation. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); CFFloatingInterestListDeal deal = (CFFloatingInterestListDeal)Deal; // Deal validation specific to CFFloatingInterestListValuation foreach (var cashflow in deal.Cashflows) { if (!cashflow.Resets.Any()) { continue; } var lastResetDate = cashflow.Resets.Last().Reset_Date; if (cashflow.FX_Reset_Date > 0.0 && cashflow.FX_Reset_Date < lastResetDate) { errors.Add(ErrorLevel.Warning, string.Format("Quanto adjustments for cashflow paying on {0} are not supported when the FX reset date {1} is before interest rate reset date {2}", cashflow.Payment_Date, cashflow.FX_Reset_Date, lastResetDate)); } } // Get characteristics CashflowListCharacteristics characteristics = deal.Cashflows.Analyze(factors.BaseDate); bool quanto = fForecastIsForeign && characteristics.HasQuanto && Quanto_Correction == YesNo.Yes; bool convexity = !characteristics.IsStandardLibor && Convexity_Correction == YesNo.Yes; var requirements = new VolatilityRequirements( characteristics.HasCms, characteristics.HasLibor && (characteristics.HasOptionlet || convexity || quanto), characteristics.HasCms && convexity, characteristics.HasLibor && convexity); // Collect registered volatility price factors to check they have the same distribution type var volPriceFactors = new List <IInterestVol>(); // register forecast rate volatility surfaces if (requirements.NeedForecastYieldVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestYieldVol(factors, deal.Forecast_Rate_Swaption_Volatility, fForecastCurrency)); } if (requirements.NeedForecastRateVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestRateVol(factors, deal.Forecast_Rate_Cap_Volatility, fForecastCurrency)); } if (requirements.NeedDiscountYieldVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestYieldVol(factors, deal.Discount_Rate_Swaption_Volatility, fCurrency)); } if (requirements.NeedDiscountRateVol) { volPriceFactors.Add(InterestVolBase.RegisterInterestRateVol(factors, deal.Discount_Rate_Cap_Volatility, fCurrency)); } if (fForecastIsForeign) { // Register factor for translation from forecast rate currency to settlement currency for cashflows with FX reset date if (characteristics.HasFXReset) { factors.RegisterInterface <IFxRate>(fForecastCurrency); } if (quanto) { FXVolHelper.Register(factors, fForecastCurrency, fCurrency); CorrelationHelper.Register(factors, typeof(IInterestRate), fForecastCurrency, null, typeof(IFxRate), fForecastCurrency, fCurrency); CorrelationHelper.Register(factors, typeof(IInterestRate), fForecastCurrency, null, typeof(IInterestRate), fCurrency, null); } } if (volPriceFactors.Select(pf => pf.GetDistributionType()).Distinct().Count() > 1) { deal.AddToErrors(errors, "Volatility price factors must have the same distribution type."); } ValidateUnnecessaryVolatilities(deal, requirements, errors); }