Beispiel #1
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 #2
0
        ///<summary>
        ///</summary>
        ///<param name="maturityDate">redemption date</param>
        ///<param name="lastCouponDate">last coupon date</param>
        ///<param name="couponRate">coupon rate</param>
        ///<param name="couponFrequency">coupons per year,1 for annual, 2 for semi, 4 for quarterly</param>
        ///<param name="faceValue">The face value of the bond.</param>
        ///<param name="dirtyPrice">dirty price</param>
        ///<returns></returns>
        public static double CalculateBondYTM(DateTime maturityDate, DateTime lastCouponDate, double couponRate, int couponFrequency, double faceValue, double dirtyPrice)
        {
            var c = new CalculateBondYTMObjectiveFunctionClass(maturityDate, lastCouponDate, couponRate, couponFrequency, faceValue, dirtyPrice);
            // Instantiate and initialise the equation solver.
            var solver = new Brent();

            return(solver.Solve(c, .0000001, couponRate, 0.01));
        }
Beispiel #3
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 #4
0
        /// <summary>
        /// Bootstraps the specified priceable assets.
        /// </summary>
        /// <param name="priceableAssets">The priceable assets.</param>
        /// <param name="referenceCurve">The reference curve.</param>
        /// <param name="baseDate">The base date.</param>
        /// <param name="termCurve">The term Curve with pre-existing points. This will not work if there are no points.</param>
        /// <param name="tolerance">Solver tolerance to use.</param>
        /// <returns></returns>
        public static TermPoint[] Bootstrap(IList <IPriceableRateSpreadAssetController> priceableAssets,
                                            IRateCurve referenceCurve, DateTime baseDate, TermCurve termCurve,
                                            Double tolerance)
        {
            const double min = 0.000000001;
            const double max = 1;
            Dictionary <DateTime, Pair <string, decimal> > items
                = new Dictionary <DateTime, Pair <string, decimal> > ();
            //  Add the elements (date : discount factor) to the list
            IDictionary <DateTime, double> dfs = new Dictionary <DateTime, double>();

            foreach (var point in termCurve.point)
            {
                dfs.Add((DateTime)point.term.Items[0], (double)point.mid);
                items.Add((DateTime)point.term.Items[0], new Pair <string, decimal>(point.id, point.mid));
            }
            var solver = new Brent();

            foreach (var priceableAsset in priceableAssets)
            {
                var assetMaturityDate = priceableAsset.GetRiskMaturityDate();
                if (dfs.ContainsKey(assetMaturityDate))
                {
                    continue;
                }
                //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.
                dfs.Add(assetMaturityDate, (double)priceableAsset.CalculateDiscountFactorAtMaturity(referenceCurve));
                var objectiveFunction = new RateSpreadAssetQuote(priceableAsset, referenceCurve, baseDate,
                                                                 termCurve.extrapolationPermitted, dfs, tolerance);
                // check accuracy so that solver is only called if outside the tolerance.
                if (!objectiveFunction.InitialValue())
                {
                    dfs[assetMaturityDate] = solver.Solve(objectiveFunction, tolerance, dfs[assetMaturityDate], min, max);
                }
                items.Add(assetMaturityDate, new Pair <string, decimal>(priceableAsset.Id, (decimal)dfs[assetMaturityDate]));
            }
            return(TermPointsFactory.Create(items));
        }
Beispiel #5
0
        /// <summary>
        /// <remarks>
        /// Always:
        /// pay floating
        /// receive fixed
        /// </remarks>
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="cache"></param>
        /// <param name="nameSpace"></param>
        /// <param name="valueDate"></param>
        /// <param name="effectiveDate"></param>
        /// <param name="terminationDate"></param>
        /// <param name="interpolationMethod"></param>
        /// <param name="margineAboveFloatingRate"></param>
        /// <param name="resetRate"></param>
        /// <param name="directionDateGenerationPayLeg"></param>
        /// <param name="cashFlowFrequencyPayLeg"></param>
        /// <param name="accrualMethodPayLeg"></param>
        /// <param name="holidaysPayLeg"></param>
        /// <param name="discountFactorCurvePayLeg"></param>
        /// <param name="directionDateGenerationRecLeg"></param>
        /// <param name="cashFlowFrequencyRecLeg"></param>
        /// <param name="accrualMethodRecLeg"></param>
        /// <param name="holidaysRecLeg"></param>
        /// <param name="discountFactorCurveRecLeg"></param>
        /// <returns></returns>
        public double GetSwapParRateWithoutCurves
        (
            ILogger logger,
            ICoreCache cache,
            String nameSpace,
            DateTime valueDate,
            DateTime effectiveDate,
            DateTime terminationDate,
            string interpolationMethod,      //1 is linear on forward rates => make sure that the right curve is provided ...
            double margineAboveFloatingRate, // use 0 initially
            double resetRate,
            int directionDateGenerationPayLeg,
            string cashFlowFrequencyPayLeg,
            string accrualMethodPayLeg,
            string holidaysPayLeg,
            IRateCurve discountFactorCurvePayLeg,
            int directionDateGenerationRecLeg,
            string cashFlowFrequencyRecLeg,
            string accrualMethodRecLeg,
            string holidaysRecLeg,
            IRateCurve discountFactorCurveRecLeg
        )
        {
            const decimal dummyNotional = 1000000.0m;
            //  received fixed leg
            //
            var recFixedCashflows = InterestRateSwapPricer.GenerateCashflows(logger, cache, nameSpace, null, valueDate, effectiveDate, terminationDate,
                                                                             interpolationMethod, margineAboveFloatingRate, resetRate,
                                                                             dummyNotional,
                                                                             directionDateGenerationRecLeg,
                                                                             cashFlowFrequencyRecLeg,
                                                                             accrualMethodRecLeg,
                                                                             holidaysRecLeg,
                                                                             discountFactorCurveRecLeg,
                                                                             true);

            recFixedCashflows.PayingFixedRate = false;
            //  pay floating leg
            //
            var payFloatingCashflows = InterestRateSwapPricer.GenerateCashflows(logger, cache, nameSpace, null, valueDate, effectiveDate, terminationDate,
                                                                                interpolationMethod, margineAboveFloatingRate, resetRate,
                                                                                dummyNotional,
                                                                                directionDateGenerationPayLeg,
                                                                                cashFlowFrequencyPayLeg,
                                                                                accrualMethodPayLeg,
                                                                                holidaysPayLeg,
                                                                                discountFactorCurvePayLeg,
                                                                                false);

            payFloatingCashflows.PayingFixedRate = false;
            var objectiveFunction = new InterestRateSwapPricer
            {
                ReceiveLeg = recFixedCashflows,
                PayLeg     = payFloatingCashflows
            };
            var solver = new Brent
            {
                LowerBound = -100.0,
                UpperBound = 100.0
            };

            return(solver.Solve(objectiveFunction, Accuracy, Guess, Step));
        }
Beispiel #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="cache"></param>
        /// <param name="nameSpace"></param>
        /// <param name="valueDate"></param>
        /// <param name="effectiveDate"></param>
        /// <param name="terminationDate"></param>
        /// <param name="interpolationMethod"></param>
        /// <param name="margineAboveFloatingRate"></param>
        /// <param name="resetRate"></param>
        /// <param name="notional"></param>
        /// <param name="directionDateGenerationPayLeg"></param>
        /// <param name="cashFlowFrequencyPayLeg"></param>
        /// <param name="accrualMethodPayLeg"></param>
        /// <param name="holidaysPayLeg"></param>
        /// <param name="rateCurvePayLeg"></param>
        /// <param name="directionDateGenerationRecLeg"></param>
        /// <param name="cashFlowFrequencyRecLeg"></param>
        /// <param name="accrualMethodRecLeg"></param>
        /// <param name="holidaysRecLeg"></param>
        /// <param name="rateCurveRecLeg"></param>
        /// <param name="layout">
        /// if 0 - cashflows displayed one under another,
        /// if 1 - cashflows displayed side by side.
        /// </param>
        /// <returns>
        ///  Pay cashflows:
        ///
        ///
        ///
        ///  Rec cashflows:
        ///
        ///
        /// </returns>
        public object[,] GetSwapCashflowsWithoutCurves
        (
            ILogger logger,
            ICoreCache cache,
            String nameSpace,
            DateTime valueDate,
            DateTime effectiveDate,
            DateTime terminationDate,
            string interpolationMethod,      //1 is linear on forward rates => make sure that the right curve is provided ...
            double margineAboveFloatingRate, // use 0 initially
            double resetRate,
            decimal notional,
            int directionDateGenerationPayLeg,
            string cashFlowFrequencyPayLeg,
            string accrualMethodPayLeg,
            string holidaysPayLeg,
            IRateCurve rateCurvePayLeg,
            int directionDateGenerationRecLeg,
            string cashFlowFrequencyRecLeg,
            string accrualMethodRecLeg,
            string holidaysRecLeg,
            IRateCurve rateCurveRecLeg,
            int layout
        )
        {
            //  received fixed leg
            //
            var recFixedCashflows = InterestRateSwapPricer.GenerateCashflows(logger, cache, nameSpace, null, valueDate, effectiveDate, terminationDate,
                                                                             interpolationMethod, margineAboveFloatingRate, resetRate,
                                                                             notional,
                                                                             directionDateGenerationRecLeg,
                                                                             cashFlowFrequencyRecLeg,
                                                                             accrualMethodRecLeg,
                                                                             holidaysRecLeg,
                                                                             rateCurvePayLeg,
                                                                             true);
            //  pay floating leg
            //
            var payFloatingCashflows = InterestRateSwapPricer.GenerateCashflows(logger, cache, nameSpace, null, valueDate, effectiveDate, terminationDate,
                                                                                interpolationMethod, margineAboveFloatingRate, resetRate,
                                                                                notional,
                                                                                directionDateGenerationPayLeg,
                                                                                cashFlowFrequencyPayLeg,
                                                                                accrualMethodPayLeg,
                                                                                holidaysPayLeg,
                                                                                rateCurveRecLeg,
                                                                                false);
            var objectiveFunction = new InterestRateSwapPricer
            {
                ReceiveLeg = recFixedCashflows,
                PayLeg     = payFloatingCashflows
            };
            var solver = new Brent
            {
                LowerBound = -100.0,
                UpperBound = 100.0
            };

            solver.Solve(objectiveFunction, Accuracy, Guess, Step);
            //            bool bothLegsHaveTheSameStructure =
            //                directionDateGenerationPayLeg == directionDateGenerationRecLeg &&
            //                cashFlowFrequencyPayLeg == cashFlowFrequencyRecLeg &&
            //                holidaysPayLeg == holidaysRecLeg;

            // if 0 - cashflows displayed one under another,
            // if 1 - cashflows displayed side by side.

            var result = 1 == layout?Utilities.GetCashflowsSideBySideExcelRange(payFloatingCashflows.Coupons, recFixedCashflows.Coupons) : Utilities.GetCashflowsOneUnderAnotherExcelRange(payFloatingCashflows.Coupons, recFixedCashflows.Coupons);

            return(result);
        }
        /// <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);
        }
        /// <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));
        }