/// <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> /// Warn of unnecessary volatility surface definitions. /// </summary> /// <remarks> /// Test differently if the cap and swaption volatility definitions are the same or /// distinct because they may have been set by a single property or two distinct ones. /// </remarks> private static void ValidateUnnecessaryVolatilities(CFGeneralInterestSpreadListDeal deal, SpreadCashflowListCharacteristics characteristics, ErrorList errors) { if (deal.Discount_Rate_Cap_Volatility == deal.Discount_Rate_Swaption_Volatility) { if (!characteristics.NeedDiscountRateVol && !characteristics.NeedDiscountYieldVol && !string.IsNullOrEmpty(deal.Discount_Rate_Cap_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Discount_Rate_Cap_Volatility)} and {nameof(deal.Discount_Rate_Swaption_Volatility)} {deal.Discount_Rate_Cap_Volatility}"); } } else { if (!characteristics.NeedDiscountRateVol && !string.IsNullOrEmpty(deal.Discount_Rate_Cap_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Discount_Rate_Cap_Volatility)} {deal.Discount_Rate_Cap_Volatility}"); } if (!characteristics.NeedDiscountYieldVol && !string.IsNullOrEmpty(deal.Discount_Rate_Swaption_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Discount_Rate_Swaption_Volatility)} {deal.Discount_Rate_Swaption_Volatility}"); } } if (deal.Forecast_Rate1_Cap_Volatility == deal.Forecast_Rate1_Swaption_Volatility) { if (!characteristics.NeedForecast1RateVol && !characteristics.NeedForecast1YieldVol && !string.IsNullOrEmpty(deal.Forecast_Rate1_Cap_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Forecast_Rate1_Cap_Volatility)} and {nameof(deal.Forecast_Rate1_Swaption_Volatility)} {deal.Forecast_Rate1_Cap_Volatility}."); } } else { if (!characteristics.NeedForecast1RateVol && !string.IsNullOrEmpty(deal.Forecast_Rate1_Cap_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Forecast_Rate1_Cap_Volatility)} {deal.Forecast_Rate1_Cap_Volatility}."); } if (!characteristics.NeedForecast1YieldVol && !string.IsNullOrEmpty(deal.Forecast_Rate1_Swaption_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Forecast_Rate1_Swaption_Volatility)} {deal.Forecast_Rate1_Swaption_Volatility}."); } } if (deal.Forecast_Rate2_Cap_Volatility == deal.Forecast_Rate2_Swaption_Volatility) { if (!characteristics.NeedForecast2RateVol && !characteristics.NeedForecast2YieldVol && !string.IsNullOrEmpty(deal.Forecast_Rate2_Cap_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Forecast_Rate2_Cap_Volatility)} and {nameof(deal.Forecast_Rate2_Swaption_Volatility)} {deal.Forecast_Rate2_Cap_Volatility}."); } } else { if (!characteristics.NeedForecast2RateVol && !string.IsNullOrEmpty(deal.Forecast_Rate2_Cap_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Forecast_Rate2_Cap_Volatility)} {deal.Forecast_Rate2_Cap_Volatility}."); } if (!characteristics.NeedForecast2YieldVol && !string.IsNullOrEmpty(deal.Forecast_Rate2_Swaption_Volatility)) { deal.AddToErrors(errors, ErrorLevel.Info, $"Unnecessary {nameof(deal.Forecast_Rate2_Swaption_Volatility)} {deal.Forecast_Rate2_Swaption_Volatility}."); } } }
/// <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); }