@Override public double[] getNodeSensitivitiesForValue(Interpolator1DDataBundle data, Double value) { ArgChecker.notNull(value, "Value to be interpolated must not be null"); ArgChecker.notNull(data, "Data bundle must not be null"); int n = data.size(); double[] resultSensitivity = new double[n]; InterpolationBoundedValues boundedValues = data.getBoundedValues(value); double x1 = boundedValues.getLowerBoundKey(); double y1 = boundedValues.getLowerBoundValue(); int index = boundedValues.getLowerBoundIndex(); if (index == n - 1) { resultSensitivity[n - 1] = 1.0; return resultSensitivity; } double x2 = boundedValues.getHigherBoundKey(); double y2 = boundedValues.getHigherBoundValue(); if ((y1 < EPS) || (y2 < EPS)) { throw new UnsupportedOperationException( "node sensitivity not implemented when one node is 0 value"); } double w = (x2 - value) / (x2 - x1); double xy21 = x1 * y1 * y1; double xy22 = x2 * y2 * y2; double xy2 = w * xy21 + (1 - w) * xy22; double resultValue = Math.sqrt(xy2 / value); double resultValueBar = 1.0; double xy2Bar = 0.5 / resultValue / value * resultValueBar; double xy21Bar = w * xy2Bar; double xy22Bar = (1 - w) * xy2Bar; double y2Bar = 2 * x2 * y2 * xy22Bar; double y1Bar = 2 * x1 * y1 * xy21Bar; resultSensitivity[index] = y1Bar; resultSensitivity[index + 1] = y2Bar; return resultSensitivity; }
/** * Make a set of standard CDS represented as a MultiCdsAnalytic instance. The maturities of the * CDS are measured from the next IMM date (after the trade date), and the tenors are the given * matIndices multiplied by the coupon interval (3 months). * * @param tradeDate the trade date * @param accStartDate the accrual start date * @param matIndices the CDS tenors are these multiplied by the coupon interval (3 months) * @return a set of CDS represented as a MultiCdsAnalytic */ public MultiCdsAnalytic makeMultiImmCds( LocalDate tradeDate, LocalDate accStartDate, int[] matIndices) { if (!_couponInterval.equals(DEFAULT_COUPON_INT)) { throw new IllegalArgumentException( "coupon interval must be 3M for this method. However it is set to " + _couponInterval.toString()); } ArgChecker.notNull(tradeDate, "tradeDate"); ArgChecker.notEmpty(matIndices, "matIndicies"); LocalDate nextIMM = ImmDateLogic.getNextIMMDate(tradeDate); LocalDate stepinDate = tradeDate.plusDays(_stepIn); LocalDate valueDate = addWorkDays(tradeDate, _cashSettle, _calendar); return new MultiCdsAnalytic( tradeDate, stepinDate, valueDate, accStartDate, nextIMM, matIndices, _payAccOnDefault, _couponIntervalTenor, _stubType, _protectStart, _recoveryRate, _businessdayAdjustmentConvention, DEFAULT_CALENDAR, _accrualDayCount, _curveDayCount); }
/** * Creates a periodic frequency. * * @param period the period to represent * @param name the name */ private Frequency(Period period, String name) { ArgChecker.notNull(period, "period"); ArgChecker.isFalse(period.isZero(), "Period must not be zero"); ArgChecker.isFalse(period.isNegative(), "Period must not be negative"); this.period = period; this.name = name; }
// ------------------------------------------------------------------------- @Override public double getVolatility(DoubleArray t) { ArgChecker.notNull(t, "data"); ArgChecker.isTrue( t.size() == 4, "data should have four components (expiry time, tenor, strike and forward"); return getVolatility(t.get(0), t.get(1), t.get(2), t.get(3)); }
@Override public MulticurveSensitivity visitSwapFuturesPriceDeliverableSecurity( final SwapFuturesPriceDeliverableSecurity futures, final ParameterProviderInterface multicurve) { ArgChecker.notNull(futures, "futures"); ArgChecker.notNull(multicurve, "multi-curve provider"); double dfInv = 1.0 / multicurve .getMulticurveProvider() .getDiscountFactor(futures.getCurrency(), futures.getDeliveryTime()); MulticurveSensitivity pvcs = futures .getUnderlyingSwap() .accept(PVCSDC, multicurve.getMulticurveProvider()) .getSensitivity(futures.getCurrency()) .multipliedBy(dfInv); final PresentValueDiscountingCalculator pvCalc = PresentValueDiscountingCalculator.getInstance(); double pv = futures .getUnderlyingSwap() .accept(pvCalc, multicurve.getMulticurveProvider()) .getAmount(futures.getCurrency()) .getAmount(); final Map<String, List<DoublesPair>> resultMap = new HashMap<>(); final List<DoublesPair> listDf = new ArrayList<>(); listDf.add(DoublesPair.of(futures.getDeliveryTime(), futures.getDeliveryTime() * pv * dfInv)); resultMap.put(multicurve.getMulticurveProvider().getName(futures.getCurrency()), listDf); MulticurveSensitivity result = MulticurveSensitivity.ofYieldDiscounting(resultMap); return result.plus(pvcs); }
/** * Solves the system Ax = y for the unknown vector x, where A is a tridiagonal matrix and y is a * vector. This takes order n operations where n is the size of the system (number of linear * equations), as opposed to order n^3 for the general problem. * * @param aM tridiagonal matrix * @param b known vector (must be same length as rows/columns of matrix) * @return vector (as an array of doubles) with same length as y */ public static double[] solvTriDag(TridiagonalMatrix aM, double[] b) { ArgChecker.notNull(aM, "null matrix"); ArgChecker.notNull(b, "null vector"); double[] d = aM.getDiagonal(); // b is modified, so get copy of diagonal int n = d.length; ArgChecker.isTrue(n == b.length, "vector y wrong length for matrix"); double[] y = Arrays.copyOf(b, n); double[] l = aM.getLowerSubDiagonalData(); double[] u = aM.getUpperSubDiagonalData(); double[] x = new double[n]; for (int i = 1; i < n; i++) { double m = l[i - 1] / d[i - 1]; d[i] = d[i] - m * u[i - 1]; y[i] = y[i] - m * y[i - 1]; } x[n - 1] = y[n - 1] / d[n - 1]; for (int i = n - 2; i >= 0; i--) { x[i] = (y[i] - u[i] * x[i + 1]) / d[i]; } return x; }
@Override public GreekResultCollection visitEquityOption( final EquityOption option, final StaticReplicationDataBundle data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); final double k = option.getStrike(); final double t = option.getTimeToExpiry(); final boolean isCall = option.isCall(); final double volatility = data.getVolatilitySurface().getVolatility(t, k); final double r = data.getDiscountCurve().getInterestRate(t); final double spot = data.getForwardCurve().getSpot(); final double fwd = data.getForwardCurve().getForward(t); final double b; if (t > 0) { b = Math.log(fwd / spot) / t; } else { b = r; // TODO } final double[] greeks = MODEL.getPriceAdjoint(spot, k, r, b, t, volatility, isCall); final GreekResultCollection result = new GreekResultCollection(); result.put(Greek.DELTA, greeks[1]); result.put(Greek.DUAL_DELTA, greeks[2]); result.put(Greek.RHO, greeks[3]); result.put(Greek.CARRY_RHO, greeks[4]); result.put(Greek.THETA, greeks[5]); result.put(Greek.VEGA, greeks[6]); final double[] pdg = MODEL.getPriceDeltaGamma(spot, k, r, b, t, volatility, isCall); result.put(Greek.GAMMA, pdg[2]); return result; }
/** * @param baseInterpolator The interpolator used for interpolating in the transformed space * @param transform a two way mapping between a limited range and the real line */ public TransformedInterpolator1D( final Interpolator1D baseInterpolator, final ParameterLimitsTransform transform) { ArgChecker.notNull(baseInterpolator, "null baseInterpolator"); ArgChecker.notNull(transform, "null transform"); _base = baseInterpolator; _transform = transform; }
/** * Merges the specified date/value point into this builder. * * <p>The operator is invoked if the date already exists. * * @param date the date to be added * @param value the value associated with the date * @param operator the operator to use for merging * @return this builder */ public LocalDateDoubleTimeSeriesBuilder merge( LocalDate date, double value, DoubleBinaryOperator operator) { ArgChecker.notNull(date, "date"); ArgChecker.notNull(operator, "operator"); entries.merge(date, value, (a, b) -> operator.applyAsDouble(a, b)); return this; }
private SurfaceMetadata updateSurfaceMetadata(Set<DoublesPair> pairs) { SurfaceMetadata surfaceMetadata = surface.getMetadata(); List<SurfaceParameterMetadata> sortedMetaList = new ArrayList<SurfaceParameterMetadata>(); if (surfaceMetadata.getParameterMetadata().isPresent()) { List<SurfaceParameterMetadata> metaList = new ArrayList<SurfaceParameterMetadata>(surfaceMetadata.getParameterMetadata().get()); for (DoublesPair pair : pairs) { metadataLoop: for (SurfaceParameterMetadata parameterMetadata : metaList) { ArgChecker.isTrue( parameterMetadata instanceof GenericVolatilitySurfaceYearFractionMetadata, "Surface parameter metadata must be instance of GenericVolatilitySurfaceYearFractionMetadata"); GenericVolatilitySurfaceYearFractionMetadata casted = (GenericVolatilitySurfaceYearFractionMetadata) parameterMetadata; if (pair.getFirst() == casted.getYearFraction() && pair.getSecond() == casted.getStrike().getValue()) { sortedMetaList.add(casted); metaList.remove(parameterMetadata); break metadataLoop; } } } ArgChecker.isTrue( metaList.size() == 0, "Mismatch between surface parameter metadata list and doubles pair list"); } else { for (DoublesPair pair : pairs) { GenericVolatilitySurfaceYearFractionMetadata parameterMetadata = GenericVolatilitySurfaceYearFractionMetadata.of( pair.getFirst(), SimpleStrike.of(pair.getSecond())); sortedMetaList.add(parameterMetadata); } } return surfaceMetadata.withParameterMetadata(sortedMetaList); }
public BasisFunctionAggregation(List<Function<T, Double>> functions, double[] weights) { ArgChecker.notEmpty(functions, "no functions"); ArgChecker.notNull(weights, "no weights"); ArgChecker.isTrue(functions.size() == weights.length); _f = functions; _w = weights.clone(); }
/** * Make a set of CDSs with a common trade date and maturities dates the given periods after the * next IMM date (after the trade-date). * * @param tradeDate the trade date * @param accStartDate this is when the CDS nominally starts in terms of premium payments. For a * standard CDS this is the previous IMM date, and for a `legacy' CDS it is T+1 * @param tenors the tenors (lengths) of the CDSs * @return an array of CDS analytic descriptions */ public CdsAnalytic[] makeImmCds(LocalDate tradeDate, LocalDate accStartDate, Period[] tenors) { ArgChecker.notNull(tradeDate, "tradeDate"); ArgChecker.notNull(accStartDate, "effectiveDate"); ArgChecker.noNulls(tenors, "tenors"); LocalDate nextIMM = ImmDateLogic.getNextIMMDate(tradeDate); LocalDate[] maturities = ImmDateLogic.getIMMDateSet(nextIMM, tenors); return makeCds(tradeDate, accStartDate, maturities); }
/** * Constructor from a multicurveSensitivity and a sensitivityPriceCurve. The maps are used * directly. * * @param multicurveSensitivity The multicurveSensitivity. * @param sensitivityCommodityForwardCurve The map. * @return The sensitivity. */ public static CommoditySensitivity of( final MulticurveSensitivity multicurveSensitivity, final Map<String, List<DoublesPair>> sensitivityCommodityForwardCurve) { ArgChecker.notNull(multicurveSensitivity, "multicurve sensitivity"); ArgChecker.notNull(sensitivityCommodityForwardCurve, "Sensitivity commodity forward curve"); return new CommoditySensitivity(multicurveSensitivity, sensitivityCommodityForwardCurve); }
/** * Set up a strip of on-the-run indexes represented as a single name CDSs (i.e. by CdsAnalytic). * The index roll dates (when new indices are issued) are 20 Mar & Sep, and the index is defined * to have a maturity that is its nominal tenor plus 3M on issuance, so a 5Y index on the * 6-Feb-2014 will have a maturity of 20-Dec-2018 (5Y3M on the issue date of 20-Sep-2013). The * accrual start date will be the previous IMM date (before the trade date), business-day * adjusted. <b>Note</b> it payment interval is changed from the default of 3M, this will produce * a (possibly incorrect) non-standard first coupon. * * @param tradeDate the trade date * @param tenors the nominal lengths of the indexes * @return an array of CDS analytic descriptions */ public CdsAnalytic[] makeCdx(LocalDate tradeDate, Period[] tenors) { ArgChecker.notNull(tradeDate, "tradeDate"); ArgChecker.noNulls(tenors, "tenors"); LocalDate effectiveDate = _businessdayAdjustmentConvention.adjust(ImmDateLogic.getPrevIMMDate(tradeDate), _calendar); LocalDate mid = ImmDateLogic.getNextIndexRollDate(tradeDate).minusMonths(3); LocalDate[] maturities = ImmDateLogic.getIMMDateSet(mid, tenors); return makeCds(tradeDate, effectiveDate, maturities); }
/** * Puts the specified date/value point into this builder. * * @param date the date to be added * @param value the value associated with the date * @return this builder */ public LocalDateDoubleTimeSeriesBuilder put(LocalDate date, double value) { ArgChecker.notNull(date, "date"); ArgChecker.isFalse(Double.isNaN(value), "NaN is not allowed as a value"); entries.put(date, value); if (!containsWeekends && date.get(ChronoField.DAY_OF_WEEK) > 5) { containsWeekends = true; } return this; }
// ------------------------------------------------------------------------- @ImmutableValidator private void validate() { if (rebate != null) { ArgChecker.isTrue(rebate.getAmount() > 0d, "rebate must be positive"); ArgChecker.isTrue( underlyingOption.getUnderlying().getCurrencyPair().contains(rebate.getCurrency()), "The rebate currency must be one of underlying currency pair"); } }
@Override public Interpolator1DDataBundle getDataBundleFromSortedArrays(double[] x, double[] y) { ArgChecker.notNull(y, "y"); int nY = y.length; for (int i = 0; i < nY; ++i) { ArgChecker.isTrue(y[i] >= 0.0, "All values in y must be positive"); } return new ArrayInterpolator1DDataBundle(x, y, true); }
/** * Set up an on-the-run index represented as a single name CDS (i.e. by CdsAnalytic). The index * roll dates (when new indices are issued) are 20 Mar & Sep, and the index is defined to have a * maturity that is its nominal tenor plus 3M on issuance, so a 5Y index on the 6-Feb-2014 will * have a maturity of 20-Dec-2018 (5Y3M on the issue date of 20-Sep-2013). The accrual start date * will be the previous IMM date (before the trade date), business-day adjusted. <b>Note</b> it * payment interval is changed from the default of 3M, this will produce a (possibly incorrect) * non-standard first coupon. * * @param tradeDate the trade date * @param tenor the nominal length of the index * @return a CDS analytic description */ public CdsAnalytic makeCdx(LocalDate tradeDate, Period tenor) { ArgChecker.notNull(tradeDate, "tradeDate"); ArgChecker.notNull(tenor, "tenor"); LocalDate effectiveDate = _businessdayAdjustmentConvention.adjust(ImmDateLogic.getPrevIMMDate(tradeDate), _calendar); LocalDate roll = ImmDateLogic.getNextIndexRollDate(tradeDate); LocalDate maturity = roll.plus(tenor).minusMonths(3); return makeCds(tradeDate, effectiveDate, maturity); }
/** * Returns the convexity adjustment, i.e. the difference between the adjusted price and the * present value of the underlying swap. * * @param futures The swap futures. * @param hwMulticurves The multi-curve and parameters provider. * @return The adjustment. */ public double convexityAdjustment( final SwapFuturesPriceDeliverableSecurity futures, final HullWhiteOneFactorProviderInterface hwMulticurves) { ArgChecker.notNull(futures, "swap futures"); ArgChecker.notNull(hwMulticurves, "parameter provider"); MultiCurrencyAmount pv = futures.getUnderlyingSwap().accept(PVDC, hwMulticurves.getMulticurveProvider()); double price = price(futures, hwMulticurves); return price - (1.0d + pv.getAmount(futures.getCurrency()).getAmount()); }
/** * Make a set of standard CDS represented as a MultiCdsAnalytic instance. The maturities of the * CDS are measured from the next IMM date (after the trade date), and the first and last tenors * are the firstIndex and lastIndex multiplied by the coupon interval (3 months), which the * remaining tenors being everything in between. * * @param tradeDate the trade date * @param firstIndex the First index * @param lastIndex the last index * @return a set of CDS represented as a MultiCdsAnalytic */ public MultiCdsAnalytic makeMultiImmCds(LocalDate tradeDate, int firstIndex, int lastIndex) { ArgChecker.isTrue(lastIndex > firstIndex, "Require lastIndex>firstIndex"); ArgChecker.isTrue(firstIndex >= 0, "Require positive indices"); int n = lastIndex - firstIndex + 1; int[] matIndices = new int[n]; for (int i = 0; i < n; i++) { matIndices[i] = i + firstIndex; } return makeMultiImmCds(tradeDate, matIndices); }
/** * Obtains a template based on the specified periods and convention. * * <p>The periods from the spot date to the start date and to the end date are specified. * * <p>For example, a '2 x 5' FRA has a period to the start date of 2 months and a period to the * end date of 5 months. * * @param periodToStart the period between the spot date and the start date * @param periodToEnd the period between the spot date and the end date * @param convention the market convention * @return the template */ public static FraTemplate of(Period periodToStart, Period periodToEnd, FraConvention convention) { ArgChecker.notNull(periodToStart, "periodToStart"); ArgChecker.notNull(periodToEnd, "periodToEnd"); ArgChecker.notNull(convention, "convention"); return FraTemplate.builder() .periodToStart(periodToStart) .periodToEnd(periodToEnd) .convention(convention) .build(); }
/** * Constructor from a yield discounting map of sensitivity. The maps are used directly. * * @param sensitivityYieldDiscounting The map. * @param sensitivityForward The map. * @param sensitivityCommodityForwardCurve The map. * @return The sensitivity. */ public static CommoditySensitivity of( final Map<String, List<DoublesPair>> sensitivityYieldDiscounting, final Map<String, List<ForwardSensitivity>> sensitivityForward, final Map<String, List<DoublesPair>> sensitivityCommodityForwardCurve) { ArgChecker.notNull(sensitivityYieldDiscounting, "Sensitivity yield curve"); ArgChecker.notNull(sensitivityForward, "Sensitivity forward"); ArgChecker.notNull(sensitivityCommodityForwardCurve, "Sensitivity commodity forward curve"); return new CommoditySensitivity( sensitivityYieldDiscounting, sensitivityForward, sensitivityCommodityForwardCurve); }
/** * Make a CDS with a maturity date the given period on from the next IMM date after the * trade-date. The accrual start date will be the previous IMM date (before the trade date). * <b>Note</b> it payment interval is changed from the default of 3M, this will produce a * (possibly incorrect) non-standard first coupon. * * @param tradeDate the trade date * @param tenor the tenor (length) of the CDS * @param makeEffBusDay is the accrual start day business-day adjusted. * @return a CDS analytic description */ public CdsAnalytic makeImmCds(LocalDate tradeDate, Period tenor, boolean makeEffBusDay) { ArgChecker.notNull(tradeDate, "tradeDate"); ArgChecker.notNull(tenor, "tenor"); LocalDate effectiveDate = makeEffBusDay ? _businessdayAdjustmentConvention.adjust( ImmDateLogic.getPrevIMMDate(tradeDate), _calendar) : ImmDateLogic.getPrevIMMDate(tradeDate); LocalDate nextIMM = ImmDateLogic.getNextIMMDate(tradeDate); LocalDate maturity = nextIMM.plus(tenor); return makeCds(tradeDate, effectiveDate, maturity); }
/** * @param spotValues Spot values * @return realized variance */ public double getRealizedVariance(final double[] spotValues) { ArgChecker.notNull(spotValues, "spotValues"); final int nSpots = spotValues.length; ArgChecker.isTrue(nSpots > 1, "Number of spot values should be greater than 1"); double res = 0.0; for (int i = 1; i < nSpots; ++i) { res += Math.pow(Math.log(spotValues[i] / spotValues[i - 1]), 2.0); } final double factor = 252.0 * 1.e4 / (nSpots - 1.0); res *= factor; return res; }
/** * Puts all the specified dates and values into this builder. * * <p>The date collection and value array must be the same size. * * <p>The date-value pairs are added one by one. If a date is duplicated it will overwrite an * earlier entry. * * @param dates the dates to be added * @param values the values to be added * @return this builder */ public LocalDateDoubleTimeSeriesBuilder putAll(Collection<LocalDate> dates, double[] values) { ArgChecker.noNulls(dates, "dates"); ArgChecker.notNull(values, "values"); ArgChecker.isTrue( dates.size() == values.length, "Arrays are of different sizes - dates: {}, values: {}", dates.size(), values.length); Iterator<LocalDate> itDate = dates.iterator(); for (int i = 0; i < dates.size(); i++) { put(itDate.next(), values[i]); } return this; }
/** * Make a set of standard CDS represented as a MultiCdsAnalytic instance. The first CDS with have * a tenor of firstTenor, while the last CDS will have a tenor of lastTenor; the remaining CDS * will consist of all the (multiple of 3 month) tenors between the first and last tenor, e.g. if * firstTenor = 6M and lastTenor = 5Y, there will be a total of 22 CDS with tenors of 6M, 9M, * 1Y,....4Y9M, 5Y. * * @param tradeDate the trade date * @param firstTenor the first tenor * @param lastTenor the last tenor * @return a set of CDS represented as a MultiCdsAnalytic */ public MultiCdsAnalytic makeMultiImmCds( LocalDate tradeDate, Period firstTenor, Period lastTenor) { ArgChecker.notNull(firstTenor, "firstTenor"); ArgChecker.notNull(lastTenor, "lastTenor"); int immNMonths = (int) DEFAULT_COUPON_INT.toTotalMonths(); int m1 = (int) firstTenor.toTotalMonths(); int m2 = (int) lastTenor.toTotalMonths(); if (m1 % immNMonths != 0 || m2 % immNMonths != 0) { throw new IllegalArgumentException( "tenors is not a multiple of " + DEFAULT_COUPON_INT.toString()); } int firstIndex = m1 / immNMonths; int lastIndex = m2 / immNMonths; return makeMultiImmCds(tradeDate, firstIndex, lastIndex); }
/** * Simpson's integration method. * * <p>Note that the Commons implementation fails if the lower bound is larger than the upper - in * this case, the bounds are reversed and the result negated. * * @param f The function to integrate, not null * @param lower The lower bound, not null * @param upper The upper bound, not null * @return The result of the integration */ @Override public Double integrate(Function<Double, Double> f, Double lower, Double upper) { ArgChecker.notNull(f, "function"); ArgChecker.notNull(lower, "lower bound"); ArgChecker.notNull(upper, "upper bound"); try { if (lower < upper) { return integrator.integrate(MAX_EVAL, CommonsMathWrapper.wrapUnivariate(f), lower, upper); } log.info("Upper bound was less than lower bound; swapping bounds and negating result"); return -integrator.integrate(MAX_EVAL, CommonsMathWrapper.wrapUnivariate(f), upper, lower); } catch (NumberIsTooSmallException | NumberIsTooLargeException e) { throw new MathException(e); } }
/** * Add a certain number of working days (defined by the holidayCalendar) to a date. * * @param startDate the start date * @param workingDaysToAdd working days to add * @param calendar the calendar of holidays * @return a working day */ private static LocalDate addWorkDays( LocalDate startDate, int workingDaysToAdd, HolidayCalendar calendar) { ArgChecker.notNull(startDate, "startDate"); ArgChecker.notNull(calendar, "calendar"); int daysLeft = workingDaysToAdd; LocalDate temp = startDate; while (daysLeft > 0) { temp = temp.plusDays(1); if (calendar.isBusinessDay(temp)) { daysLeft--; } } return temp; }
// ------------------------------------------------------------------------- @Override public double relativeTime(ZonedDateTime dateTime) { ArgChecker.notNull(dateTime, "dateTime"); LocalDate valuationDate = valuationDateTime.toLocalDate(); LocalDate date = dateTime.toLocalDate(); return dayCount.relativeYearFraction(valuationDate, date); }
/** * Constructor from LMM parameters and curve bundle. * * @param lmmParameters The LMM model parameters. * @param curves Curve bundle. */ public LiborMarketModelDisplacedDiffusionDataBundle( final LiborMarketModelDisplacedDiffusionParameters lmmParameters, final YieldCurveBundle curves) { super(curves); ArgChecker.notNull(lmmParameters, "LMM parameters"); _parameters = lmmParameters; }