public virtual double CalculateQuoteError() { var curve = new SimpleDiscountFactorCurve(BaseDate, InterpolationMethod, Extrapolation, Dfs); var impliedQuote = PriceableAsset.CalculateImpliedQuote(curve); return((double)(Quote - impliedQuote)); }
/// <summary> /// Bootstraps the specified priceable assets. /// </summary> /// <param name="priceableAssets">The priceable assets.</param> /// <param name="baseDate">The base date.</param> /// <param name="extrapolationPermitted">The extrapolationPermitted flag.</param> /// <param name="interpolationMethod">The interpolationMethod.</param> /// <param name="tolerance">Solver tolerance to use.</param> /// <returns></returns> public static TermPoint[] Bootstrap(IEnumerable <IPriceableRateAssetController> priceableAssets, DateTime baseDate, Boolean extrapolationPermitted, InterpolationMethod interpolationMethod, Double tolerance) { const double defaultGuess = 0.9; const double min = 0.000000001; const double max = 2; //only works for linear on zero. InterpolationMethod interp = InterpolationMethodHelper.Parse("LogLinearInterpolation"); // Add the first element (date : discount factor) to the list var points = new Dictionary <DateTime, double> { { baseDate, 1d } }; var items = new Dictionary <DateTime, Pair <string, decimal> > { { baseDate, new Pair <string, decimal>("", 1m) } }; var solver = new Brent(); bool first = true; // Add the rest foreach (IPriceableRateAssetController priceableAsset in priceableAssets) { DateTime assetMaturityDate = priceableAsset.GetRiskMaturityDate(); if (points.Keys.Contains(assetMaturityDate)) { continue; } if (assetMaturityDate < points.Keys.Last()) { throw new InvalidOperationException("The maturity dates of the assets must be consecutive order"); } if (first) { first = false; // Add the first point points.Add(assetMaturityDate, defaultGuess); var curve = new SimpleDiscountFactorCurve(baseDate, interp, extrapolationPermitted, points); points[assetMaturityDate] = (double)priceableAsset.CalculateDiscountFactorAtMaturity(curve); } else { //This now should automatically extrapolate the required discount factor on a flat rate basis. var curve = new SimpleDiscountFactorCurve(baseDate, interp, extrapolationPermitted, points); //The first guess, which should be correct for all priceable assets with analytical solutions that have been implemented. points.Add(assetMaturityDate, (double)priceableAsset.CalculateDiscountFactorAtMaturity(curve)); } var objectiveFunction = new RateAssetQuote(priceableAsset, baseDate, interpolationMethod, extrapolationPermitted, points, tolerance); // Check whether the guess was close enough if (!objectiveFunction.InitialValue()) { double guess = Math.Max(min, points[assetMaturityDate]); points[assetMaturityDate] = solver.Solve(objectiveFunction, tolerance, guess, min, max); } items.Add(assetMaturityDate, new Pair <string, decimal>(priceableAsset.Id, (decimal)points[assetMaturityDate])); } return(TermPointsFactory.Create(items)); }
/// <summary> /// Create a series of CapFloor engines from a raw volatility grid and a DF curve /// </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 engine, including the reference handle to access this engine collection</param> /// <param name="instruments">An array of instrument types.</param> /// <param name="rawVolatilityGrid">The raw grid used to build the engines. Assume that all volatility and strike values are 100x true</param> /// <param name="dfDataTimeGrid">The discount factor dates array.</param> /// <param name="dfGrid">The discount factors required for bootstrapping</param> /// <returns>The engine handle or an error message</returns> public string CreateCapFloorATMCurve(ILogger logger, ICoreCache cache, string nameSpace, NamedValueSet properties, String[] instruments, Decimal[] rawVolatilityGrid, DateTime[] dfDataTimeGrid, Decimal[] dfGrid) { var volatilityCheck = CheckVolatilities(rawVolatilityGrid); if (volatilityCheck != null) { throw new ArgumentException(volatilityCheck); } var id = properties.GetString("EngineHandle", true); var baseDate = properties.GetValue <DateTime>("BaseDate", true); var valuationDate = properties.GetValue("ValuationDate", DateTime.MinValue); if (valuationDate == DateTime.MinValue) { properties.Set("ValuationDate", baseDate); } properties.Set("PricingStructureType", PricingStructureTypeEnum.CapVolatilityCurve.ToString()); var strikeQuoteUnits = properties.GetString("StrikeQuoteUnits", null); if (strikeQuoteUnits == null) { properties.Set("StrikeQuoteUnits", StrikeQuoteUnitsEnum.ATMFlatMoneyness.ToString()); } var measureType = properties.GetString("MeasureType", null); if (measureType == null) { properties.Set("MeasureType", MeasureTypesEnum.Volatility.ToString()); } var quoteUnits = properties.GetString("QuoteUnits", null); if (quoteUnits == null) { properties.Set("QuoteUnits", QuoteUnitsEnum.LogNormalVolatility.ToString()); } var algorithm = properties.GetString("Algorithm", null); if (algorithm == null) { properties.Set("Algorithm", "Default"); } InterpolationMethod interp = InterpolationMethodHelper.Parse("LogLinearInterpolation"); // Check there are valid strikes IRateCurve discountCurve = new SimpleDiscountFactorCurve(baseDate, interp, true, dfDataTimeGrid, dfGrid); // Create the engines and either add to, or overwrite the existing, collection if (_capFloorEngine.ContainsKey(id)) { _capFloorEngine[id] = CreateCurves(logger, cache, nameSpace, properties, discountCurve, discountCurve, instruments, rawVolatilityGrid); } else { _capFloorEngine.Add(id, CreateCurves(logger, cache, nameSpace, properties, discountCurve, discountCurve, instruments, rawVolatilityGrid)); } return(id); }
/// <summary> /// An inital test to see if the guess was good.. /// </summary> /// <returns></returns> public Boolean InitialValue() { var curve = new SimpleDiscountFactorCurve(_baseDate, _interpolationMethod, _extrapolation, _dates, _dfs); var impliedQuote = _priceableAsset.CalculateImpliedQuote(curve); var marketQuote = MarketQuoteHelper.NormalisePriceUnits(_priceableAsset.MarketQuote, "DecimalRate").value; var quoteError = (double)(marketQuote - impliedQuote); return(Math.Abs(quoteError) < _cTolerance); }
static public IMarketEnvironment CreateSimpleInflationCurve(string curveName, DateTime baseDate, Double[] times, Double[] dfs) { var market = new MarketEnvironment(); var interpMethod = InterpolationMethodHelper.Parse("LinearInterpolation"); var curve = new SimpleDiscountFactorCurve(baseDate, interpMethod, true, times, dfs); market.AddPricingStructure(curveName, curve); return(market); }
/// <summary> /// Values the specified discount factor. /// </summary> /// <param name="discountFactor">The discount factor.</param> /// <returns></returns> public double Value(double discountFactor) { _dfs[_dfs.Length - 1] = discountFactor; var curve = new SimpleDiscountFactorCurve(_baseDate, _interpolationMethod, _extrapolation, _dates, _dfs); var impliedQuote = _priceableAsset.CalculateImpliedQuote(curve); var marketQuote = MarketQuoteHelper.NormalisePriceUnits(_priceableAsset.MarketQuote, "DecimalRate").value; var quoteError = (double)(marketQuote - impliedQuote); return(quoteError); }
static public ISimpleRateMarketEnvironment CreateSimpleRateMarketEnvironment(DateTime baseDate, Double[] times, Double[] dfs) { var market = new SimpleRateMarketEnvironment(); var interpMethod = InterpolationMethodHelper.Parse("LogLinearInterpolation"); var curve = new SimpleDiscountFactorCurve(baseDate, interpMethod, true, times, dfs); market.AddPricingStructure("DiscountCurve", curve); market.PricingStructureIdentifier = "DiscountCurve"; return(market); }
static public ISwapLegEnvironment CreateInterestRateStreamEnvironment(DateTime baseDate, Double[] times, Double[] dfs) { var market = new SwapLegEnvironment(); var interpMethod = InterpolationMethodHelper.Parse("LogLinearInterpolation"); var curve = new SimpleDiscountFactorCurve(baseDate, interpMethod, true, times, dfs); market.AddPricingStructure("DiscountCurve", curve); market.AddPricingStructure("ForecastCurve", curve); return(market); }
static public IMarketEnvironment CreateDFandVolCurves(string curveName, string volcurveName, DateTime baseDate, Double[] times, Double[] dfs, Double[] voltimes, Double[] volstrikes, Double[,] vols) { var market = new MarketEnvironment(); var interpMethod = InterpolationMethodHelper.Parse("LinearInterpolation"); var curve = new SimpleDiscountFactorCurve(baseDate, interpMethod, true, times, dfs); var volcurve = new SimpleVolatilitySurface(baseDate, interpMethod, true, voltimes, volstrikes, vols); market.AddPricingStructure(curveName, curve); market.AddPricingStructure(volcurveName, volcurve); return(market); }
private static IRateCurve GetDiscountFactorCurveFromObject(object discountFactorCurveObject, string paramName) { IRateCurve curve; if (discountFactorCurveObject is IRateCurve o) { curve = o; } else { if (discountFactorCurveObject is object[,] array) { // extract from [ , ] // [ , ] // [ , ] // [ , ] array var discountFactorCurveObjectAsArray = array; int dim0LowerBound = (discountFactorCurveObjectAsArray).GetLowerBound(0); int dim1LowerBound = (discountFactorCurveObjectAsArray).GetLowerBound(1); int dim0UpperBound = (discountFactorCurveObjectAsArray).GetUpperBound(0); var listDt = new List <DateTime>(); var listDf = new List <double>(); for (int i = dim0LowerBound; i <= dim0UpperBound; ++i) { var dt = (DateTime)discountFactorCurveObjectAsArray[i, dim1LowerBound]; var df = (double)discountFactorCurveObjectAsArray[i, dim1LowerBound + 1]; listDt.Add(dt); listDf.Add(df); } DateTime baseDate = listDt[0]; InterpolationMethod interp = InterpolationMethodHelper.Parse("LinearInterpolation"); //SimpleDFToZeroRateCurve curve = new SimpleDFToZeroRateCurve(baseDate, interp, false, dates, dfs); curve = new SimpleDiscountFactorCurve(baseDate, interp, false, listDt.ToArray(), listDf.ToArray()); } else { var message = $"{paramName} is invalid"; throw new ArgumentException(message, paramName); } } return(curve); }
/// <summary> /// Create a Sortedlist of bootstrap engines from the data matrix /// </summary> /// <param name="logger">The logger</param> /// <param name="cache">The cache.</param> /// <param name="nameSpace"></param> /// <param name="engineHandle">The engine collection name</param> /// <param name="matrix">The internal data structure used in conversion</param> /// <param name="properties">The properties object to use</param> /// <returns></returns> private static SortedList <decimal, CapVolatilityCurve> CreateEngines(ILogger logger, ICoreCache cache, string nameSpace, string engineHandle, CapFloorVolatilityMatrix matrix, NamedValueSet properties) { var engines = new SortedList <decimal, CapVolatilityCurve>(); // Check there is a valid settings object if (properties == null) { return(null); } var currency = properties.GetString("Currency", true); var baseDate = properties.GetValue("Calculation Date", DateTime.MinValue); properties.Set("EngineHandle", engineHandle); matrix.ValuationDate = baseDate; var valuationDate = properties.GetValue("ValuationDate", DateTime.MinValue); if (valuationDate == DateTime.MinValue) { properties.Set("ValuationDate", baseDate); } properties.Set("PricingStructureType", PricingStructureTypeEnum.CapVolatilityCurve.ToString()); var strikeQuoteUnits = properties.GetString("StrikeQuoteUnits", null); if (strikeQuoteUnits == null) { properties.Set("StrikeQuoteUnits", StrikeQuoteUnitsEnum.ATMFlatMoneyness.ToString()); } var measureType = properties.GetString("MeasureType", null); if (measureType == null) { properties.Set("MeasureType", MeasureTypesEnum.Volatility.ToString()); } var quoteUnits = properties.GetString("QuoteUnits", null); if (quoteUnits == null) { properties.Set("QuoteUnits", QuoteUnitsEnum.LogNormalVolatility.ToString()); } var algorithm = properties.GetString("Algorithm", null); if (algorithm == null) { properties.Set("Algorithm", "Default"); } InterpolationMethod interp = InterpolationMethodHelper.Parse("LogLinearInterpolation"); var dfs = matrix.DiscountFactorsAsDoubles(); // Check there are valid strikes IRateCurve discountCurve = new SimpleDiscountFactorCurve(baseDate, interp, true, dfs); //TODO //The quoted asset set var volTypes = matrix.CapVolatilities(); var instruments = new List <string>(); var volatilties = new List <decimal>(); foreach (var volType in volTypes) { string tempName; string tenor; var type = volType.VolatilityType; if (type == VolatilityDataType.ETO) { tempName = currency + "-Caplet-"; tenor = volType.Expiry + "D-90D"; } else { tempName = currency + "-IRCap-"; tenor = volType.Expiry + "Y"; } instruments.Add(tempName + tenor); volatilties.Add(volType.Volatility); } var qas = AssetHelper.Parse(instruments.ToArray(), volatilties.ToArray()); //The volatilities // Create a new ATM CapletBootstrap engine. The default decimal should be 0 var engine = new CapVolatilityCurve(logger, cache, nameSpace, properties, qas, discountCurve, discountCurve, null, null); // Add engine engines.Add(0, engine); return(engines); }