/// <summary> /// Helper function used by the master function that validates all /// constructor arguments. /// Exceptions: ArgumentNullException, ArgumentException. /// </summary> /// <param name="atmBootstrapEngine">An existing At-the-Money (ATM) /// Caplet bootstrap engine. /// </param> private static void ValidateATMBootstrapEngine (VolatilityCurve atmBootstrapEngine) { // Check for a correct engine type. if (atmBootstrapEngine.Equals(null) || !atmBootstrapEngine.IsATMBootstrap) { // Invalid engine type. const string errorMessage = "Invalid engine passed as an ATM Caplet Bootstrap engine"; throw new ArgumentException (errorMessage, nameof(atmBootstrapEngine)); } // Check that the Caplet Bootstrap engine is in a calibrated state. if (atmBootstrapEngine.IsBootstrapSuccessful) { } else { // Engine is not in a calibrated state. const string errorMessage = "ATM Caplet Bootstrap engine is not calibrated"; throw new ArgumentException (errorMessage, nameof(atmBootstrapEngine)); } }
/// <summary> /// Constructor for <see cref="ExpiryInterpolatedVolatility"/> /// class. /// </summary> /// <param name="bootstrapEngine">The Bootstrap Engine /// that contains the results of the bootstrap. /// Precondition: IsCapletBootstrapSuccessful method applied to the /// Caplet bootstrap engine returns "true".</param> /// <param name="expiryInterpolationType">Type of one dimensional /// interpolation that will be applied to the expiry.</param> public ExpiryInterpolatedVolatility (VolatilityCurve bootstrapEngine, ExpiryInterpolationType expiryInterpolationType) { ValidateConstructorArguments(bootstrapEngine); InitialisePrivateFields (bootstrapEngine, expiryInterpolationType); }
/// <summary> /// Master function used to validate all constructor arguments. /// </summary> /// /// <param name="atmBootstrapEngine">An existing At-the-Money (ATM) /// Caplet bootstrap engine. /// </param> /// <param name="smileSettings">An existing Smile settings /// object that will be used in the calibration of the Caplet smile. /// </param> /// <param name="fixedStrikeBootstrapEngines">List of existing fixed /// strike Caplet bootstrap engines. /// when applied to each Caplet bootstrap engine in the list.</param> /// <param name="handle">Unique name that will identify the object /// that will be instantiated.</param> private static void ValidateConstructorArguments (VolatilityCurve atmBootstrapEngine, SmileCalibrationSettings smileSettings, ICollection <VolatilityCurve> fixedStrikeBootstrapEngines, string handle) { ValidateATMBootstrapEngine(atmBootstrapEngine); ValidateSmileSettings(smileSettings); ValidateFixedStrikeBootstrapEngines(fixedStrikeBootstrapEngines); ValidateHandle(handle); }
/// <summary> /// Helper function used to initialise the private fields. /// </summary> /// <param name="volatilityCurve">The Bootstrap engine /// that contains the results of the bootstrap.</param> /// <param name="expiryInterpolationType">Type of the expiry /// interpolation. /// Example: Linear interpolation.</param> private void InitialisePrivateFields (VolatilityCurve volatilityCurve, ExpiryInterpolationType expiryInterpolationType) { // Initialise the Calculation Date. _calculationDate = volatilityCurve.GetBaseDate(); // Set the x and y arrays for the one dimensional interpolation. var results = volatilityCurve.BootstrapResults.Results; IDayCounter dayCountObj = Actual365.Instance; var tempXArray = new List <double>(); var tempYArray = new List <double>(); var count = 1; foreach (var expiry in results.Keys) { var timeToExpiry = dayCountObj.YearFraction (_calculationDate, expiry); tempXArray.Add(timeToExpiry); tempYArray.Add(decimal.ToDouble(results[expiry])); // Record the first and last time to expiry and available // bootstrap Caplet volatility. if (count == 1) { _firstExpiry = (decimal)timeToExpiry; _firstVolatility = results[expiry]; } _lastVolatility = results[expiry]; _lastExpiry = (decimal)timeToExpiry; ++count; } double[] xArray = tempXArray.ToArray(); double[] yArray = tempYArray.ToArray(); // Initialise the one dimensional interpolation object. switch (expiryInterpolationType) { case ExpiryInterpolationType.CubicHermiteSpline: _expiryInterpolationObj = new CubicHermiteSplineInterpolation(); _expiryInterpolationObj.Initialize(xArray, yArray); break; default: // Linear interpolation _expiryInterpolationObj = new LinearInterpolation(); _expiryInterpolationObj.Initialize(xArray, yArray); break; } }
/// <summary> /// Constructor for the class <see cref="CapletSmileCalibrationEngine"/> /// </summary> /// <param name="atmBootstrapEngine">An existing At-the-Money (ATM) /// Caplet bootstrap engine. /// Precondition: Method IsCapletBootstrapSuccessful returns true. /// </param> /// <param name="capletSmileSettings">An existing Caplet Smile settings /// object that will be used in the calibration of the Caplet smile. /// </param> /// <param name="fixedStrikeBootstrapEngines">List of existing fixed /// strike Caplet bootstrap engines. /// Precondition: Method IsCapletBootstrapSuccessful returns true /// when applied to each Caplet bootstrap engine in the list.</param> /// <param name="handle">Unique name that will identify the object /// that will be instantiated. /// Precondition: Non empty string.</param> public SmileCalibrationEngine (VolatilityCurve atmBootstrapEngine, SmileCalibrationSettings capletSmileSettings, List <VolatilityCurve> fixedStrikeBootstrapEngines, string handle) { ValidateConstructorArguments (atmBootstrapEngine, capletSmileSettings, fixedStrikeBootstrapEngines, handle); InitialisePrivateFields (atmBootstrapEngine, capletSmileSettings, fixedStrikeBootstrapEngines, handle); }
/// <summary> /// Master function used to initialise all private fields. /// </summary> /// <param name="atmBootstrapEngine">An existing At-the-Money (ATM) /// Caplet bootstrap engine.</param> /// <param name="capletSmileSettings">An existing Caplet Smile settings /// object that will be used in the calibration of the Caplet smile. /// </param> /// <param name="fixedStrikeBootstrapEngines">List of existing fixed /// strike Caplet bootstrap engines.</param> /// <param name="handle">Unique name that will identify the object /// that will be instantiated.</param> private void InitialisePrivateFields (VolatilityCurve atmBootstrapEngine, SmileCalibrationSettings capletSmileSettings, List <VolatilityCurve> fixedStrikeBootstrapEngines, string handle) { _atmBootstrapEngine = atmBootstrapEngine; _smileSettings = capletSmileSettings; _fixedStrikeBootstrapEngines = fixedStrikeBootstrapEngines; Handle = handle; InitialiseSABRSettings(); // Initialise the remaining private fields to an appropriate // default. _assetPrice = -1.0m; _excerciseTime = -1.0m; _sabrEngine = null; _sabrStrikes = null; _sabrVolatilities = null; }
/// <summary> /// Helper function used to validate the arguments to the constructor. /// Exception: ArgumentException. /// </summary> /// <param name="capletCurve">The Caplet bootstrap engine /// that contains the results of the bootstrap. /// Precondition: IsCapletBootstrapSuccessful method applied to the /// Caplet bootstrap engine returns "true".</param> private static void ValidateConstructorArguments (VolatilityCurve capletCurve) { // Check for a valid Caplet Bootstrap Engine. if (capletCurve == null) { const string errorMessage = "Volatility curve expiry interpolation found a NULL calibration engine"; throw new ArgumentException(errorMessage); } if (capletCurve.IsBootstrapSuccessful) { } else { const string errorMessage = "Volatility curve expiry interpolation requires a successful bootstrap"; throw new ArgumentException(errorMessage); } }
/// <summary> /// Calculates the specified model data. /// </summary> /// <param name="modelData">The model data.</param> /// <returns></returns> public override BasicAssetValuation Calculate(IAssetControllerData modelData) { ModelData = modelData; switch (ModelIdentifier) { case "CapAsset": AnalyticsModel = new RateOptionAssetAnalytic(); break; case "DiscountCapAsset": AnalyticsModel = new RateOptionAssetAnalytic(); break; } 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 bEvalLastForewardVolatiltiy = false; if (metrics.Contains(RateOptionMetrics.VolatilityAtExpiry)) { bEvalLastForewardVolatiltiy = true; metrics.RemoveAll( metricItem => metricItem != RateOptionMetrics.VolatilityAtExpiry); } var metricsToEvaluate = metrics.ToArray(); IRateOptionAssetParameters analyticModelParameters = new RateOptionAssetParameters(); AnalyticResults = new RateOptionAssetResults(); var marketEnvironment = modelData.MarketEnvironment; //1. instantiate curve if (marketEnvironment.GetType() == typeof(SimpleMarketEnvironment)) { DiscountCurve = (IRateCurve)((ISimpleMarketEnvironment)marketEnvironment).GetPricingStructure(); DiscountCurveName = DiscountCurve.GetPricingStructureId().UniqueIdentifier; ForecastCurve = DiscountCurve; ForecastCurveName = DiscountCurveName; var volatilities = CreateList((double)Volatility, TimesToExpiry.Count); analyticModelParameters.Volatilities = volatilities; } if (marketEnvironment.GetType() == typeof(SwapLegEnvironment)) { DiscountCurve = ((ISwapLegEnvironment)marketEnvironment).GetDiscountRateCurve(); DiscountCurveName = DiscountCurve.GetPricingStructureId().UniqueIdentifier; ForecastCurve = ((ISwapLegEnvironment)marketEnvironment).GetForecastRateCurve(); ForecastCurveName = ForecastCurve.GetPricingStructureId().UniqueIdentifier; VolatilityCurve = ((ISwapLegEnvironment)marketEnvironment).GetVolatilitySurface(); VolatilityCurveName = VolatilityCurve.GetPricingStructureId().UniqueIdentifier; analyticModelParameters.Volatilities = GetVolatilties(VolatilityCurve, TimesToExpiry, Strikes); } if (marketEnvironment.GetType() == typeof(MarketEnvironment)) { if (DiscountCurveName != null) { DiscountCurve = (IRateCurve)modelData.MarketEnvironment.GetPricingStructure(DiscountCurveName); } if (ForecastCurveName != null) { ForecastCurve = (IRateCurve)modelData.MarketEnvironment.GetPricingStructure(ForecastCurveName); } if (VolatilityCurveName != null) { VolatilityCurve = (IVolatilitySurface)modelData.MarketEnvironment.GetPricingStructure(VolatilityCurveName); } analyticModelParameters.Volatilities = GetVolatilties(VolatilityCurve, TimesToExpiry, Strikes); } analyticModelParameters.FlatVolatility = Volatility; //2. Set the premium if (Premium == null) { Premium = CalculatePremium(); } if (Premium != null) { analyticModelParameters.Premium = (double)Premium; } if (bEvalLastForewardVolatiltiy) { //3. Set the start diccount factor and vol. analyticModelParameters.PremiumPaymentDiscountFactor = GetDiscountFactor(DiscountCurve, AdjustedStartDate, modelData.ValuationDate); //4. Get the respective year fractions analyticModelParameters.YearFractions = GetYearFractions(); //5. Set the anaytic input parameters and Calculate the respective metrics AnalyticResults = AnalyticsModel.Calculate <IRateOptionAssetResults, RateOptionAssetResults>(analyticModelParameters, metricsToEvaluate); } else { analyticModelParameters.IsDiscounted = false; analyticModelParameters.IsPut = !IsCap; analyticModelParameters.Notionals = Notionals; analyticModelParameters.ForwardRates = ResetRates; //2. Get the discount factors analyticModelParameters.PaymentDiscountFactors = GetDiscountFactors(DiscountCurve, AdjustedPeriodDates.ToArray(), modelData.ValuationDate); analyticModelParameters.ForecastDiscountFactors = GetDiscountFactors(ForecastCurve, AdjustedPeriodDates.ToArray(), modelData.ValuationDate); //3. Get the respective year fractions analyticModelParameters.YearFractions = GetYearFractions(); analyticModelParameters.Strikes = Strikes; analyticModelParameters.Rate = (double)CalculateImpliedParRate(modelData.ValuationDate); analyticModelParameters.TimesToExpiry = TimesToExpiry; //5. Set the anaytic input parameters and Calculate the respective metrics AnalyticResults = AnalyticsModel.Calculate <IRateOptionAssetResults, RateOptionAssetResults>(analyticModelParameters, metricsToEvaluate); } return(GetValue(AnalyticResults)); }