/// <summary> /// Helper method used by the Caplet Bootstrap Engine to compute the /// discount factor from the Calculation Date to some date beyond /// or equal to the Calculation Date. /// </summary> /// <param name="capletBootstrapSettings">The Caplet Bootstrap /// settings object that stores the Calculation Date.</param> /// <param name="offsets">Array of offsets (number of days) from /// the Calculation Date.</param> /// <param name="discountFactors">Array of discount factors.</param> /// <param name="endDate">Target date. /// Precondition: End date cannot be before the Calculation Date.</param> /// <returns>Discount factor.</returns> public static decimal ComputeDiscountFactor (NamedValueSet capletBootstrapSettings, double[] offsets, double[] discountFactors, DateTime endDate) { // Compute and validate the offset from the start date to the // end date. var calcDate = capletBootstrapSettings.GetValue("Calculation Date", DateTime.MinValue); var timeDiff = endDate - calcDate; var offset = (double)timeDiff.Days; const string errorMessage = "End date for a discount factor cannot be before Calculation Date"; DataQualityValidator.ValidateMinimum (offset, 0.0d, errorMessage, true); // Compute the discount factor by interpolation at the target. var discountFactor = 1.0m; if (offset > 0.0d) { var interpObj = new Analytics.Interpolations.LinearInterpolation(); interpObj.Initialize(offsets, discountFactors); discountFactor = (decimal)interpObj.ValueAt(offset, true); } return(discountFactor); }
/// <summary> /// Computes the expiry interpolated Caplet volatility. /// </summary> /// <param name="expiry">The expiry date. /// Postcondition: expiry cannot be before the Calculation date.</param> /// <returns>Expiry interpolated Caplet volatility.</returns> public decimal ComputeVolatility(DateTime expiry) { // Convert the expiry into a corresponding time in ACT/365 // day count. IDayCounter dayCountObj = Actual365.Instance; var target = dayCountObj.YearFraction (_calculationDate, expiry); // Validate the time equivalent to the expiry date. var targetErrorMessage = "Expiry cannot be before: " + _calculationDate; DataQualityValidator.ValidateMinimum (target, 0.0d, targetErrorMessage, true); // Compute and return the Caplet volatility: flat line extrapolate // at each end. decimal volatility; if (target < 0.0d) { const string errorMessage = "Date cannot be before the Calculation Date"; throw new ArgumentException(errorMessage); } if (target >= 0.0d && target < decimal.ToDouble(_firstExpiry)) { volatility = _firstVolatility; } else { volatility = target > decimal.ToDouble(_lastExpiry) ? _lastVolatility : (decimal)_expiryInterpolationObj.ValueAt(target, true); } return(volatility); }
/// <summary> /// Helper method used by the Caplet Bootstrap Engine to compute the /// forward rate for a period. /// </summary> /// <param name="capletBootstrapSettings">The Caplet Bootstrap Settings /// object that stores the Calculation Date and Day Count.</param> /// <param name="offsets">Array of offsets (number of days) from /// the Calculation Date.</param> /// <param name="discountFactors">Array of discount factors.</param> /// <param name="startDate">The start date for the period.</param> /// <param name="endDate">The end date for the period.</param> /// <returns> /// Simple forward rate (in the day count) for the given period. /// Note: if the start and end date of the period are equal, then the /// function returns the value 0.0. /// </returns> public static decimal ComputeForwardRate (NamedValueSet capletBootstrapSettings, double[] offsets, double[] discountFactors, DateTime startDate, DateTime endDate) { // Check that the End Date is not before the Start Date. var dateDiff = endDate - startDate; const string dateErrorMessage = "End date cannot be before start date for a forward rate"; DataQualityValidator.ValidateMinimum (dateDiff.Days, 0.0d, dateErrorMessage, true); // Check for the special case of a zero length period. if (dateDiff.Days == 0) { return(0.0m); } // Compute the discount factor at the start and end of the period. var dfToStart = ComputeDiscountFactor (capletBootstrapSettings, offsets, discountFactors, startDate); var dfToEnd = ComputeDiscountFactor (capletBootstrapSettings, offsets, discountFactors, endDate); // Compute the year fraction. var dayCount = capletBootstrapSettings.GetValue("DayCount", "ACT/365.FIXED"); IDayCounter dayCountObj = DayCounterHelper.Parse(dayCount); var tau = (decimal)dayCountObj.YearFraction (startDate, endDate); // Compute and validate the forward rate. var forwardRate = (dfToStart - dfToEnd) / (tau * dfToEnd); const string rateErrorMessage = "Negative forward rate encountered: check inputs"; DataQualityValidator.ValidateMinimum (forwardRate, 0.0m, rateErrorMessage, true); return(forwardRate); }
/// <summary> /// Helper function used to validate all constructor arguments. /// </summary> /// <param name="notional">Caplet/Floorlet face value.</param> /// <param name="optionExpiry">Option expiry expressed in years /// as an ACT/365 day count.</param> /// <param name="strike">Option strike expressed as a decimal.</param> /// <param name="tau">Year fraction for the Caplet/Floorlet.</param> private static void ValidateConstructorArguments (decimal notional, decimal optionExpiry, decimal strike, decimal tau) { // Validate notional. const string notionalErrorMessage = "Notional for a Caplet/Floorlet must be positive"; DataQualityValidator.ValidatePositive(notional, notionalErrorMessage, true); // Validate option expiry. const string optionExpiryErrorMessage = "Expiry for a Caplet/Floorlet cannot be negative"; DataQualityValidator.ValidateMinimum(optionExpiry, 0m, optionExpiryErrorMessage, true); // Validate strike. const string strikeErrorMessage = "Strike for a Caplet/Floorlet must be positive"; DataQualityValidator.ValidatePositive(strike, strikeErrorMessage, true); // Validate tau. const string tauErrorMessage = "Year fraction for a Caplet/Floorlet must be positive"; DataQualityValidator.ValidatePositive(tau, tauErrorMessage, true); }