/// <summary>
        /// The constructor
        /// </summary>
        /// <param name="logger">The logger</param>
        /// <param name="surfaceId">The id to use with this matrix</param>
        /// <param name="nameSpace">The namespace</param>
        /// <param name="expiryTenors">An array of expiry definitions</param>
        /// <paparam name="strike">An array of strike descriptions</paparam>
        /// <param name="strikes">The strike array.</param>
        /// <param name="volSurface">A 2d array of volatilities.
        /// This must be equal to (expiry.Count x (1 &lt;= y &lt;= term.Count) x strike.Count </param>
        /// <param name="cache">The cache</param>
        protected ExpiryTermStrikeVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, String[] expiryTenors, Double[] strikes, Double[,] volSurface,
                                                    VolatilitySurfaceIdentifier surfaceId)
        {
            Algorithm = surfaceId.Algorithm;
            PricingStructureIdentifier = surfaceId;
            var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            var curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));

            _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey());
            var points = ProcessRawSurface(expiryTenors, strikes, volSurface, surfaceId.StrikeQuoteUnits, surfaceId.UnderlyingAssetReference);

            PricingStructure          = CreateVolatilityRepresentation(surfaceId);
            PricingStructureValuation = CreateDataPoints(points, surfaceId);
            var expiries = new double[expiryTenors.Length];
            var index    = 0;

            foreach (var term in expiryTenors)//TODO include business day holidays and roll conventions.
            {
                expiries[index] = PeriodHelper.Parse(term).ToYearFraction();
                index++;
            }
            // Record the row/column sizes of the inputs
            _matrixRowCount = expiryTenors.Length;
            // Columns includes expiry and term (tenor) if it exists.
            _matrixColumnCount = strikes.Length + 1;
            // Generate an interpolator to use
            Interpolator = new VolSurfaceInterpolator(expiries, strikes, new Matrix(volSurface), curveInterpolationMethod, true);
        }
        internal TermCurve SetConfigurationData()
        {
            // The bootstrapper to use
            if (Holder != null)
            {
                var bootstrapper = Holder.GetValue("Bootstrapper");
                if (bootstrapper != null)
                {
                    BootstrapperName = Holder.GetValue("Bootstrapper");
                }
                var extrapolationPermitted = Holder.GetValue("ExtrapolationPermitted");
                if (extrapolationPermitted != null)
                {
                    ExtrapolationPermitted = bool.Parse(extrapolationPermitted);
                }
                var interpolation = InterpolationMethodHelper.Parse(
                    Holder.GetValue("BootstrapperInterpolation"));
                if (interpolation != null)
                {
                    InterpolationMethod = interpolation;
                }
            }
            var termCurve = new TermCurve
            {
                extrapolationPermitted =
                    ExtrapolationPermitted,
                extrapolationPermittedSpecified = true,
                interpolationMethod             = InterpolationMethod
            };

            return(termCurve);
        }
        private void InitialiseInstance(ILogger logger, ICoreCache cache, string nameSpace, PricingStructureIdentifier curveId,
                                        DateTime baseDate, FxRateSet assetSet, IBusinessCalendar fixingCalendar, IBusinessCalendar rollCalendar, double tolerance)
        {
            FixingCalendar  = fixingCalendar;
            PaymentCalendar = rollCalendar;
            // The bootstrapper to use
            //
            BootstrapperName = Holder.GetValue("Bootstrapper");
            var termCurve = new TermCurve
            {
                extrapolationPermitted =
                    bool.Parse(Holder.GetValue("ExtrapolationPermitted")),
                extrapolationPermittedSpecified = true,
                interpolationMethod             =
                    InterpolationMethodHelper.Parse(
                        Holder.GetValue("BootstrapperInterpolation"))
            };

            PriceableCommodityAssets = PriceableAssetFactory.CreatePriceableCommodityAssets(logger, cache, nameSpace, curveId.BaseDate, assetSet, fixingCalendar, rollCalendar);
            termCurve.point          = CommodityBootstrapper.Bootstrap(PriceableCommodityAssets, curveId.BaseDate, termCurve.extrapolationPermitted,
                                                                       termCurve.interpolationMethod, tolerance);
            // Pull out the fx curve and fx curve valuation
            //
            var quotedAssetSet = PriceableCommodityAssets != null?PriceableAssetFactory.Parse(PriceableCommodityAssets) : assetSet;

            var fpmlData = CreateFpMLPair(baseDate, curveId, quotedAssetSet, termCurve);

            //Bootstrapper = Bootstrap(bootstrapperName, fpmlData.First, fpmlData.Second);
            SetFpMLData(fpmlData);
            // Interpolate the DiscountFactor curve based on the respective curve interpolation
            //
            SetInterpolator(baseDate, Holder);
        }
        /// <summary>
        /// Create a surface from an FpML
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="cache">The cache.</param>
        /// <param name="nameSpace">The nameSpace</param>
        /// <param name="fpmlData">The data.</param>
        /// <param name="properties">The properties.</param>
        protected ExtendedExpiryTermStrikeVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, Pair <PricingStructure, PricingStructureValuation> fpmlData, NamedValueSet properties)
        {
            var surfaceId = new VolatilitySurfaceIdentifier(properties);

            Algorithm = surfaceId.Algorithm;
            PricingStructureIdentifier = surfaceId;
            var data   = (VolatilityMatrix)fpmlData.Second;
            var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            //Get the forwards from the surface.
            var adjustments = new ParametricAdjustment();

            if (data.adjustment != null)
            {
                //assume the forwards are the first parameter set.
                adjustments = data.adjustment[0];
            }
            //Creates the property collection. This should be backward compatable with V1.
            PricingStructureIdentifier = new VolatilitySurfaceIdentifier(properties);
            var xDimensionInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("xDimensionInterpolation"));
            var yDimensionInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("yDimensionInterpolation"));

            // Generate an interpolator to use
            if (adjustments?.datapoint != null)
            {
                Interpolator = new ExtendedVolatilitySurfaceInterpolator(data.dataPoints, adjustments.datapoint, xDimensionInterpolationMethod.Value, yDimensionInterpolationMethod.Value);
            }
            SetFpMLData(fpmlData);
            _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey());
            ProcessVolatilityRepresentation();
        }
Beispiel #5
0
        /// <summary>
        /// Gets the quoted asset set.
        /// </summary>
        /// <returns></returns>
        public sealed override void Build(ILogger logger, ICoreCache cache, string nameSpace,
                                          IBusinessCalendar fixingCalendar, IBusinessCalendar rollCalendar)
        {
            var pricingStructureId = (RateCurveIdentifier)PricingStructureIdentifier;

            //Order the assets.
            PriceableRateSpreadAssets = PriceableRateSpreadAssets.OrderBy(a => a.GetRiskMaturityDate()).ToList();
            var termCurve = SetConfigurationData();

            //Get the reference interpolated curve.
            termCurve.point = RateSpreadBootstrapper.Bootstrap(PriceableRateSpreadAssets,//TODO what about the interpoation.
                                                               BaseCurve,
                                                               pricingStructureId.BaseDate,
                                                               termCurve.extrapolationPermitted,
                                                               Tolerance);
            CreatePricingStructure(pricingStructureId, termCurve, PriceableAssetFactory.Parse(PriceableRateSpreadAssets));
            SetInterpolator(BaseCurve, pricingStructureId.PricingStructureType);
            // Set the Zero curve, just for reference
            YieldCurveValuation yieldCurveValuation = GetYieldCurveValuation();

            if (yieldCurveValuation.zeroCurve?.rateCurve == null)
            {
                //var curveId = (RateCurveIdentifier)PricingStructureIdentifier;
                //var psType = PricingStructureIdentifier.PricingStructureType;
                TermCurve curve = YieldCurveAnalytics.ToZeroCurve(termCurve, GetBaseDate(), CompoundingFrequency, DayCounter);
                curve.interpolationMethod = InterpolationMethodHelper.Parse(Holder.GetValue("CurveInterpolation"));
                var zeroCurve = new ZeroRateCurve
                {
                    rateCurve            = curve,
                    compoundingFrequency = FpML.V5r3.Reporting.CompoundingFrequency.Create(CompoundingFrequency)
                };
                yieldCurveValuation.zeroCurve = zeroCurve;
            }
        }
Beispiel #6
0
        /// <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));
        }
Beispiel #7
0
        /// <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(List <IPriceableFxAssetController> priceableAssets,
                                            DateTime baseDate, Boolean extrapolationPermitted,
                                            InterpolationMethod interpolationMethod, Double tolerance)
        {
            const Double        solveRateGap     = 0.015d;//should we need more precising perhaps???
            const Decimal       dfamMinThreshold = 0.0m;
            const Decimal       defaultGuess     = 0.9m;
            const Double        accuracy         = 0.000001d;
            InterpolationMethod interp           = InterpolationMethodHelper.Parse("LinearInterpolation"); //only works for linear on zero.

            priceableAssets = priceableAssets.OrderBy(a => a.GetRiskMaturityDate()).ToList();
            var  dates           = new List <DateTime>();
            var  discountFactors = new List <double>();
            var  items           = new Dictionary <DateTime, Pair <string, decimal> >();
            bool firstTime       = true;

            foreach (var asset in priceableAssets)
            {
                DateTime assetMaturityDate = asset.GetRiskMaturityDate();
                //check if the maturity date is already in the list. If not contimue.
                if (items.ContainsKey(assetMaturityDate))
                {
                    continue;
                }
                decimal guess = asset.ForwardAtMaturity > dfamMinThreshold ? asset.ForwardAtMaturity : defaultGuess;
                decimal dfam;
                if (firstTime)
                {
                    firstTime = false;
                    dates.Add(assetMaturityDate);
                    discountFactors.Add(Convert.ToDouble(guess));
                    dfam = asset.CalculateImpliedQuote(new SimpleFxCurve(baseDate, interp, extrapolationPermitted, dates, discountFactors));
                    discountFactors[0] = (double)dfam;
                }
                else
                {
                    //The first guess, which should be correct for all priceable assets with analytical solutions that have been implemented.
                    //So far this is only wrt Depos and Futures...This now should automatically extrapolate the required discount factor on a flat rate basis.
                    dfam = asset.CalculateImpliedQuote(new SimpleFxCurve(baseDate, interp, extrapolationPermitted, dates, discountFactors));
                    discountFactors.Add((double)dfam);
                    dates.Add(assetMaturityDate);
                }
                //Add a check on the dfam so that the solver is only called if outside the tolerance.
                var objectiveFunction = new FxAssetQuote(asset, baseDate, interpolationMethod,
                                                         extrapolationPermitted, dates, discountFactors, tolerance);
                if (!objectiveFunction.InitialValue())
                {
                    var timeInterval  = Actual365.Instance.YearFraction(baseDate, assetMaturityDate);
                    var solveInterval = Math.Exp(-solveRateGap * timeInterval);
                    var min           = Math.Max(0, (double)dfam * solveInterval);
                    var max           = (double)dfam / solveInterval;
                    var solver        = new Brent();
                    dfam = (decimal)solver.Solve(objectiveFunction, accuracy, (double)dfam, min, max);
                }
                items.Add(assetMaturityDate, new Pair <string, decimal>(asset.Id, dfam));
            }
            return(TermPointsFactory.Create(items));
        }
Beispiel #8
0
        /// <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>
        /// Takes a range of volatilities, an array of tenor expiries and an
        /// array of strikes to create a VolatilitySurface
        /// </summary>
        /// <param name="nameSpace"></param>
        /// <param name="expiryTenors"></param>
        /// <param name="strikes"></param>
        /// <param name="volSurface"></param>
        /// <param name="surfaceId"></param>
        /// <param name="logger"></param>
        /// <param name="cache">The cache.</param>
        /// <param name="forwards">The array of forwards. The first element is the spot value. Conseuently, the length of this array is expiryTenors.Length + 1.</param>
        protected ExtendedExpiryTermStrikeVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, String[] expiryTenors, Double[] strikes, Double[] forwards, Double[,]
                                                            volSurface, VolatilitySurfaceIdentifier surfaceId)
        {
            Algorithm = surfaceId.Algorithm;
            PricingStructureIdentifier = surfaceId;
            //Build the parameteric adjustment set from th3e forwards.
            var parametricAdjustment = GenerateForwards(forwards);
            var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            var xDimensionInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("xDimensionInterpolation"));
            var yDimensionInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("yDimensionInterpolation"));

            _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey());
            var points = ProcessRawSurface(expiryTenors, strikes, volSurface, surfaceId.StrikeQuoteUnits, surfaceId.UnderlyingAssetReference);

            PricingStructure = new VolatilityRepresentation
            {
                name     = surfaceId.Name,
                id       = surfaceId.Id,
                currency = surfaceId.Currency,
                asset    = new AnyAssetReference {
                    href = surfaceId.Instrument
                },
            };
            var datapoints = new MultiDimensionalPricingData {
                point = points
            };

            PricingStructureValuation = new VolatilityMatrix
            {
                dataPoints = datapoints
                ,
                adjustment = parametricAdjustment
                ,
                objectReference = new AnyAssetReference {
                    href = surfaceId.Instrument
                }
                ,
                baseDate = new IdentifiedDate {
                    Value = surfaceId.BaseDate
                }
                , buildDateTime          = DateTime.Now
                , buildDateTimeSpecified = true
            };
            var expiries = new double[expiryTenors.Length];
            var index    = 0;

            foreach (var term in expiryTenors)//TODO include business day holidays and roll conventions.
            {
                expiries[index] = PeriodHelper.Parse(term).ToYearFraction();
                index++;
            }
            // Record the row/column sizes of the inputs
            _matrixRowCount = expiryTenors.Length;
            // Columns includes expiry and term (tenor) if it exists.
            _matrixColumnCount = strikes.Length + 1;
            // Generate an interpolator to use
            Interpolator = new ExtendedVolatilitySurfaceInterpolator(expiries, strikes, forwards, new Matrix(volSurface), xDimensionInterpolationMethod.Value, yDimensionInterpolationMethod.Value);
        }
        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);
        }
        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);
        }
Beispiel #14
0
        internal TermCurve SetConfigurationData()
        {
            // The bootstrapper to use
            BootstrapperName = Holder.GetValue("Bootstrapper");
            var termCurve = new TermCurve
            {
                extrapolationPermitted          = bool.Parse(Holder.GetValue("ExtrapolationPermitted")),
                extrapolationPermittedSpecified = true,
                interpolationMethod             = InterpolationMethodHelper.Parse(Holder.GetValue("BootstrapperInterpolation"))
            };

            return(termCurve);
        }
Beispiel #15
0
        /// <summary>
        /// Sets the interpolator.
        /// </summary>
        /// <param name="baseDate">The base date.</param>
        /// <param name="holder">The holder.</param>
        private void SetInterpolator(DateTime baseDate, PricingStructureAlgorithmsHolder holder)
        {
            // The underlying curve and associated compounding frequency (compounding frequency required when underlying curve is a ZeroCurve)
            var curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));
            var dayCounter = DayCounterHelper.Parse(holder.GetValue("DayCounter"));

            UnderlyingInterpolatedCurve = holder.GetValue("UnderlyingCurve"); //TODO this redundant.
            // Retrieve the Discount factor curve and assign the curve interpolation we want to initiate
            // This dependends on the underyling curve type (i.e. rate or discount factor)
            var termCurve = GetFxCurveValuation().fxForwardCurve;

            termCurve.interpolationMethod = curveInterpolationMethod;
            // interpolate the DiscountFactor curve based on the respective curve interpolation
            Interpolator = new CommodityCurveInterpolator(termCurve, baseDate, dayCounter);
        }
Beispiel #16
0
        /// <summary>
        /// Sets the interpolator.
        /// </summary>
        private void SetInterpolator(DateTime baseDate)
        {
            // The underlying curve and associated compounding frequency (compounding frequency required when underlying curve is a ZeroCurve)
            InterpolationMethod curveInterpolationMethod = InterpolationMethodHelper.Parse(Holder.GetValue("CurveInterpolation"));
            IDayCounter         dayCounter = DayCounterHelper.Parse(Holder.GetValue("DayCounter"));

            UnderlyingInterpolatedCurve = Holder.GetValue("UnderlyingCurve");
            // Retrieve the Discount factor curve and assign the curve interpolation we want to initiate
            // This dependends on the underyling curve type (i.e. rate or discount factor)
            TermCurve termCurve = GetEquityCurveValuation().fxForwardCurve;

            termCurve.interpolationMethod = curveInterpolationMethod;
            // interpolate the DiscountFactor curve based on the respective curve interpolation
            Interpolator = new FxCurveInterpolator(termCurve, baseDate, dayCounter);
        }
        /// <summary>
        /// Create a surface from an FpML
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="cache"></param>
        /// <param name="nameSpace"></param>
        /// <param name="fpmlData"></param>
        /// <param name="properties"></param>
        public ExpiryTermTenorStrikeVolatilityCube(ILogger logger, ICoreCache cache, String nameSpace, Pair <PricingStructure, PricingStructureValuation> fpmlData, NamedValueSet properties)
        {
            var surfaceId = new VolatilitySurfaceIdentifier(properties);

            Algorithm = surfaceId.Algorithm;
            PricingStructureIdentifier = surfaceId;
            var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);

            Algorithm = "Linear"; //Add as a propert in the id.
            var      curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));
            var      data     = (VolatilityMatrix)fpmlData.Second;
            DateTime baseDate = data.baseDate.Value;

            Interpolator = new VolSurfaceInterpolator(data.dataPoints, curveInterpolationMethod, true, baseDate);
            SetFpMLData(fpmlData);
        }
        /// <summary>
        /// Create a surface from an FpML
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="cache">The cache.</param>
        /// <param name="nameSpace">The nameSpace</param>
        /// <param name="fpmlData">The data.</param>
        /// <param name="properties">The properties.</param>
        protected ExpiryTermStrikeVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, Pair <PricingStructure, PricingStructureValuation> fpmlData, NamedValueSet properties)
        {
            var data = (VolatilityMatrix)fpmlData.Second;

            Algorithm = "Linear";//Add as a property in the id.
            //Creates the property collection. This should be backward compatable with V1.
            var surfaceId = new VolatilitySurfaceIdentifier(properties);

            PricingStructureIdentifier = surfaceId;
            var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            var curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));

            Interpolator = new VolSurfaceInterpolator(data.dataPoints, curveInterpolationMethod, true, PricingStructureIdentifier.BaseDate);
            SetFpmlData(fpmlData);
            _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey());
            ProcessVolatilityRepresentation();
        }
Beispiel #19
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RateBasisCurve"/> class.
        /// </summary>
        /// <param name="referenceCurve">The reference curve.</param>
        /// <param name="spreadAssets">The spreads by asset.</param>
        /// <param name="properties">The properties of the new spread curve.</param>
        /// <param name="algorithm">The algorithm holder. </param>
        public RateBasisCurve(NamedValueSet properties, IRateCurve referenceCurve,
                              List <IPriceableRateSpreadAssetController> spreadAssets, PricingStructureAlgorithmsHolder algorithm)
            : base(properties, algorithm)
        {
            PricingStructureData = new PricingStructureData(CurveType.Child, AssetClass.Rates, properties);
            //Set the identifier.
            var pricingStructureId = GetRateCurveId();

            if (pricingStructureId.PricingStructureType != PricingStructureTypeEnum.RateBasisCurve)
            {
                return;
            }
            //Set the reference curve
            BaseCurve                 = referenceCurve;
            ReferenceCurveId          = BaseCurve.GetPricingStructureId();
            PriceableRateSpreadAssets = spreadAssets;
            //Order the assets.
            PriceableRateSpreadAssets = PriceableRateSpreadAssets.OrderBy(a => a.GetRiskMaturityDate()).ToList();
            var termCurve = SetConfigurationData();

            //Get the reference interpolated curve.
            termCurve.point = RateSpreadBootstrapper.Bootstrap(PriceableRateSpreadAssets,
                                                               BaseCurve,
                                                               pricingStructureId.BaseDate,
                                                               termCurve.extrapolationPermitted,
                                                               Tolerance);
            CreatePricingStructure(pricingStructureId, termCurve, PriceableAssetFactory.Parse(PriceableRateSpreadAssets));
            SetInterpolator(BaseCurve, pricingStructureId.PricingStructureType);
            // Set the Zero curve, just for reference
            YieldCurveValuation yieldCurveValuation = GetYieldCurveValuation();

            if (yieldCurveValuation.zeroCurve?.rateCurve == null)
            {
                //var curveId = (RateCurveIdentifier)PricingStructureIdentifier;
                //var psType = PricingStructureIdentifier.PricingStructureType;
                TermCurve curve = YieldCurveAnalytics.ToZeroCurve(termCurve, GetBaseDate(), CompoundingFrequency, DayCounter);
                curve.interpolationMethod = InterpolationMethodHelper.Parse(Holder.GetValue("CurveInterpolation"));
                var zeroCurve = new ZeroRateCurve
                {
                    rateCurve            = curve,
                    compoundingFrequency = FpML.V5r3.Reporting.CompoundingFrequency.Create(CompoundingFrequency)
                };
                yieldCurveValuation.zeroCurve = zeroCurve;
            }
        }
Beispiel #20
0
        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>
        /// Takes a range of volatilities, an array of tenor expiries and an
        /// array of strikes to create a VolatilitySurface
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="cache"></param>
        /// <param name="nameSpace"></param>
        /// <param name="expiryTenors"></param>
        /// <param name="strikes"></param>
        /// <param name="volSurface"></param>
        /// <param name="surfaceId"></param>
        public ExpiryTermTenorStrikeVolatilityCube(ILogger logger, ICoreCache cache, String nameSpace, String[] expiryTenors, Double[] strikes, Double[,] volSurface,
                                                   VolatilitySurfaceIdentifier surfaceId)
        {
            Algorithm = surfaceId.Algorithm;
            var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            var curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));
            var points = ProcessRawSurface(expiryTenors, strikes, volSurface);

            PricingStructure = new VolatilityRepresentation {
                name  = surfaceId.Name,
                id    = surfaceId.Id,
                asset = new AnyAssetReference {
                    href = "Unknown"
                },
            };
            var datapoints = new MultiDimensionalPricingData {
                point = points
            };

            PricingStructureValuation = new VolatilityMatrix
            {
                dataPoints        = datapoints
                , objectReference = new AnyAssetReference {
                    href = PricingStructure.id
                }
                ,
                baseDate = new IdentifiedDate {
                    Value = surfaceId.BaseDate
                }
                , buildDateTime          = DateTime.Now
                , buildDateTimeSpecified = true
            };
            var expiries = new double[expiryTenors.Length];
            var index    = 0;

            foreach (var term in expiryTenors)//TODO include business day holidays and roll conventions.
            {
                expiries[index] = PeriodHelper.Parse(term).ToYearFraction();
                index++;
            }
            // Generate an interpolator to use
            Interpolator = new VolSurfaceInterpolator(expiries, strikes, new Matrix(volSurface), curveInterpolationMethod, true);
        }
Beispiel #22
0
        private void CreateYieldCurve()
        {
            var curveId = (RateCurveIdentifier)PricingStructureIdentifier;
            InterpolationMethod interpolationMethod =
                InterpolationMethodHelper.Parse(Holder.GetValue("BootstrapperInterpolation"));
            bool extrapolationPermitted = bool.Parse(Holder.GetValue("ExtrapolationPermitted"));

            TermPoint[] points = BaseCurve != null ? new RateBootstrapperNewtonRaphson().Bootstrap(PriceableRateAssets, BaseCurve, Holder) : null;
            //TermPoint[] points = BaseCurve != null ? RateXccySpreadBootstrapper.Bootstrap(PriceableRateAssets, BaseCurve, Holder) : null;
            var termCurve = new TermCurve
            {
                extrapolationPermitted          = extrapolationPermitted,
                extrapolationPermittedSpecified = true,
                interpolationMethod             = interpolationMethod,
                point = points
            };

            CreatePricingStructure(curveId, termCurve, PriceableRateAssets, null);
        }
Beispiel #23
0
        private void InitialiseInstance(ILogger logger, ICoreCache cache, string nameSpace,
                                        NamedValueSet properties, FxRateSet assetSet, IBusinessCalendar fixingCalendar, IBusinessCalendar rollCalendar)
        {
            PricingStructureData = new PricingStructureData(CurveType.Parent, AssetClass.Equity, properties);
            var curveId = new EquityCurveIdentifier(properties);

            PricingStructureIdentifier = curveId;
            Holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, curveId.PricingStructureType, curveId.Algorithm);
            DateTime baseDate = PricingStructureIdentifier.BaseDate;

            //Set the spot date;
            SettlementDate = GetSettlementDate(logger, cache, nameSpace, GetEquityCurveId(), fixingCalendar, rollCalendar, baseDate);
            //TODO
            //FixingCalendar = null;
            //RollCalendar = null;
            // The bootstrapper to use
            BootstrapperName = Holder.GetValue("Bootstrapper");
            Tolerance        = double.Parse(Holder.GetValue("Tolerance"));
            bool extrapolationPermitted             = bool.Parse(Holder.GetValue("ExtrapolationPermitted"));
            InterpolationMethod interpolationMethod = InterpolationMethodHelper.Parse(Holder.GetValue("BootstrapperInterpolation"));
            var termCurve = new TermCurve
            {
                extrapolationPermitted          = extrapolationPermitted,
                extrapolationPermittedSpecified = true,
                interpolationMethod             = interpolationMethod
            };

            PriceableEquityAssets = PriceableAssetFactory.CreatePriceableEquityAssets(logger, cache, nameSpace, baseDate, assetSet, fixingCalendar, rollCalendar);
            termCurve.point       = EquityBootstrapper.Bootstrap(PriceableEquityAssets, baseDate, termCurve.extrapolationPermitted,
                                                                 termCurve.interpolationMethod, Tolerance);
            // Pull out the fx curve and fx curve valuation
            Pair <PricingStructure, PricingStructureValuation> fpmlData
                = CreateFpmlPair(logger, cache, nameSpace, baseDate, (EquityCurveIdentifier)PricingStructureIdentifier, assetSet, termCurve, fixingCalendar, rollCalendar);

            SetFpmlData(fpmlData);
            // Interpolate the DiscountFactor curve based on the respective curve interpolation
            SetInterpolator(baseDate);
        }
Beispiel #24
0
        //TODO this is not yet implemented. FIX IT!
        internal void SetSpreadInterpolator(TermCurve discountFactorCurve, string algorithm, PricingStructureTypeEnum psType)
        {
            var curveId = (RateCurveIdentifier)PricingStructureIdentifier;

            // The underlying curve and associated compounding frequency (compounding frequency required when underlying curve is a ZeroCurve)
            CompoundingFrequency        = EnumHelper.Parse <CompoundingFrequencyEnum>(Holder.GetValue("CompoundingFrequency"));
            UnderlyingInterpolatedCurve = Holder.GetValue("UnderlyingCurve"); //TODO this redundant.
            var interpDayCounter = Actual365.Instance;
            var underlyingCurve  = ParseUnderlyingCurve(UnderlyingInterpolatedCurve);

            // interpolate the DiscountFactor curve based on the respective curve interpolation
            if (underlyingCurve != UnderlyingCurveTypes.ZeroCurve)
            {
                Interpolator = new TermCurveInterpolator(discountFactorCurve, GetBaseDate(), interpDayCounter);
            }
            // otherwise interpolate our underlying curve will be a zero curve
            else
            {
                var zeroCurve = new ZeroRateCurve
                {
                    rateCurve = YieldCurveAnalytics.ToZeroCurve(discountFactorCurve,
                                                                GetBaseDate(),
                                                                CompoundingFrequency, DayCounter)
                };
                zeroCurve.rateCurve.interpolationMethod = InterpolationMethodHelper.Parse(Holder.GetValue("CurveInterpolation"));
                zeroCurve.compoundingFrequency          = FpML.V5r3.Reporting.CompoundingFrequency.Create(CompoundingFrequency);
                GetYieldCurveValuation().zeroCurve      = zeroCurve;
                if (curveId.Algorithm == "SpreadInterpolation")
                {
                }
                else
                {
                    Interpolator =
                        new TermCurveInterpolator(GetYieldCurveValuation().zeroCurve.rateCurve, GetBaseDate(), interpDayCounter);
                }//TODO this is where to add the spread stuff.
            }
        }
Beispiel #25
0
        /// <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(List <IPriceableCommodityAssetController> priceableAssets,
                                            DateTime baseDate, Boolean extrapolationPermitted,
                                            InterpolationMethod interpolationMethod, Double tolerance)
        {
            //const Double cSolveRateGap = 0.015d;//should we need more precising perhaps???
            //const double Min = 0.000000001;
            //const double max = 2;
            const double defaultGuess = 0.9;

            //const Double accuracy = 0.000001d;
            priceableAssets.Sort
            (
                (priceableAssetController1, priceableAssetController2) =>
                priceableAssetController1.GetRiskMaturityDate().CompareTo(priceableAssetController2.GetRiskMaturityDate())
            );
            //  Add the first element (date : discount factor) to the list
            //
            //  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) } }
            bool first = true;

            foreach (var priceableAsset in priceableAssets)
            {
                //TODO check if the maturity date is already in the list. If not contimue.
                var assetMaturityDate = priceableAsset.GetRiskMaturityDate();
                if (points.Keys.Contains(assetMaturityDate))
                {
                    continue;
                }
                // do we really need that guess step??? I don't think so...
                //
                //if (assetMaturityDate < points.Keys.Last())
                //{
                //    throw new InvalidOperationException("The maturity dates of the assets must be consecutive order");
                //}
                //only works for linear on zero.
                var     interp = InterpolationMethodHelper.Parse("LinearInterpolation");
                decimal dfam;
                if (first)
                {
                    first = false;
                    // Add the first point
                    points.Add(assetMaturityDate, defaultGuess);
                    var curve = new SimpleCommodityCurve(baseDate, interp, extrapolationPermitted, points);
                    dfam = priceableAsset.CalculateImpliedQuote(curve);
                    points[assetMaturityDate] = (double)dfam;
                }
                else
                {
                    //The first guess, which should be correct for all priceable assets with analytical solutions that have been implemented.
                    //So far this is only wrt Depos and Futures...This now should automatically extrapolate the required discount factor on a flat rate basis.
                    var curve = new SimpleCommodityCurve(baseDate, interp, extrapolationPermitted, points);
                    //The first guess, which should be correct for all priceable assets with analytical solutions that have been implemented.
                    dfam = priceableAsset.CalculateImpliedQuote(curve);
                    points.Add(assetMaturityDate, (double)dfam);
                }
                //Add a check on the dfam so that the solver is only called if outside tyhe tolerance.
                //var objectiveFunction = new CommodityAssetQuote(priceableAsset, baseDate, interpolationMethod,
                //                                         extrapolationPermitted, points, tolerance);
                //// Check whether the guess was close enough
                //if (!objectiveFunction.InitialValue())
                //{
                //    var timeInterval = Actual365.Instance.YearFraction(baseDate, assetMaturityDate);
                //    var cSolveInterval = Math.Exp(-cSolveRateGap * timeInterval);
                //    var min = Math.Max(0,(double)dfam * cSolveInterval);
                //    var max = (double)dfam / cSolveInterval;
                //    double guess = Math.Max(min, points[assetMaturityDate]);
                //    var solver = new Brent();
                //    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 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);
        }
        /// <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(List <IPriceableCreditAssetController> priceableAssets,
                                            DateTime baseDate, Boolean extrapolationPermitted,
                                            InterpolationMethod interpolationMethod, Double tolerance)
        {
            const Double  cSolveRateGap     = 0.015d;//should be need more precise perhaps???
            const Decimal cDfamMinThreshold = 0.0m;
            const Decimal cDefaultGuess     = 0.9m;
            const Double  accuracy          = 0.000001d;

            priceableAssets.Sort
            (
                (priceableAssetController1, priceableAssetController2) =>
                priceableAssetController1.GetRiskMaturityDate().CompareTo(priceableAssetController2.GetRiskMaturityDate())
            );
            //  Add the first element (date : discount factor) to the list
            //
            IList <DateTime> dates = new List <DateTime> {
                baseDate
            };
            IList <double> discountFactors = new List <double> {
                1.0
            };
            var index = 0;

            foreach (var priceableAsset in priceableAssets)
            {
                //TODO check if the maturity date is already in the list. If not contimue.
                var assetMaturityDate = priceableAsset.GetRiskMaturityDate();
                if (dates.Contains(assetMaturityDate))
                {
                    continue;
                }
                // do we really need that guess step??? I don't think so...
                //
                var guess = priceableAsset.SurvivalProbabilityAtMaturity;
                if (guess <= cDfamMinThreshold)
                {
                    guess = cDefaultGuess;
                }
                //dates.Add(priceableAsset.GetRiskMaturityDate());
                decimal  dfam;
                double[] values;
                //var position = dates.IndexOf(priceableAsset.GetRiskMaturityDate());
                //discountFactors.CopyTo(values, 0);
                //only works for linear on zero.
                var interp = InterpolationMethodHelper.Parse("LogLinearInterpolation");
                if (index == 0)
                {
                    dates.Add(priceableAsset.GetRiskMaturityDate());
                    values = new double[dates.Count];
                    var position = dates.IndexOf(priceableAsset.GetRiskMaturityDate());
                    discountFactors.CopyTo(values, 0);
                    values[position] = Convert.ToDouble(guess);
                    dfam             = priceableAsset.CalculateImpliedQuote(new SimpleDiscountFactorCurve(baseDate, interp, extrapolationPermitted, dates, values));
                    values[position] = (double)dfam;
                    index++;
                }
                else
                {
                    //The first guess, which should be correct for all priceable assets with analytical solutions that have been implemented.
                    //So far this is only wrt Depos and Futures...This now should automatically extrapolate the required discount factor on a flat rate basis.
                    var tempvalues = new List <double>(discountFactors);
                    dfam = priceableAsset.CalculateImpliedQuote(new SimpleDiscountFactorCurve(baseDate, interp, extrapolationPermitted, dates, tempvalues.ToArray()));
                    tempvalues.Add((double)dfam);
                    dates.Add(priceableAsset.GetRiskMaturityDate());
                    values = new double[dates.Count];
                    tempvalues.CopyTo(values, 0);
                    index++;
                }
                //Add a check on the dfam so that the solver is only called if outside tyhe tolerance.
                var objectiveFunction = new CreditAssetQuote(priceableAsset, baseDate, interpolationMethod,
                                                             extrapolationPermitted, dates, values, tolerance);
                if (objectiveFunction.InitialValue())
                {
                    discountFactors.Add((double)dfam);
                }
                else
                {
                    var timeInterval         = Actual365.Instance.YearFraction(baseDate, assetMaturityDate);
                    var cSolveInterval       = Math.Exp(-cSolveRateGap * timeInterval);
                    var min                  = Math.Max(0, (double)dfam * cSolveInterval);
                    var max                  = (double)dfam / cSolveInterval;
                    var solver2              = new Brent();
                    var solvedFiscountFactor = solver2.Solve(objectiveFunction, accuracy, (double)dfam, min, max);
                    //TODO check that this is the correct usage of the optimizer.
                    discountFactors.Add(solvedFiscountFactor);
                }
            }
            return(TermPointsFactory.Create(dates, discountFactors));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="cache"></param>
        /// <param name="nameSpace"></param>
        /// <param name="properties"></param>
        /// <param name="expiries"></param>
        /// <param name="vols"></param>
        /// <param name="inputInstruments"></param>
        /// <param name="inputSwapRates"></param>
        /// <param name="inputBlackVolRates"></param>
        protected ExpiryTermStrikeVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, NamedValueSet properties, DateTime[] expiries, double[] vols,
                                                    string[] inputInstruments, double[] inputSwapRates, double[] inputBlackVolRates)
        {
            Algorithm = PropertyHelper.ExtractAlgorithm(properties);
            PricingStructureIdentifier = new VolatilitySurfaceIdentifier(properties);
            var surfaceId    = (VolatilitySurfaceIdentifier)PricingStructureIdentifier;
            var expiryLength = expiries.Length;
            var pointIndex   = 0;
            var points       = new PricingStructurePoint[expiryLength];

            _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey());
            for (var expiryIndex = 0; expiryIndex < expiryLength; expiryIndex++)
            {
                // extract the current expiry
                var expiryKeyPart = expiries[expiryIndex];
                var key           = new ExpiryTenorStrikeKey(expiryKeyPart.ToString(CultureInfo.InvariantCulture), 0);
                _matrixIndexHelper.Add(key, pointIndex);
                // Add the value to the points array (dataPoints entry in the matrix)
                var coordinates = new PricingDataPointCoordinate[1];
                coordinates[0] = new PricingDataPointCoordinate {
                    expiration = new TimeDimension[1]
                };
                coordinates[0].expiration[0] = new TimeDimension {
                    Items = new object[] { expiries[expiryIndex] }
                };
                var pt = new PricingStructurePoint
                {
                    value          = (decimal)vols[expiryIndex],
                    valueSpecified = true,
                    coordinate     = coordinates,
                };
                points[pointIndex++] = pt;
            }
            // Record the row/column sizes of the inputs
            _matrixRowCount           = expiries.Length;
            _matrixColumnCount        = 1;
            PricingStructure          = CreateVolatilityRepresentation(surfaceId);
            PricingStructureValuation = CreateDataPoints(points, surfaceId);
            if (inputInstruments != null)
            {
                int inputCount  = inputInstruments.GetUpperBound(0);
                var assetQuotes = new List <BasicAssetValuation>();
                var assetSet    = new List <Asset>();
                var itemsList   = new List <ItemsChoiceType19>();
                for (int i = 0; i <= inputCount; i++)
                {
                    var assetProperties = new PriceableAssetProperties(inputInstruments[i]);
                    assetSet.Add(new SimpleIRSwap {
                        id = inputInstruments[i], term = assetProperties.TermTenor
                    });
                    var rateQuote = BasicQuotationHelper.Create((decimal)inputSwapRates[i], AssetMeasureEnum.MarketQuote, PriceQuoteUnitsEnum.DecimalRate);
                    var volQuote  = BasicQuotationHelper.Create((decimal)inputBlackVolRates[i], AssetMeasureEnum.Volatility, PriceQuoteUnitsEnum.LogNormalVolatility);
                    assetQuotes.Add(new BasicAssetValuation
                    {
                        objectReference = new AnyAssetReference {
                            href = inputInstruments[i]
                        },
                        definitionRef = assetProperties.TermTenor.ToString(),
                        quote         = new[] { rateQuote, volQuote }
                    });
                    itemsList.Add(ItemsChoiceType19.simpleIrSwap);//TODO NOt actually correct.
                }
                var instrumentSet = new InstrumentSet {
                    Items = assetSet.ToArray(), ItemsElementName = itemsList.ToArray()
                };
                ((VolatilityMatrix)PricingStructureValuation).inputs
                    = new QuotedAssetSet {
                    assetQuote = assetQuotes.ToArray(), instrumentSet = instrumentSet
                    };
            }
            // Generate an interpolator to use
            double[] expiryTerms = expiries.Select(a => (surfaceId.BaseDate - a).TotalDays / 365d).ToArray();
            var      holder      = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            var      curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));

            Interpolator = new VolSurfaceInterpolator(expiryTerms, new double[] { 1 }, new Matrix(vols), curveInterpolationMethod, true);
        }
        /// <summary>
        /// Takes a range of volatilities, an array of tenor expiries and an
        /// array of strikes to create a VolatilitySurface
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="cache">The cache.</param>
        /// <param name="expiryTenors">the expiry tenors.</param>
        /// <param name="tenors">The tenors.</param>
        /// <param name="volSurface">The vol surface.</param>
        /// <param name="nameSpace">The namespace</param>
        /// <param name="properties">The properties.</param>
        protected ExpiryTermTenorATMVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, NamedValueSet properties, String[] expiryTenors, String[] tenors, Double[,] volSurface)
        {
            Algorithm = PropertyHelper.ExtractAlgorithm(properties);
            PricingStructureIdentifier = new VolatilitySurfaceIdentifier(properties);
            var surfaceId = (VolatilitySurfaceIdentifier)PricingStructureIdentifier;
            var holder    = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm);
            var curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation"));

            _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey());
            var points = ProcessRawSurface(expiryTenors, tenors, volSurface, surfaceId.UnderlyingAssetReference);

            PricingStructure = new VolatilityRepresentation
            {
                name     = surfaceId.Name,
                id       = surfaceId.Id,
                currency = surfaceId.Currency,
                asset    = new AnyAssetReference {
                    href = surfaceId.Instrument
                },
            };
            var datapoints = new MultiDimensionalPricingData {
                point             = points,
                businessCenter    = surfaceId.BusinessCenter,
                timing            = surfaceId.QuoteTiming,
                currency          = surfaceId.Currency,
                cashflowType      = surfaceId.CashflowType,
                informationSource = surfaceId.InformationSources,
                measureType       = surfaceId.MeasureType,
                quoteUnits        = surfaceId.QuoteUnits
            };

            if (surfaceId.ExpiryTime != null)
            {
                datapoints.expiryTime          = (DateTime)surfaceId.ExpiryTime;
                datapoints.expiryTimeSpecified = true;
            }
            if (surfaceId.ValuationDate != null)
            {
                datapoints.valuationDate          = (DateTime)surfaceId.ValuationDate;
                datapoints.valuationDateSpecified = true;
            }
            if (surfaceId.Time != null)
            {
                datapoints.time          = (DateTime)surfaceId.Time;
                datapoints.timeSpecified = true;
            }
            if (surfaceId.QuotationSide != null)
            {
                datapoints.side          = (QuotationSideEnum)surfaceId.QuotationSide;
                datapoints.sideSpecified = true;
            }
            PricingStructureValuation = new VolatilityMatrix
            {
                dataPoints      = datapoints,
                objectReference = new AnyAssetReference {
                    href = surfaceId.Instrument
                },
                baseDate = new IdentifiedDate {
                    Value = surfaceId.BaseDate
                },
                buildDateTime          = surfaceId.BuildDateTime,
                buildDateTimeSpecified = true
            };
            var expiries = new double[expiryTenors.Length];
            var index    = 0;

            foreach (var term in expiryTenors)//TODO include business day holidays and roll conventions.
            {
                expiries[index] = PeriodHelper.Parse(term).ToYearFraction();
                index++;
            }
            var tenor = new double[tenors.Length];

            index = 0;
            foreach (var term in tenors)//TODO include business day holidays and roll conventions.
            {
                tenor[index] = PeriodHelper.Parse(term).ToYearFraction();
                index++;
            }
            // Record the row/column sizes of the inputs
            _matrixRowCount  = expiryTenors.Length;
            _matrixRowCount *= tenors.Length;
            // Columns includes expiry and term (tenor) if it exists.
            _matrixColumnCount = 1;
            // Generate an interpolator to use
            Interpolator = new VolSurfaceInterpolator(expiries, tenor, new Matrix(volSurface), curveInterpolationMethod, true);
        }
        /// <summary>
        /// Bootstraps the specified priceable assets.
        /// </summary>
        /// <param name="priceableAssets">The priceable assets.</param>
        /// <param name="forecastCurve">The forecast rate curve.</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>
        /// <param name="discountCurve">The discount rate curve.</param>
        /// <param name="curveProperties">The properties.</param>
        /// <returns></returns>
        public static SortedList <DateTime, Decimal> Bootstrap(IEnumerable <IPriceableOptionAssetController> priceableAssets,
                                                               NamedValueSet curveProperties, IRateCurve discountCurve, IRateCurve forecastCurve, DateTime baseDate, Boolean extrapolationPermitted,
                                                               InterpolationMethod interpolationMethod, Double tolerance)
        {
            const double min = 0.000000001;
            const double max = 2;

            if (interpolationMethod == null)
            {
                interpolationMethod = InterpolationMethodHelper.Parse("LinearInterpolation");
            }
            var  points = new SortedList <DateTime, Decimal>();
            var  solver = new Brent();
            bool first  = true;

            // Add the rest
            foreach (var priceableOptionAssetController in priceableAssets)
            {
                var      priceableAsset    = (IPriceableRateOptionAssetController)priceableOptionAssetController;
                DateTime assetMaturityDate = priceableAsset.GetExpiryDate();
                if (points.Keys.Contains(assetMaturityDate))
                {
                    continue;
                }
                if (priceableAsset is PriceableRateFuturesOptionAsset || priceableAsset is PriceableSimpleRateOptionAsset)
                {
                    points[assetMaturityDate] = priceableAsset.VolatilityAtRiskMaturity;
                    first = false;
                }
                if (priceableAsset is PriceableCapRateAsset asset)
                {
                    //Some new code which creates flat volatilities out to the first expisry when no ETO's are supplied.
                    if (first)
                    {
                        var maturityDate = priceableAsset.GetRiskMaturityDate();
                        int weeks        = DateHelper.GetWeeks(baseDate, maturityDate);
                        for (var i = 1; i <= weeks; i++)
                        {
                            var shortEndDate = baseDate.AddDays(7 * i);
                            points[shortEndDate] = priceableAsset.VolatilityAtRiskMaturity;
                        }
                        points[assetMaturityDate] = priceableAsset.VolatilityAtRiskMaturity;
                    }
                    else
                    {
                        //The first guess, which should be correct for all priceable assets with analytical solutions that have been implemented.
                        points[assetMaturityDate] = priceableAsset.VolatilityAtRiskMaturity;
                        //Set the ATM strike
                        asset.DiscountCurve = discountCurve;
                        asset.ForecastCurve = forecastCurve;
                        asset.Strike        = asset.CalculateImpliedParRate(baseDate);
                        var objectiveFunction = new CapFloorAssetQuote(asset, discountCurve, forecastCurve, baseDate, interpolationMethod,
                                                                       extrapolationPermitted, points, tolerance);
                        // Check whether the guess was close enough
                        var initialValue = objectiveFunction.InitialValue();
                        if (initialValue)
                        {
                            continue;
                        }
                        var    tempMax = (double)points[assetMaturityDate];
                        double guess   = Math.Max(min, tempMax);
                        var    result  = solver.Solve(objectiveFunction, tolerance, guess, min, max);
                        points[assetMaturityDate] = (decimal)result;
                    }
                }
            }
            return(points);
        }