/// <summary> /// This assumes that the rest dates are consistent with the curve. /// </summary> /// <param name="valuationDate"></param> /// <param name="paymentDate">The payment date. The same rest period is assumed as with the spot date.</param> /// <param name="indexCurve">The index curve should be already in the correct form for the fx.</param> /// <param name="currency2">Normally the foreign rate curve.</param> /// <param name="currency2PerCurrency1">The currency2PerCurrency1 flag. </param> /// <param name="currency1">Normally the domestic rate curve. </param> /// <param name="indexVolatilitySurface">The index volatility surface. </param> /// <param name="expiryTime">The expiry time. </param> /// <param name="timeToIndex">The time to reset or expiry. </param> /// <param name="strike">The strike. </param> /// <param name="fxOptionType">The option type. </param> public FxOptionLegAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve, IRateCurve currency1, IRateCurve currency2, bool currency2PerCurrency1, decimal strike, decimal expiryTime, decimal timeToIndex, IVolatilitySurface indexVolatilitySurface, FxOptionType fxOptionType) { //ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); var todayRate = indexCurve.GetForward(valuationDate, valuationDate); //TODO The spot rate may not be the same due to the carry effect, but the evolution works. var df1 = currency1.GetDiscountFactor(valuationDate, paymentDate); var df2 = currency2.GetDiscountFactor(valuationDate, paymentDate); var forward = df1 / df2; if (!currency2PerCurrency1) { forward = df2 / df1; } ForwardFxRate = (decimal)(todayRate * forward); OptionType = fxOptionType; Strikes = new List <decimal> { strike }; ExpiryTimes = new List <decimal> { expiryTime }; TimeToIndices = new List <decimal> { timeToIndex }; Volatilities = new List <decimal> { (decimal)indexVolatilitySurface.GetValue((double)timeToIndex, (double)strike) }; }
/// <summary> /// Gets the discount factor. /// </summary> /// <param name="fxCurve">The fx curve.</param> /// <param name="targetDate">The target date.</param> /// <param name="valuationDate">The valuation date.</param> /// <returns></returns> public decimal GetForwardAtMaturity(IFxCurve fxCurve, DateTime targetDate, DateTime valuationDate) { var point = new DateTimePoint1D(valuationDate, targetDate); var discountFactor = (decimal)fxCurve.Value(point); return(discountFactor); }
/// <summary> /// Initiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="startDate">The start date of the coupon.</param> /// <param name="endDate">The end date of the coupon.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="timeToIndex">The timeToIndex. Not necessarily the time to expiry. This is used for surface interpolation..</param> /// <param name="strike">The strike.</param> /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param> /// <param name="discountCurve">The rate curve to use for discounting.</param> /// <param name="forecastCurve">The forecast curve.</param> /// <param name="indexVolSurface">The index volatility surface.</param> public RateOptionCouponAnalytic(DateTime valuationDate, DateTime startDate, DateTime endDate, DateTime paymentDate, decimal timeToIndex, decimal strike, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve, IRateCurve forecastCurve, IVolatilitySurface indexVolSurface) : base(valuationDate, startDate, endDate, paymentDate, reportingCurrencyFxCurve, discountCurve, forecastCurve) { Strike = strike; TimeToIndex = timeToIndex; Volatility = (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)strike); }
///// <param name="isCall">The isCall flag. If [true] then the the option is a call.</param> ///// <param name="rate">The rate.</param> ///// <param name="timeToExpiry">The time To Expiry.</param> /// <summary> /// Initiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="timeToIndex">The timeToIndex. Not necessarily the time to expiry. This is used for surface interpolation..</param> /// <param name="strike">The strike.</param> /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param> /// <param name="indexVolSurface">THe volatility surface to use. </param> ///// <param name="discountCurve">The rate curve to use for discounting.</param> public SimpleIRSwaptionInstrumentAnalytic(DateTime valuationDate, //DateTime paymentDate, bool isCall, decimal timeToIndex, decimal strike, //decimal timeToExpiry, decimal rate, IFxCurve reportingCurrencyFxCurve, IVolatilitySurface indexVolSurface) //IRateCurve discountCurve, /// <param name="paymentDate">The payment date of the cash flow.</param> { ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); TimeToIndex = timeToIndex; Strike = strike; Volatility = (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)strike); }
/// <summary> /// Evaluating the fx rate. /// </summary> /// <returns>The fx rate</returns> protected decimal EvaluateReportingCurrencyFxRate(DateTime valuationDate, IFxCurve fxCurve) { var result = 1.0m; if (fxCurve != null) { result = (decimal)fxCurve.GetForward(valuationDate, valuationDate); } return(result); }
/// <summary> /// Initiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param> /// <param name="indexCurve">The rate curve to use for calculating the forward index.</param> /// <param name="discountCurve">The rate curve to use for discounting.</param> public FxRateCashflowAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve reportingCurrencyFxCurve, ICurve indexCurve, IRateCurve discountCurve) { ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); if (indexCurve != null) { FloatingIndex = (decimal)indexCurve.GetValue(new DateTimePoint1D(valuationDate, paymentDate)).Value; } if (discountCurve != null) { PaymentDiscountFactor = (decimal)discountCurve.GetDiscountFactor(valuationDate, paymentDate); } }
/// <summary> /// This assumes that the rest dates are consistent with the curve. /// </summary> /// <param name="valuationDate"></param> /// <param name="paymentDate">The payment date. The same rest period is assumed as with the spot date.</param> /// <param name="indexCurve">The index curve should be already in the correct form for the fx.</param> /// <param name="currency2">Normaly the foreign rate curve.</param> /// <param name="currency2PerCurrency1">The currency2PerCurrency1 flag. </param> /// <param name="currency1">Normally the domestic rate curve. </param> public FxLegAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve, IRateCurve currency1, IRateCurve currency2, bool currency2PerCurrency1) { //ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); var todayRate = indexCurve.GetForward(valuationDate, valuationDate); //TODO The spot rate may not be the same due to the carry effect, but the evolution works. var df1 = currency1.GetDiscountFactor(valuationDate, paymentDate); var df2 = currency2.GetDiscountFactor(valuationDate, paymentDate); var forward = df1 / df2; if (!currency2PerCurrency1) { forward = df2 / df1; } ForwardFxRate = (decimal)(todayRate * forward); }
/// <summary> /// Initiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="reportingCurrencyFxCurve">The fx curve. It must already be normalised.</param> /// <param name="discountCurve">The rate curve to use for discounting.</param> public CashflowAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve) { ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); PaymentDiscountFactor = EvaluateDiscountFactor(valuationDate, paymentDate, discountCurve); var paymentDiscountFactor = PaymentDiscountFactor; var days = (paymentDate - valuationDate).Days; if (days == 0) { days = 1; paymentDiscountFactor = EvaluateDiscountFactor(valuationDate, paymentDate.AddDays(1), discountCurve); } var time = days / 365.25; ContinuousRate = -(Decimal)(Math.Log((double)paymentDiscountFactor) / time); }
/// <summary> /// Intantiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param> /// <param name="indexCurve">The rate curve to use for calculating the forward index.</param> /// <param name="discountCurve">The rate curve to use for discounting.</param> /// <param name="indexVolSurface">The index volatility surface.</param> /// <param name="expiryTime">The expiry time. </param> /// <param name="timeToIndex">The time to reset or expiry. </param> /// <param name="strike">The strike. </param> /// <param name="fxOptionType">The option type. </param> public FxOptionAnalytic(DateTime valuationDate, DateTime paymentDate, decimal strike, decimal expiryTime, decimal timeToIndex, IFxCurve reportingCurrencyFxCurve, ICurve indexCurve, IRateCurve discountCurve, IVolatilitySurface indexVolSurface, FxOptionType fxOptionType) : base(valuationDate, paymentDate, reportingCurrencyFxCurve, indexCurve, discountCurve) { OptionType = fxOptionType; Strikes = new List <decimal> { strike }; ExpiryTimes = new List <decimal> { expiryTime }; TimeToIndices = new List <decimal> { timeToIndex }; Volatilities = new List <decimal> { (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)strike) }; }
/// <summary> /// This assumes that the rest dates are consistent with the curve. /// </summary> /// <param name="valuationDate"></param> /// <param name="paymentDate"></param> /// <param name="indexCurve"></param> /// <param name="expiryTime">The expiry time. </param> /// <param name="timeToIndex">The time to reset or expiry. </param> /// <param name="strike">The strike. </param> /// <param name="indexVolatilitySurface">The index volatility surface. </param> /// <param name="fxOptionType">The option type. </param> public FxOptionLegAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve, decimal strike, decimal expiryTime, decimal timeToIndex , IVolatilitySurface indexVolatilitySurface, FxOptionType fxOptionType) { //ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); ForwardFxRate = (decimal)indexCurve.GetForward(valuationDate, paymentDate); OptionType = fxOptionType; Strikes = new List <decimal> { strike }; ExpiryTimes = new List <decimal> { expiryTime }; TimeToIndices = new List <decimal> { timeToIndex }; Volatilities = new List <decimal> { (decimal)indexVolatilitySurface.GetValue((double)timeToIndex, (double)strike) }; }
/// <summary> /// Initializes a new instance of the <see cref="RateXccySpreadCurve"/> class, /// by applying spreads to an existing RateCurve. Using FX Curve to create synthetic swaps /// for the period under 1Y. /// </summary> /// <param name="logger">The logger.</param> /// <param name="cache">The cache.</param> /// <param name="nameSpace">THe client namespace</param> /// <param name="properties">The properties of the new curve. One of the mandatory properties for this curve type: /// CutOverTerm, is the tenor at which point all Fx Curve points are removed form the RateXccyCurve bootstrap. /// Normally this is 1Y.</param> /// <param name="currency1Curve">The base zero curve.</param> /// <param name="fxCurve">The FX curve, used for constructing synthetic deposits. The fx points map from the base curve to the non-base curve.</param> /// <param name="currency2Curve">The non-Base Curve.</param> /// <param name="spreadInstruments">The spread instruments and their values.</param> /// <param name="fixingCalendar">The fixingCalendar.</param> /// <param name="rollCalendar">The rollCalendar.</param> public RateXccySpreadCurve(ILogger logger, ICoreCache cache, String nameSpace, NamedValueSet properties, RateCurve currency1Curve, IFxCurve fxCurve, RateCurve currency2Curve, QuotedAssetSet spreadInstruments, IBusinessCalendar fixingCalendar, IBusinessCalendar rollCalendar) : base(logger, cache, nameSpace, new RateCurveIdentifier(properties)) { //Set the base curve. BaseCurve = currency1Curve; ReferenceCurveId = BaseCurve.GetPricingStructureId(); //PricingStructureIdentifier = new RateCurveIdentifier(properties); Currency2Curve = currency2Curve; //Get the cut-over date. var cutOverTerm = properties.GetValue <string>("CutOverTerm"); if (cutOverTerm != null) { CutOverTerm = PeriodHelper.Parse(cutOverTerm); } //set the fx curve. ReferenceFxCurve = fxCurve; IsCurrency1RateCurve = properties.GetValue <bool>("Currency1RateCurve"); //Check the pricing structure type. var pricingStructureId = (RateCurveIdentifier)PricingStructureIdentifier; if (pricingStructureId.PricingStructureType != PricingStructureTypeEnum.RateXccyCurve || ReferenceFxCurve == null) { return; } //There must be a valid quoted asset set in order to bootstrap. if (!XsdClassesFieldResolver.QuotedAssetSetIsValid(spreadInstruments)) { return; } PriceableRateSpreadAssets = PriceableAssetFactory.CreatePriceableRateSpreadAssets(logger, cache, nameSpace, pricingStructureId.BaseDate, spreadInstruments, fixingCalendar, rollCalendar); Build(logger, cache, nameSpace, fixingCalendar, rollCalendar); }
/// <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; CalculationResults = null; UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval)); // 1. First derive the analytics to be evaluated via the stream controller model // NOTE: These take precendence of the child model metrics if (AnalyticsModel == null) { AnalyticsModel = new SimpleXccySwapInstrumentAnalytic(); } var swapControllerMetrics = ResolveModelMetrics(AnalyticsModel.Metrics); AssetValuation swapValuation; var quotes = ModelData.AssetValuation.quote.ToList(); 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); } ModelData.AssetValuation.quote = quotes.ToArray(); //Sets the evolution type for calculations. foreach (var leg in Legs) { leg.PricingStructureEvolutionType = PricingStructureEvolutionType; leg.BucketedDates = BucketedDates; leg.Multiplier = Multiplier; } if (AdditionalPayments != null) { foreach (var payment in AdditionalPayments) { payment.PricingStructureEvolutionType = PricingStructureEvolutionType; payment.BucketedDates = BucketedDates; payment.Multiplier = Multiplier; } } var legControllers = new List <InstrumentControllerBase> { PayLeg, ReceiveLeg }; //The assetValuation list. var childValuations = new List <AssetValuation>(); // 2. Now evaluate only the child specific metrics (if any) if (modelData.MarketEnvironment is ISwapLegEnvironment) { var market = (SwapLegEnvironment)modelData.MarketEnvironment; IRateCurve discountCurve = null; IRateCurve forecastCurve = null; IFxCurve currencyCurve = null; foreach (var leg in legControllers) { var stream = (PriceableInterestRateStream)leg; if (modelData.ReportingCurrency == null) { modelData.ReportingCurrency = stream.Currency; } if (stream.DiscountCurveName != null) { discountCurve = market.GetDiscountRateCurve(); } if (stream.ForecastCurveName != null) { forecastCurve = market.GetForecastRateCurve(); } if (modelData.ReportingCurrency.Value != stream.Currency.Value) { //stream.ReportingCurrencyFxCurveName = // MarketEnvironmentHelper.ResolveFxCurveNames(stream.Currency.Value, modelData.ReportingCurrency.Value); currencyCurve = market.GetReportingCurrencyFxCurve(); } modelData.MarketEnvironment = MarketEnvironmentHelper.CreateInterestRateStreamEnvironment(modelData.ValuationDate, discountCurve, forecastCurve, currencyCurve); childValuations.Add(leg.Calculate(modelData)); } if (GetAdditionalPayments() != null) { var paymentControllers = new List <InstrumentControllerBase>(GetAdditionalPayments()); childValuations.AddRange(paymentControllers.Select(payment => payment.Calculate(modelData))); } } else { childValuations = EvaluateChildMetrics(legControllers, modelData, Metrics); } var childControllerValuations = AssetValuationHelper.AggregateMetrics(childValuations, new List <string>(Metrics), PaymentCurrencies);// modelData.ValuationDate); childControllerValuations.id = Id + ".InterestRateStreams"; // Child metrics have now been calculated so we can now evaluate the stream model metrics if (swapControllerMetrics.Count > 0) { //TODO need to fix this calculation. var payStreamAccrualFactor = AssetValuationHelper.GetQuotationByMeasureType(childValuations[0], InstrumentMetrics.AccrualFactor.ToString()); //AggregateMetric(InstrumentMetrics.AccrualFactor, childValuations); var payStreamNPV = AssetValuationHelper.GetQuotationByMeasureType(childValuations[0], InstrumentMetrics.NPV.ToString()); //AggregateMetric(InstrumentMetrics.NPV, childValuations); var payStreamFloatingNPV = AssetValuationHelper.GetQuotationByMeasureType(childValuations[0], InstrumentMetrics.FloatingNPV.ToString()); //AggregateMetric(InstrumentMetrics.FloatingNPV, childValuations); var receiveStreamAccrualFactor = AssetValuationHelper.GetQuotationByMeasureType(childValuations[1], InstrumentMetrics.AccrualFactor.ToString()); //AggregateMetric(InstrumentMetrics.AccrualFactor, childValuations); var receiveStreamNPV = AssetValuationHelper.GetQuotationByMeasureType(childValuations[1], InstrumentMetrics.NPV.ToString()); //AggregateMetric(InstrumentMetrics.NPV, childValuations); var receiveStreamFloatingNPV = AssetValuationHelper.GetQuotationByMeasureType(childValuations[1], InstrumentMetrics.FloatingNPV.ToString()); IIRSwapInstrumentParameters analyticModelParameters = new SwapInstrumentParameters { IsPayFixedInd = true, PayStreamAccrualFactor = payStreamAccrualFactor.value, PayStreamFloatingNPV = payStreamFloatingNPV.value, PayStreamNPV = payStreamNPV.value, ReceiveStreamFloatingNPV = receiveStreamFloatingNPV.value, ReceiveStreamNPV = receiveStreamNPV.value, ReceiveStreamAccrualFactor = receiveStreamAccrualFactor.value, NPV = payStreamNPV.value + receiveStreamNPV.value }; CalculationResults = AnalyticsModel.Calculate <IIRSwapInstrumentResults, SwapInstrumentResults>(analyticModelParameters, swapControllerMetrics.ToArray()); // Now merge back into the overall stream valuation var swapControllerValuation = GetValue(CalculationResults, modelData.ValuationDate); swapValuation = AssetValuationHelper.UpdateValuation(swapControllerValuation, childControllerValuations, ConvertMetrics(swapControllerMetrics), new List <string>(Metrics)); } else { swapValuation = childControllerValuations; } CalculationPerfomedIndicator = true; swapValuation.id = Id; return(swapValuation); }
/// <summary> /// Calculates the specified model data. /// </summary> /// <param name="modelData">The model data.</param>//TODO the floating delta? /// <returns></returns> public override AssetValuation Calculate(IInstrumentControllerData modelData) { ModelData = modelData; AnalyticModelParameters = null; AnalyticsModel = new FxRateCashflowAnalytic(); CalculationResults = null; YearFractionToCashFlowPayment = Convert.ToDecimal(CDefaultDayCounter.YearFraction(ModelData.ValuationDate, PaymentDate)); //Make sure there are some bucket dates even if not set previously. if (BucketedDates.Length < 1) { UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval)); } IsRealised = HasBeenRealised(ModelData.ValuationDate); //Add the extra metrics required var quotes = ModelData.AssetValuation.quote.ToList(); if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.NPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.LocalCurrencyNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.RiskNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.LocalCurrencyExpectedValue.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyExpectedValue.ToString(), "DecimalValue", ModelData.ValuationDate); 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); IFxCurve fxCurve = null; IRateCurve discountCurve = null; IFxCurve currencyCurve = null; var reportingCurrency = ModelData.ReportingCurrency == null ? PaymentCurrency.Value : ModelData.ReportingCurrency.Value; //Set the basic model. var analyticModelParameters = new FxRateCashflowParameters { Multiplier = Multiplier, ValuationDate = ModelData.ValuationDate, PaymentDate = PaymentDate, Currency = PaymentCurrency.Value, ReportingCurrency = reportingCurrency, NotionalAmount = PaymentAmount.amount, StartIndex = StartIndex, IsRealised = IsRealised, CurveYearFraction = YearFractionToCashFlowPayment, PeriodAsTimesPerYear = 0.25m, BucketingRate = 0.05m }; if (modelData.MarketEnvironment is ISwapLegEnvironment environment) { var marketEnvironment = environment; //The discount curve. discountCurve = marketEnvironment.GetDiscountRateCurve(); discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; analyticModelParameters.DiscountCurve = discountCurve; //Check if it is our of currency. if (ModelData.ReportingCurrency != null && ModelData.ReportingCurrency.Value != PaymentCurrency.Value) { fxCurve = marketEnvironment.GetReportingCurrencyFxCurve(); fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; analyticModelParameters.ReportingCurrencyFxCurve = fxCurve; } } else if (modelData.MarketEnvironment.GetType() == typeof(MarketEnvironment)) { var market = (MarketEnvironment)modelData.MarketEnvironment; discountCurve = (IRateCurve)market.SearchForPricingStructureType(DiscountCurveName); discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; analyticModelParameters.DiscountCurve = discountCurve; var currencyCurveName = MarketEnvironmentHelper.ResolveFxCurveNames(StartFxRate.quotedCurrencyPair.currency1.Value, StartFxRate.quotedCurrencyPair.currency2.Value); currencyCurve = (IFxCurve)market.SearchForPricingStructureType(currencyCurveName); currencyCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; if (delta1PDH) { var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta1PDH"); analyticModelParameters.Delta1PDHCurves = riskMarket; analyticModelParameters.Delta1PDHPerturbation = 10; } if (delta0PDH) { var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta0PDH");//TODO The fx deltas analyticModelParameters.Delta1PDHCurves = riskMarket; analyticModelParameters.Delta1PDHPerturbation = 10; } if (modelData.ReportingCurrency.Value != PaymentCurrency.Value) { string curveName = MarketEnvironmentHelper.ResolveFxCurveNames(PaymentCurrency.Value, modelData.ReportingCurrency.Value); fxCurve = (IFxCurve)market.SearchForPricingStructureType(curveName); fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; analyticModelParameters.ReportingCurrencyFxCurve = fxCurve; } if (HybridValuation) { var currency1RateCurve = (IRateCurve)market.SearchForPricingStructureType(Currency1DiscountCurveName); currency1RateCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; var currency2RateCurve = (IRateCurve)market.SearchForPricingStructureType(Currency2DiscountCurveName); currency2RateCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; AnalyticsModel = new FxRateCashflowAnalytic(ModelData.ValuationDate, PaymentDate, currencyCurve, currency1RateCurve, currency2RateCurve, !InvertFxRate, IsSettlementInCurrency1, fxCurve); } } // store inputs and results from this run AnalyticModelParameters = analyticModelParameters; if (!HybridValuation) { AnalyticsModel = new FxRateCashflowAnalytic(ModelData.ValuationDate, PaymentDate, fxCurve, currencyCurve, discountCurve); } //TODO Fix this with a generic index curve. //AnalyticsModel = analyticsModel; CalculationResults = AnalyticsModel.Calculate <IFloatingCashflowResults, FloatingCashflowResults>(AnalyticModelParameters, metrics.ToArray()); CalculationPerformedIndicator = true; PaymentDiscountFactor = ((FxRateCashflowAnalytic)AnalyticsModel).PaymentDiscountFactor; 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); }
/// <summary> /// Creates a stream environment. /// </summary> /// <param name="baseDate"></param> /// <param name="discountCurve"></param> /// <param name="forecastCurve"></param> /// <param name="fxCurve"></param> /// <returns></returns> public static ISwapLegEnvironment CreateInterestRateStreamEnvironment(DateTime baseDate, IRateCurve discountCurve, IRateCurve forecastCurve, IFxCurve fxCurve) { var market = new SwapLegEnvironment(); market.AddPricingStructure(InterestRateStreamPSTypes.DiscountCurve.ToString(), discountCurve); market.AddPricingStructure(InterestRateStreamPSTypes.ForecastCurve.ToString(), forecastCurve); market.AddPricingStructure(InterestRateStreamPSTypes.ReportingCurrencyFxCurve.ToString(), fxCurve); return(market); }
/// <summary> /// Initiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="startDate">The start date of the coupon.</param> /// <param name="endDate">The end date of the coupon.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param> /// <param name="discountCurve">The rate curve to use for discounting.</param> /// <param name="forecastCurve">The forecast curve.</param> public StructuredRateCouponAnalytic(DateTime valuationDate, DateTime startDate, DateTime endDate, DateTime paymentDate, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve, IRateCurve forecastCurve) : base(valuationDate, startDate, endDate, paymentDate, reportingCurrencyFxCurve, discountCurve, forecastCurve) { }
/// <summary> /// Intantiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="startDate">The start date of the coupon.</param> /// <param name="endDate">The end date of the coupon.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="discountRate">The discount rate.</param> /// <param name="yearFraction">The yearFraction.</param> /// <param name="reportingCurrencyFxCurve">The reportingCurrencyFxCurve</param> /// <param name="discountCurve">THe fx curve. It must already be normalised.</param> /// <param name="discountType">The discountType.</param> /// <param name="forecastCurve">The rate curve to use for forecasting.</param> public FloatingRateCouponAnalytic(DateTime valuationDate, DateTime startDate, DateTime endDate, DateTime paymentDate, decimal?discountRate, decimal yearFraction, DiscountType discountType, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve, IRateCurve forecastCurve) : base(valuationDate, startDate, endDate, paymentDate, discountRate, yearFraction, discountType, reportingCurrencyFxCurve, discountCurve, forecastCurve) { StartDate = startDate; EndDate = endDate; }
/// <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; CalculationResults = null; UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval)); // 1. First derive the analytics to be evaluated via the stream controller model // NOTE: These take precendence of the child model metrics if (AnalyticsModel == null) { AnalyticsModel = new SimpleIRSwaptionInstrumentAnalytic(); } var swaptionControllerMetrics = ResolveModelMetrics(AnalyticsModel.Metrics); 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.NPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue"); quotes.Add(quote); } ModelData.AssetValuation.quote = quotes.ToArray(); AssetValuation swaptionValuation; //Sets the evolution type for calculations. Swap.PricingStructureEvolutionType = PricingStructureEvolutionType; Swap.BucketedDates = BucketedDates; if (PremiumPayments != null) { foreach (var payment in PremiumPayments) { payment.PricingStructureEvolutionType = PricingStructureEvolutionType; payment.BucketedDates = BucketedDates; } } //The assetValuation list. var childValuations = new List <AssetValuation>(); // 2. Now evaluate only the child specific metrics (if any) if (PremiumPayments != null) { var paymentControllers = new List <InstrumentControllerBase>(PremiumPayments); childValuations.AddRange(paymentControllers.Select(payment => payment.Calculate(modelData))); } var swapMetrics = Swap.Calculate(modelData); //We assume the fixed leg is always the first leg! var fixedLeg = Swap.GetLegs()[0].Calculate(modelData); var breakEvenRate = AssetValuationHelper.GetQuotationByMeasureType(swapMetrics, InstrumentMetrics.BreakEvenRate.ToString()).value; var timeToIndex = (Swap.EffectiveDate - ModelData.ValuationDate).Days / 365.0; //This is European only. var expiryTime = (ExerciseDates[0] - ModelData.ValuationDate).Days / 365.0; IVolatilitySurface indexVolSurface = null; if (modelData.MarketEnvironment is ISwapLegEnvironment streamMarket1) { indexVolSurface = streamMarket1.GetVolatilitySurface(); indexVolSurface.PricingStructureEvolutionType = PricingStructureEvolutionType; VolatilitySurfaceName = indexVolSurface.GetPricingStructureId().UniqueIdentifier; } else { if (!string.IsNullOrEmpty(VolatilitySurfaceName)) { indexVolSurface = (IVolatilitySurface)modelData.MarketEnvironment.GetPricingStructure(VolatilitySurfaceName); } } //Calculate the delta var delta = SimpleIRSwaptionInstrumentAnalytic.CalculateOptionDelta(IsCall, breakEvenRate, StrikeRate, expiryTime, timeToIndex, indexVolSurface); //Set the multiplier using the delta of the option. //Multiplier = delta;? Swap.Multiplier = System.Math.Abs(delta); //New function that converts the metrics by multiplying be the delta. var swapCalculations = Swap.Calculate(modelData); //childValuations.Add(swapCalculations); var childControllerValuations = AssetValuationHelper.AggregateMetrics(childValuations, new List <string>(Metrics), PaymentCurrencies); // modelData.ValuationDate); var streamAccrualFactor = AssetValuationHelper.GetQuotationByMeasureType(fixedLeg, InstrumentMetrics.AccrualFactor.ToString()); //TODO This is not correct! var npv = AssetValuationHelper.GetQuotationByMeasureType(childControllerValuations, InstrumentMetrics.NPV.ToString()); childValuations.Add(swapCalculations); // Child metrics have now been calculated so we can now evaluate the stream model metrics if (swaptionControllerMetrics.Count > 0) { //Get the market data. IFxCurve fxCurve = null; ISwaptionInstrumentParameters analyticModelParameters = new SwaptionInstrumentParameters { IsBought = IsBasePartyBuyer, IsCall = IsCall, SwapAccrualFactor = System.Math.Abs(streamAccrualFactor.value), Strike = StrikeRate, OtherNPV = npv.value, TimeToExpiry = (decimal)expiryTime, SwapBreakEvenRate = breakEvenRate, //OtherNPV = }; // Curve Related if (modelData.MarketEnvironment is ISwapLegEnvironment streamMarket) { analyticModelParameters.VolatilitySurface = indexVolSurface; //Check for currency. if (ModelData.ReportingCurrency != null) { if (ModelData.ReportingCurrency.Value != PaymentCurrencies[0])//This is an interest rate swap and so only has one currency. { fxCurve = streamMarket.GetReportingCurrencyFxCurve(); fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; } } } var analyticsModel = new SimpleIRSwaptionInstrumentAnalytic(ModelData.ValuationDate, (decimal)timeToIndex, StrikeRate, fxCurve, indexVolSurface); AnalyticsModel = analyticsModel; Volatility = analyticsModel.Volatility; AnalyticModelParameters = analyticModelParameters; CalculationResults = AnalyticsModel.Calculate <ISwaptionInstrumentResults, SwaptionInstrumentResults>(analyticModelParameters, swaptionControllerMetrics.ToArray()); // Now merge back into the overall stream valuation var swapControllerValuation = GetValue(CalculationResults, modelData.ValuationDate); //childValuations.Add(swapControllerValuation); childControllerValuations = AssetValuationHelper.AggregateMetrics(childValuations, new List <string>(Metrics), PaymentCurrencies);// modelData.ValuationDate); swaptionValuation = AssetValuationHelper.UpdateValuation(swapControllerValuation, childControllerValuations, ConvertMetrics(swaptionControllerMetrics), new List <string>(Metrics)); //swaptionValuation = AssetValuationHelper.AggregateMetrics(childValuations, new List<string>(Metrics), modelData.ValuationDate); } else { swaptionValuation = childControllerValuations; } CalculationPerfomedIndicator = true; swaptionValuation.id = Id; return(swaptionValuation); }
/// <summary> /// Calculates the specified model data. /// </summary> /// <param name="modelData">The model data.</param> /// <returns></returns> public override BasicAssetValuation Calculate(IAssetControllerData modelData) { ModelData = modelData; AnalyticsModel = new FxRateAssetAnalytic(); //DependencyCreator.Resolve<IModelAnalytic<IFxRateAssetParameters, FxMetrics>>(_modelIdentifier); var metrics = MetricsHelper.GetMetricsToEvaluate(Metrics, AnalyticsModel.Metrics); // Determine if DFAM has been requested - if so thats all we evaluate - every other metric is ignored var bEvalForwardAtMaturity = false; if (metrics.Contains(FxMetrics.ForwardAtMaturity)) { bEvalForwardAtMaturity = true; metrics.RemoveAll( metricItem => metricItem != FxMetrics.ForwardAtMaturity); } IFxRateAssetParameters analyticModelParameters = new FxRateAssetParameters(); CalculationResults = new FxAssetResults(); var metricsToEvaluate = metrics.ToArray(); var marketEnvironment = modelData.MarketEnvironment; //1. instantiate curve //var fxCurve = (IFxCurve)modelData.MarketEnvironment.GetPricingStructure(FxCurveName); IFxCurve fxCurve = null; //1. instantiate curve if (marketEnvironment.GetType() == typeof(SimpleMarketEnvironment)) { fxCurve = (IFxCurve)((ISimpleMarketEnvironment)marketEnvironment).GetPricingStructure(); FxCurveName = fxCurve.GetPricingStructureId().UniqueIdentifier; } if (marketEnvironment.GetType() == typeof(SimpleFxMarketEnvironment)) { fxCurve = ((ISimpleFxMarketEnvironment)marketEnvironment).GetFxCurve(); FxCurveName = fxCurve.GetPricingStructureId().UniqueIdentifier; } if (marketEnvironment.GetType() == typeof(SwapLegEnvironment)) { fxCurve = ((ISwapLegEnvironment)marketEnvironment).GetReportingCurrencyFxCurve(); FxCurveName = fxCurve.GetPricingStructureId().UniqueIdentifier; } if (marketEnvironment.GetType() == typeof(MarketEnvironment)) { fxCurve = (IFxCurve)modelData.MarketEnvironment.GetPricingStructure(FxCurveName); } //3. Get the Rate if (FxRate != null) { analyticModelParameters.FxRate = FxRate.value; } if (bEvalForwardAtMaturity) { //4. Set the anaytic input parameters and Calculate the respective metrics CalculationResults = AnalyticsModel.Calculate <IFxAssetResults, FxAssetResults>(analyticModelParameters, metricsToEvaluate); } else { analyticModelParameters.NotionalAmount = NotionalAmount; IDayCounter dc = Actual365.Instance; analyticModelParameters.YearFraction = (decimal)dc.YearFraction(modelData.ValuationDate, RiskMaturityDate); //3. Get the end discount factor - Need to fix this. analyticModelParameters.FxCurveSpotRate = GetForwardAtMaturity(fxCurve, GetRiskMaturityDate(), modelData.ValuationDate); //4. Set the anaytic input parameters and Calculate the respective metrics CalculationResults = AnalyticsModel.Calculate <IFxAssetResults, FxAssetResults>(analyticModelParameters, metricsToEvaluate); } return(GetValue(CalculationResults)); }
/// <summary> /// Initiates a new model. /// </summary> /// <param name="valuationDate">The valuation date.</param> /// <param name="startDate">The start date of the coupon.</param> /// <param name="endDate">The end date of the coupon.</param> /// <param name="paymentDate">The payment date of the cash flow.</param> /// <param name="timeToIndex">The timeToIndex. Not necessarily the time to expiry. This is used for surface interpolation..</param> /// <param name="capStrike">The cap strike.</param> /// <param name="floorStrike">The floor strike.</param> /// <param name="reportingCurrencyFxCurve">THe fx curve. It must already be normalised.</param> /// <param name="discountCurve">The rate curve to use for discounting.</param> /// <param name="forecastCurve">The forecast curve.</param> /// <param name="indexVolSurface">The index volatility surface.</param> public RateOptionCouponAnalytic(DateTime valuationDate, DateTime startDate, DateTime endDate, DateTime paymentDate, decimal timeToIndex, decimal capStrike, decimal floorStrike, IFxCurve reportingCurrencyFxCurve, IRateCurve discountCurve, IRateCurve forecastCurve, IVolatilitySurface indexVolSurface) : this(valuationDate, startDate, endDate, paymentDate, timeToIndex, capStrike, reportingCurrencyFxCurve, discountCurve, forecastCurve, indexVolSurface) { IsCollar = true; CollarFloorStrike = floorStrike; CollarFloorVolatility = (decimal)indexVolSurface.GetValue((double)timeToIndex, (double)floorStrike); }
//Clones a curve, maps the quoted assets specified and then returns an FpML structure back. // /// <summary> /// /// </summary> /// <param name="logger"></param> /// <param name="cache"></param> /// <param name="nameSpace">THe client namespace</param> /// <param name="referenceCurve"></param> /// <param name="spreadValues"></param> /// <param name="id"></param> /// <param name="fixingCalendar"></param> /// <param name="rollCalendar"></param> /// <param name="baseDate"></param> /// <returns></returns> public static Pair <PricingStructure, PricingStructureValuation> ProcessQuotedAssetSet(ILogger logger, ICoreCache cache, string nameSpace, IFxCurve referenceCurve, FxRateSet spreadValues, string id, IBusinessCalendar fixingCalendar, IBusinessCalendar rollCalendar, DateTime baseDate) { //Clone the ref curves. // var clonedCurve = referenceCurve.Clone(); var fpml = ((IFxCurve)clonedCurve).GetFpMLData(); var fxCurveCloned = (FpML.V5r10.Reporting.FxCurve)fpml.First; var fxvCurveCloned = (FxCurveValuation)fpml.Second; // assign id to the cloned YieldCurve // fxCurveCloned.id = id; // nullify the discount factor curve to make sure that bootstrapping will happen) // fxvCurveCloned.fxForwardCurve.point = null; fxvCurveCloned.fxForwardPointsCurve = null; //Manipulate the quated asset set. // fxvCurveCloned.spotRate = MappedQuotedAssetSet(logger, cache, nameSpace, referenceCurve, spreadValues, fixingCalendar, rollCalendar, baseDate); return(fpml); }
/// <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 FxOptionAnalytic(); CalculationResults = null; YearFractionToCashFlowPayment = Convert.ToDecimal(CDefaultDayCounter.YearFraction(ModelData.ValuationDate, PaymentDate)); //Make sure there are some bucket dates even if not set previously. if (BucketedDates.Length < 1) { UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval)); } IsRealised = HasBeenRealised(ModelData.ValuationDate); //Add the extra metrics required var quotes = ModelData.AssetValuation.quote.ToList(); if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.NPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.LocalCurrencyNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.RiskNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, FloatingCashflowMetrics.LocalCurrencyExpectedValue.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, FloatingCashflowMetrics.LocalCurrencyExpectedValue.ToString(), "DecimalValue", ModelData.ValuationDate); 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(); //Set the cash flowdetails. HasReset = modelData.ValuationDate > ResetDate; IsRealised = HasBeenRealised(ModelData.ValuationDate); TimeToExpiry = GetPaymentYearFraction(ModelData.ValuationDate, AdjustedFixingDate); var volatilityCurveNodeTime = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate); IFxCurve fxCurve = null; IRateCurve discountCurve = null; IFxCurve currencyCurve = null; IVolatilitySurface volSurface = null; var metrics = ResolveModelMetrics(AnalyticsModel.Metrics); //var metricsToEvaluate = metrics.ToArray(); //if (metricsToEvaluate.Length > 0) //{ YearFractionToCashFlowPayment = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate); var reportingCurrency = ModelData.ReportingCurrency == null ? PaymentCurrency.Value : ModelData.ReportingCurrency.Value; decimal?premium = null; if (Premium != null) { premium = Premium; } IFxRateCashflowParameters analyticModelParameters = new FxRateCashflowParameters { ValuationDate = modelData.ValuationDate, PaymentDate = PaymentDate, Currency = PaymentCurrency.Value, ReportingCurrency = reportingCurrency, IsRealised = IsRealised, IsReset = HasReset, NotionalAmount = NotionalAmount.amount, CurveYearFraction = YearFractionToCashFlowPayment, ExpiryYearFraction = TimeToExpiry, Premium = premium }; // Curve Related if (modelData.MarketEnvironment.GetType() == typeof(MarketEnvironment)) { var market = (MarketEnvironment)modelData.MarketEnvironment; discountCurve = (IRateCurve)market.SearchForPricingStructureType(DiscountCurveName); discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; volSurface = (IVolatilitySurface)market.SearchForPricingStructureType(VolatilitySurfaceName); volSurface.PricingStructureEvolutionType = PricingStructureEvolutionType; var currencyCurveName = MarketEnvironmentHelper.ResolveFxCurveNames(StartFxRate.quotedCurrencyPair.currency1.Value, StartFxRate.quotedCurrencyPair.currency2.Value); currencyCurve = (IFxCurve)market.SearchForPricingStructureType(currencyCurveName); currencyCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; analyticModelParameters.DiscountCurve = discountCurve; if (delta1PDH) { var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta1PDH"); analyticModelParameters.Delta1PDHCurves = riskMarket; analyticModelParameters.Delta1PDHPerturbation = 10; } if (delta0PDH)//TODO Do this for the fxrate { //var riskMarket = market.SearchForPerturbedPricingStructures(DiscountCurveName, "delta0PDH"); // //TODO The fx deltas //analyticModelParameters.Delta1PDHCurves = riskMarket; //analyticModelParameters.Delta1PDHPerturbation = 10; } if (modelData.ReportingCurrency.Value != PaymentCurrency.Value) { string curveName = MarketEnvironmentHelper.ResolveFxCurveNames(PaymentCurrency.Value, modelData.ReportingCurrency.Value); fxCurve = (IFxCurve)market.SearchForPricingStructureType(curveName); fxCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; analyticModelParameters.ReportingCurrencyFxCurve = fxCurve; } if (HybridValuation) { var currency1RateCurve = (IRateCurve)market.SearchForPricingStructureType(Currency1DiscountCurveName); currency1RateCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; var currency2RateCurve = (IRateCurve)market.SearchForPricingStructureType(Currency2DiscountCurveName); currency2RateCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; AnalyticsModel = new FxOptionAnalytic(ModelData.ValuationDate, PaymentDate, currencyCurve, currency1RateCurve, currency2RateCurve, IsSettlementInCurrency1, !InvertFxRate, Strike, TimeToExpiry, volatilityCurveNodeTime, volSurface, FxOptionType, fxCurve); } } // store inputs and results from this run AnalyticModelParameters = analyticModelParameters; if (!HybridValuation) { AnalyticsModel = new FxOptionAnalytic(ModelData.ValuationDate, PaymentDate, Strike, TimeToExpiry, volatilityCurveNodeTime, fxCurve, currencyCurve, discountCurve, volSurface, FxOptionType); } //TODO Fix this with a generic index curve. //AnalyticsModel = analyticsModel; CalculationResults = AnalyticsModel.Calculate <IFloatingCashflowResults, FloatingCashflowResults>( AnalyticModelParameters, metrics.ToArray()); CalculationPerfomedIndicator = true; PaymentDiscountFactor = ((FxRateCashflowAnalytic)AnalyticsModel).PaymentDiscountFactor; 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); }
/// <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 FloatingRateCouponAnalytic(); RequiresReset = modelData.ValuationDate > ResetDate; IsRealised = HasBeenRealised(ModelData.ValuationDate); //Make sure there are some bucket dates even if not set previously. if (BucketedDates.Length < 1) { UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval)); } //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", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.AccrualFactor.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.AccrualFactor.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.FloatingNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.FloatingNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.NPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.NPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.RiskNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.RiskNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyNPV.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.LocalCurrencyNPV.ToString(), "DecimalValue", ModelData.ValuationDate); quotes.Add(quote); } if (AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyExpectedValue.ToString()) == null) { var quote = QuotationHelper.Create(0.0m, InstrumentMetrics.LocalCurrencyExpectedValue.ToString(), "DecimalValue", ModelData.ValuationDate); 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); IFxCurve fxCurve = null; IRateCurve discountCurve = null; IRateCurve forecastCurve = null; //// Determine if DFAM has been requested - if so thats all we evaluate - every other metric is ignored //if (metrics.Contains(InstrumentMetrics.DiscountFactorAtMaturity)) //{ // metrics.RemoveAll(metricItem => metricItem != InstrumentMetrics.DiscountFactorAtMaturity); //} //Set the forrecast rate dates. The ForecastRateInterpolation shhould have been set. ForwardStartDate = AccrualStartDate; ForwardEndDate = ForecastRateInterpolation ? AccrualEndDate : AdjustedDateHelper.ToAdjustedDate(FixingCalendar, ForecastRateIndex.indexTenor.Add(ForwardStartDate), AccrualBusinessDayAdjustments); //var metricsToEvaluate = metrics.ToArray(); if (metrics.Count > 0) { YearFractionToCashFlowPayment = GetPaymentYearFraction(ModelData.ValuationDate, PaymentDate); var reportingCurrency = ModelData.ReportingCurrency == null ? PaymentCurrency.Value : ModelData.ReportingCurrency.Value; var amount = NotionalAmount.amount; IRateCouponParameters analyticModelParameters = new RateCouponParameters { Multiplier = Multiplier, ValuationDate = modelData.ValuationDate, PaymentDate = PaymentDate, Currency = PaymentCurrency.Value, ReportingCurrency = reportingCurrency, DiscountType = DiscountType, IsRealised = IsRealised, HasReset = RequiresReset, NotionalAmount = amount, Spread = Margin, YearFraction = CouponYearFraction, CurveYearFraction = YearFractionToCashFlowPayment }; decimal?discountRate = null; // Curve Related if (modelData.MarketEnvironment is ISwapLegEnvironment environment) { var streamMarket = environment; discountCurve = streamMarket.GetDiscountRateCurve(); discountCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; forecastCurve = streamMarket.GetForecastRateCurve(); forecastCurve.PricingStructureEvolutionType = PricingStructureEvolutionType; DiscountCurveName = discountCurve.GetPricingStructureId().UniqueIdentifier; analyticModelParameters.DiscountCurve = discountCurve; ForecastCurveName = forecastCurve.GetPricingStructureId().UniqueIdentifier; analyticModelParameters.ForecastCurve = forecastCurve; // 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; analyticModelParameters.ReportingCurrencyFxCurve = fxCurve; } } AnalyticModelParameters = analyticModelParameters; } 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; analyticModelParameters.DiscountCurve = discountCurve; analyticModelParameters.ForecastCurve = forecastCurve; // 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.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; } } else { if (Rate != null) { discountRate = Rate; } if (DiscountRate != null) { discountRate = DiscountRate; } AnalyticsModel = new FloatingRateCouponAnalytic(ModelData.ValuationDate, AccrualStartDate, AccrualEndDate, PaymentDate, discountRate, analyticModelParameters.YearFraction, DiscountType, fxCurve, discountCurve, forecastCurve); } CalculationResults = AnalyticsModel.Calculate <IRateInstrumentResults, RateInstrumentResults>(AnalyticModelParameters, metrics.ToArray()); CalculationPerfomedIndicator = 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); }
/// <summary> /// This assumes that the rest dates are consistent with the curve. /// </summary> /// <param name="valuationDate"></param> /// <param name="paymentDate"></param> /// <param name="indexCurve"></param> public FxLegAnalytic(DateTime valuationDate, DateTime paymentDate, IFxCurve indexCurve) { //ToReportingCurrencyRate = EvaluateReportingCurrencyFxRate(valuationDate, reportingCurrencyFxCurve); ForwardFxRate = (decimal)indexCurve.GetForward(valuationDate, paymentDate); }