public void CapletRateCouponAnalyicsNonDiscounted() { foreach (var val in paramRange) { IRateCouponParameters analyticModelParameters = new RateCouponParameters { Rate = .05m, DiscountType = DiscountType.None, IsCall = true, YearFraction = 0.25m, NotionalAmount = 10000000m, HasReset = false, Volatility = .20m, Strike = .05m, EndDiscountFactor = 0.9m, PaymentDiscountFactor = 0.99m, StartDiscountFactor = 1.0m, ExpiryYearFraction = val, CurveYearFraction = val, PeriodAsTimesPerYear = 0.25m }; var model = new RateOptionCouponAnalytic { AnalyticParameters = analyticModelParameters }; var result = model.ExpectedValue; var delta1 = model.Delta1; var delta0 = model.Delta0; Debug.Print("ExpectedValue1 : {0} Delta1 : {1} Delta0 : {3} CurveYearFraction : {2} ", result, delta1, analyticModelParameters.CurveYearFraction, delta0); } foreach (var val in paramRange) { IRateCouponParameters analyticModelParameters = new RateCouponParameters { Rate = .05m, DiscountType = DiscountType.None, IsCall = true, YearFraction = val, NotionalAmount = 10000000m, HasReset = false, Volatility = .20m, Strike = .05m, EndDiscountFactor = 0.9m, PaymentDiscountFactor = 0.99m, StartDiscountFactor = 1.0m, ExpiryYearFraction = val, CurveYearFraction = val, PeriodAsTimesPerYear = 0.25m }; var model = new RateOptionCouponAnalytic { AnalyticParameters = analyticModelParameters }; var result = model.ExpectedValue; var delta1 = model.Delta1; var delta0 = model.Delta0; Debug.Print("ExpectedValue2 : {0} Delta1 : {1} Delta0 : {4} CurveYearFraction : {2} YearFraction : {3}", result, delta1, analyticModelParameters.CurveYearFraction, analyticModelParameters.YearFraction, delta0); } foreach (var val in paramRange) { IRateCouponParameters analyticModelParameters = new RateCouponParameters { Rate = .05m, DiscountType = DiscountType.None, IsCall = true, YearFraction = 0.25m, NotionalAmount = 10000000m, HasReset = false, Volatility = .20m, Strike = val, EndDiscountFactor = 0.9m, PaymentDiscountFactor = 0.99m, StartDiscountFactor = 1.0m, ExpiryYearFraction = 3.0m, CurveYearFraction = 3.0m, PeriodAsTimesPerYear = 0.25m }; var model = new RateOptionCouponAnalytic { AnalyticParameters = analyticModelParameters }; var result = model.ExpectedValue; var delta1 = model.Delta1; var delta0 = model.Delta0; Debug.Print("ExpectedValue3 : {0} Delta1 : {1} Delta0 : {4} ForwardRate : {2} Strike : {3}", result, delta1, analyticModelParameters.Rate, analyticModelParameters.Strike, delta0); } foreach (var val in paramRange) { IRateCouponParameters analyticModelParameters = new RateCouponParameters { Rate = .05m, DiscountType = DiscountType.None, IsCall = true, YearFraction = 0.25m, NotionalAmount = 10000000m, HasReset = false, Volatility = val, Strike = .05m, EndDiscountFactor = 0.9m, PaymentDiscountFactor = 0.99m, StartDiscountFactor = 1.0m, ExpiryYearFraction = 3.0m, CurveYearFraction = 3.0m, PeriodAsTimesPerYear = 0.25m }; var model = new RateOptionCouponAnalytic { AnalyticParameters = analyticModelParameters }; var result = model.ExpectedValue; var delta1 = model.Delta1; var delta0 = model.Delta0; Debug.Print("ExpectedValue4 : {0} Delta1 : {1} Delta0 : {3} Volatility : {2}", result, delta1, analyticModelParameters.Volatility, delta0); } foreach (var val in paramRange) { IRateCouponParameters analyticModelParameters = new RateCouponParameters { Rate = .05m, DiscountType = DiscountType.None, IsCall = true, YearFraction = 0.25m, NotionalAmount = 10000000m, HasReset = false, Volatility = 0.2m, Strike = val, EndDiscountFactor = 0.9m, PaymentDiscountFactor = 0.99m, StartDiscountFactor = 1.0m, ExpiryYearFraction = 3.0m, CurveYearFraction = 3.0m, PeriodAsTimesPerYear = 0.25m }; var model = new RateOptionCouponAnalytic { AnalyticParameters = analyticModelParameters }; var result = model.ExpectedValue; var delta1 = model.Delta1; var delta0 = model.Delta0; Debug.Print("ExpectedValue5 : {0} Delta1 : {1} Delta0 : {3} Strike : {2}", result, delta1, analyticModelParameters.Strike, delta0); } }
/// <summary> /// Calculates the specified model data. /// </summary> /// <param name="modelData">The model data.</param> /// <returns></returns> public override AssetValuation Calculate(IInstrumentControllerData modelData) { ModelData = modelData; AnalyticModelParameters = null; AnalyticsModel = new RateOptionCouponAnalytic(); RequiresReset = modelData.ValuationDate > ResetDate; IsRealised = HasBeenRealised(ModelData.ValuationDate); TimeToExpiry = GetPaymentYearFraction(ModelData.ValuationDate, AdjustedFixingDate); var volatilityCurveNodeTime = GetPaymentYearFraction(ModelData.ValuationDate, AccrualStartDate); IFxCurve fxCurve = null; IRateCurve discountCurve = null; IRateCurve forecastCurve = null; IVolatilitySurface indexVolSurface = null; //Add the extra metrics required var quotes = ModelData.AssetValuation.quote.ToList(); if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.BreakEvenRate.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.BreakEvenRate.ToString(), "DecimalValue"); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.AccrualFactor.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.AccrualFactor.ToString(), "DecimalValue"); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.FloatingNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.FloatingNPV.ToString(), "DecimalValue"); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.NPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue"); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.LocalCurrencyNPV.ToString(), "DecimalValue"); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyExpectedValue.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.LocalCurrencyExpectedValue.ToString(), "DecimalValue"); quotes.Add(quote); } //Check if risk calc are required. bool delta1PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta1PDH.ToString()) != null || AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta1PDH.ToString()) != null; //Check if risk calc are required. bool delta0PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta0PDH.ToString()) != null || AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta0PDH.ToString()) != null; ModelData.AssetValuation.quote = quotes.ToArray(); var metrics = ResolveModelMetrics(AnalyticsModel.Metrics); //// Determine if DFAM has been requested - if so that is all we evaluate - every other metric is ignored //if (metrics.Contains(InstrumentMetrics.DiscountFactorAtMaturity)) //{ // metrics.RemoveAll(metricItem => metricItem != InstrumentMetrics.DiscountFactorAtMaturity); //} //Set the forecast rate dates. The ForecastRateInterpolation should have been set. ForwardStartDate = AccrualStartDate; ForwardEndDate = ForecastRateInterpolation ? AccrualEndDate : AdjustedDateHelper.ToAdjustedDate(FixingCalendar, ForecastRateIndex.indexTenor.Add(ForwardStartDate), AccrualBusinessDayAdjustments); //Set the strike var strike1 = 0.0m; var strike2 = 0.0m; var isCollar = false; if (PriceableCouponType == CouponType.Cap) { if (CapStrike != null) { strike1 = (decimal)CapStrike; } } if (PriceableCouponType == CouponType.Floor) { if (FloorStrike != null) { strike1 = (decimal)FloorStrike; } } if (PriceableCouponType == CouponType.Collar)//TODO Need to add the Floor calculation which will require a new model or extension of the current model. { if (CapStrike != null) { strike1 = (decimal)CapStrike; } if (FloorStrike != null) { strike2 = (decimal)FloorStrike; } isCollar = true; } //var metricsToEvaluate = metrics.ToArray(); if (metrics.Count > 0) { YearFractionToCashFlowPayment = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate); var reportingCurrency = ModelData.ReportingCurrency == null ? PaymentCurrency.Value : ModelData.ReportingCurrency.Value; IRateCouponParameters analyticModelParameters = new RateCouponParameters { Multiplier = Multiplier, ValuationDate = modelData.ValuationDate, PaymentDate = PaymentDate, Currency = PaymentCurrency.Value, ReportingCurrency = reportingCurrency, DiscountType = DiscountType, IsRealised = IsRealised, HasReset = RequiresReset, NotionalAmount = NotionalAmount.amount, Spread = Margin, YearFraction = CouponYearFraction, CurveYearFraction = YearFractionToCashFlowPayment, ExpiryYearFraction = TimeToExpiry, IsCall = IsCall }; // Curve Related if (modelData.MarketEnvironment is ISwapLegEnvironment environment) { var streamMarket = environment; discountCurve = streamMarket.GetDiscountRateCurve(); discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; forecastCurve = streamMarket.GetForecastRateCurve(); forecastCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; indexVolSurface = streamMarket.GetVolatilitySurface(); indexVolSurface.PricingStructureEvolutionType = PricingStructureEvolutionType; DiscountCurveName = discountCurve.GetPricingStructureId().UniqueIdentifier; ForecastCurveName = forecastCurve.GetPricingStructureId().UniqueIdentifier; VolatilitySurfaceName = indexVolSurface.GetPricingStructureId().UniqueIdentifier; // Bucketed Delta if (BucketedDates.Length > 1) { analyticModelParameters.PeriodAsTimesPerYear = GetPaymentYearFraction(BucketedDates[0], BucketedDates[1]); analyticModelParameters.BucketedDiscountFactors = GetBucketedDiscountFactors(discountCurve, ModelData. ValuationDate, BucketedDates); } //Check for currency. if (ModelData.ReportingCurrency != null) { if (ModelData.ReportingCurrency.Value != PaymentCurrency.Value) { fxCurve = streamMarket.GetReportingCurrencyFxCurve(); fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; } } } else if (modelData.MarketEnvironment.GetType() == typeof(MarketEnvironment)) { var market = (MarketEnvironment)modelData.MarketEnvironment; discountCurve = (IRateCurve)market.SearchForPricingStructureType(DiscountCurveName); discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; forecastCurve = (IRateCurve)market.SearchForPricingStructureType(ForecastCurveName); forecastCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; indexVolSurface = (IVolatilitySurface)market.SearchForPricingStructureType(VolatilitySurfaceName); indexVolSurface.PricingStructureEvolutionType = PricingStructureEvolutionType; if (!UseObservedRate) { Rate = GetRate(ForwardStartDate, ForwardEndDate, forecastCurve, ModelData.ValuationDate); } //the rate params analyticModelParameters.Rate = GetRate(ForwardStartDate, ForwardEndDate, forecastCurve, ModelData.ValuationDate); // Bucketed Delta if (BucketedDates.Length > 1) { analyticModelParameters.PeriodAsTimesPerYear = GetPaymentYearFraction(BucketedDates[0], BucketedDates[1]); analyticModelParameters.BucketedDiscountFactors = GetBucketedDiscountFactors(discountCurve, ModelData. ValuationDate, BucketedDates); } if (delta1PDH) { var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta1PDH"); analyticModelParameters.Delta1PDHCurves = riskMarket; analyticModelParameters.Delta1PDHPerturbation = 10; } if (delta0PDH) { var riskMarket = market.SearchForPerturbedPricingStructures(ForecastCurveName, "delta0PDH"); analyticModelParameters.Delta0PDHCurves = riskMarket; analyticModelParameters.Delta0PDHPerturbation = 10; } //Check for currency. if (ModelData.ReportingCurrency != null) { if (ModelData.ReportingCurrency.Value != PaymentCurrency.Value) { string curveName = MarketEnvironmentHelper.ResolveFxCurveNames(PaymentCurrency.Value, modelData.ReportingCurrency.Value); fxCurve = (IFxCurve)market.SearchForPricingStructureType(curveName); fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; } } } analyticModelParameters.DiscountCurve = discountCurve; analyticModelParameters.ForecastCurve = forecastCurve; analyticModelParameters.VolatilitySurface = indexVolSurface; analyticModelParameters.ReportingCurrencyFxCurve = fxCurve; AnalyticModelParameters = analyticModelParameters; //Set the base rate. Default is zero if (AnalyticModelParameters != null) { AnalyticModelParameters.BaseRate = BaseRate; } if (UseObservedRate) { AnalyticsModel = new FixedRateCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, Rate, analyticModelParameters.YearFraction, DiscountType, fxCurve, discountCurve, forecastCurve); if (Rate != null) { analyticModelParameters.Rate = (decimal)Rate; } } if (!isCollar) { AnalyticsModel = new RateOptionCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, volatilityCurveNodeTime, strike1, fxCurve, discountCurve, forecastCurve, indexVolSurface); } else { AnalyticsModel = new RateOptionCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, volatilityCurveNodeTime, strike1, strike2, fxCurve, discountCurve, forecastCurve, indexVolSurface); } CalculationResults = AnalyticsModel.Calculate <IRateInstrumentResults, RateInstrumentResults>(AnalyticModelParameters, metrics.ToArray()); CalculationPerformedIndicator = true; PaymentDiscountFactor = ((FixedRateCouponAnalytic)AnalyticsModel).PaymentDiscountFactor; if (!UseObservedRate) { Rate = CalculationResults.BreakEvenRate; } ForecastAmount = MoneyHelper.GetAmount(CalculationResults.LocalCurrencyExpectedValue, PaymentAmount.currency); NPV = MoneyHelper.GetAmount(CalculationResults.LocalCurrencyNPV, PaymentAmount.currency); } AssetValuation valuation = GetValue(CalculationResults, modelData.ValuationDate); valuation.id = Id; return(valuation); }