@Override
 public Coupon toDerivative(
     final ZonedDateTime date,
     final DoubleTimeSeries<ZonedDateTime> indexFixingTS,
     final String... yieldCurveNames) {
   Validate.notNull(date, "date");
   Validate.notNull(indexFixingTS, "index fixing time series");
   Validate.notNull(yieldCurveNames, "yield curve names");
   Validate.isTrue(yieldCurveNames.length > 1, "at least two curves required");
   Validate.isTrue(!date.isAfter(getPaymentDate()), "date is after payment date");
   final DayCount actAct = DayCountFactory.INSTANCE.getDayCount("Actual/Actual ISDA");
   final String fundingCurveName = yieldCurveNames[0];
   final double paymentTime = actAct.getDayCountFraction(date, getPaymentDate());
   if (date.isAfter(getFixingDate())
       || date.equals(
           getFixingDate())) { // The CMS coupon has already fixed, it is now a fixed coupon.
     final double fixedRate = indexFixingTS.getValue(getFixingDate());
     return new CouponFixed(
         getCurrency(),
         paymentTime,
         fundingCurveName,
         getPaymentYearFraction(),
         getNotional(),
         payOff(fixedRate));
   }
   // CMS is not fixed yet, all the details are required.
   final CouponCMS cmsCoupon =
       (CouponCMS) super.toDerivative(date, indexFixingTS, yieldCurveNames);
   return CapFloorCMS.from(cmsCoupon, _strike, _isCap);
 }
Exemple #2
0
 public Point(double lat, double lon) {
   Validate.isTrue(lat >= -90.0 && lat <= 90.0, "Latitude must be in [-90, 90] but was ", lat);
   Validate.isTrue(
       lon >= -180.0 && lon <= 180.0, "Longitude must be in [-180, 180] but was ", lon);
   this.lat = lat;
   this.lon = lon;
 }
    @SuppressWarnings("synthetic-access")
    @Override
    public Double visitStrike(final BlackVolatilitySurfaceStrike surface, final DoublesPair data) {

      Validate.isTrue(data.first >= 0, "Negative lower limit");
      Validate.isTrue(data.second > data.first, "upper limit not greater than lower");

      if (_t < 1e-4) {
        if (data.first < _f && data.second > _f) {
          final double atmVol = surface.getVolatility(_t, _f);
          return atmVol * atmVol;
        }
        return 0.0;
      }

      final Function1D<Double, Double> integrand = getStrikeIntegrand(surface);
      // if external left tail residual is provided, only integrate from cut-off, otherwise we will
      // double count
      final double lowerLimit = Math.max(_lowStrikeCutoff, data.first);
      final double upperLimit = data.second;

      // Do the call/k^2 integral - split up into the the put integral and the call integral because
      // the function is not smooth at strike = forward
      double res = _integrator.integrate(integrand, _f, upperLimit);
      res += _integrator.integrate(integrand, lowerLimit, _f);

      if (_addResidual) {
        res += _residual;
      }
      return 2 * res / _t;
    }
Exemple #4
0
 public Potion(PotionType type, int level) {
   this(type);
   Validate.notNull(type, "Type cannot be null");
   Validate.isTrue(type != PotionType.WATER, "Water bottles don't have a level!");
   Validate.isTrue((level > 0) && (level < 3), "Level must be 1 or 2");
   this.level = level;
 }
  /**
   * This calculates the sensitivity of the present value (PV) to the lognormal Black implied
   * volatities at the knot points of the surface.
   *
   * <p>The return format is a DoubleMatrix2D with rows equal to the total number of maturities and
   * columns equal to the number of strikes.
   *
   * <p>Note - the change of the surface due to the movement of a single node is
   * interpolator-dependent, so an instrument may have non-local sensitivity
   *
   * @param swap the VarianceSwap
   * @param market the VarianceSwapDataBundle
   * @param shift Size of shift made in centered-finite difference approximation. e.g. 1% would be
   *     0.01, and 1bp 0.0001
   * @return A NodalDoublesSurface with same axes as market.getVolatilitySurface(). Contains
   *     currency amount per unit amount change in the black volatility of each node
   */
  public NodalDoublesSurface calcBlackVegaForEntireSurface(
      final VarianceSwap swap, final VarianceSwapDataBundle market, final double shift) {
    Validate.notNull(swap, "null VarianceSwap");
    Validate.notNull(market, "null VarianceSwapDataBundle");

    // Unpack market data
    final Surface<Double, Double, Double> surface = market.getVolatilitySurface().getSurface();
    Validate.isTrue(
        surface instanceof InterpolatedDoublesSurface,
        "Currently will only accept a Equity VolatilitySurfaces based on an InterpolatedDoublesSurface");

    final InterpolatedDoublesSurface blackSurf = (InterpolatedDoublesSurface) surface;
    final Double[] maturities = blackSurf.getXData();
    final Double[] strikes = blackSurf.getYData();
    final int nNodes = maturities.length;
    Validate.isTrue(nNodes == strikes.length);

    // Bump and reprice
    final Double[] vegas = new Double[nNodes];
    for (int j = 0; j < nNodes; j++) {
      vegas[j] = calcBlackVegaForSinglePoint(swap, market, maturities[j], strikes[j], shift);
    }

    return new NodalDoublesSurface(maturities, strikes, vegas);
  }
 @Override
 public CurrencyAmount presentValue(
     final InstrumentDerivative instrument, final YieldCurveBundle curves) {
   Validate.isTrue(instrument instanceof CapFloorCMS, "CMS cap/floor");
   Validate.isTrue(
       curves instanceof SABRInterestRateDataBundle, "Bundle should contain SABR data");
   return presentValue((CapFloorCMS) instrument, (SABRInterestRateDataBundle) curves);
 }
 @Override
 public CurrencyAmount presentValue(InstrumentDerivative instrument, YieldCurveBundle curves) {
   Validate.isTrue(instrument instanceof SwaptionPhysicalFixedIbor, "Physical delivery swaption");
   Validate.isTrue(
       curves instanceof G2ppPiecewiseConstantDataBundle, "Bundle should contain G2++ data");
   return presentValue(
       (SwaptionPhysicalFixedIbor) instrument, (G2ppPiecewiseConstantDataBundle) curves);
 }
 /**
  * @param x The parameters for the function, $(x, y, \rho$, with $-1 \geq \rho \geq 1$, not null
  * @return The pdf
  */
 @Override
 public double getPDF(final double[] x) {
   Validate.notNull(x);
   Validate.isTrue(x.length == 3, "Need a, b and rho values");
   Validate.isTrue(x[2] >= -1 && x[2] <= 1, "Correlation must be >= -1 and <= 1");
   final double denom = 1 - x[2] * x[2];
   return Math.exp(-(x[0] * x[0] - 2 * x[2] * x[0] * x[1] + x[1] * x[1]) / (2 * denom))
       / (TWO_PI * Math.sqrt(denom));
 }
    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
      int k = context.getConfiguration().getInt(PROP_K, -1);
      int p = context.getConfiguration().getInt(PROP_P, -1);

      Validate.isTrue(k > 0, "invalid k parameter");
      Validate.isTrue(p > 0, "invalid p parameter");
      accum.set(acc = new DenseVector(k + p));
    }
 /**
  * Instantiates a final PotionData object to contain information about a Potion
  *
  * @param type the type of the Potion
  * @param extended whether the potion is extended PotionType#isExtendable() must be true
  * @param upgraded whether the potion is upgraded PotionType#isUpgradable() must be true
  */
 public PotionData(PotionType type, boolean extended, boolean upgraded) {
   Validate.notNull(type, "Potion Type must not be null");
   Validate.isTrue(!upgraded || type.isUpgradeable(), "Potion Type is not upgradable");
   Validate.isTrue(!extended || type.isExtendable(), "Potion Type is not extendable");
   Validate.isTrue(!upgraded || !extended, "Potion cannot be both extended and upgraded");
   this.type = type;
   this.extended = extended;
   this.upgraded = upgraded;
 }
 @Override
 public CurrencyAmount presentValue(
     final InstrumentDerivative instrument, final YieldCurveBundle curves) {
   Validate.isTrue(instrument instanceof SwaptionPhysicalFixedIbor, "Physical delivery swaption");
   Validate.isTrue(
       curves instanceof HullWhiteOneFactorPiecewiseConstantDataBundle,
       "Bundle should contain Hull-White data");
   return presentValue(
       (SwaptionPhysicalFixedIbor) instrument,
       (HullWhiteOneFactorPiecewiseConstantDataBundle) curves);
 }
 @Override
 public Double visitMoneyness(
     final BlackVolatilitySurfaceMoneyness surface, final DoublesPair data) {
   final double l = Math.log(data.first);
   final double u = Math.log(data.second);
   Validate.isTrue(l > 0.0, "lower limit <= 0");
   Validate.isTrue(u > l, "lower limit >= upper limit");
   final BlackVolatilitySurfaceLogMoneyness logMS =
       BlackVolatilitySurfaceConverter.toLogMoneynessSurface(surface);
   return visitLogMoneyness(logMS, new DoublesPair(l, u));
 }
Exemple #13
0
  public <T> void playEffect(Location loc, Effect effect, T data) {
    if (data != null) {
      Validate.isTrue(
          data.getClass().equals(effect.getData()), "Wrong kind of data for this effect!");
    } else {
      Validate.isTrue(effect.getData() == null, "Wrong kind of data for this effect!");
    }

    int datavalue = data == null ? 0 : CraftEffect.getDataValue(effect, data);
    playEffect(loc, effect, datavalue);
  }
 @Override
 public Pair<double[], double[]> visitMoneyness(
     final BlackVolatilitySurfaceMoneyness surface, final DoublesPair data) {
   Validate.isTrue(data.first > 0.0, "cut off must be greater than zero");
   Validate.isTrue(data.second > 0.0, "spread must be positive");
   final double[] k = new double[2];
   final double[] vols = new double[2];
   k[0] = _f * data.first;
   k[1] = _f * (data.first + data.second);
   vols[0] = surface.getVolatilityForMoneyness(_t, data.first);
   vols[1] = surface.getVolatilityForMoneyness(_t, data.first + data.second);
   return new ObjectsPair<double[], double[]>(k, vols);
 }
 /**
  * @param strike The strike
  * @param expiry The expiry
  * @param power The power, not negative
  * @param cap The cap, not negative
  * @param isCall Is the option a put or call
  */
 public CappedPowerOptionDefinition(
     final double strike,
     final Expiry expiry,
     final double power,
     final double cap,
     final boolean isCall) {
   super(strike, expiry, isCall);
   Validate.isTrue(power > 0, "power must be > 0");
   Validate.isTrue(cap > 0, "cap must be > 0");
   if (!isCall && cap > strike) {
     throw new IllegalArgumentException("Cannot have cap larger than strike for a put");
   }
   _power = power;
   _cap = cap;
 }
  private void verifyHeader(String[] header) {
    Validate.isTrue(
        header.length >= 7,
        "Expecting CSV file with at least 7 columns"); // let's be somewhat tolerant to format
    // change

    final Iterable<String> columns = Iterables.limit(Arrays.asList(header), 7);
    final List<String> expectedColumns =
        Arrays.asList(
            "Date", "Last Name", "Given Name", "Person ID", "Project", "Hours", "Description");
    final boolean columnsAsExpected = Iterables.elementsEqual(columns, expectedColumns);
    Validate.isTrue(
        columnsAsExpected,
        "Expecting CSV with following columns: " + expectedColumns + ", got " + columns);
  }
  /**
   * Set the count of a certain message to a certain value
   *
   * @param node node to set the count for
   * @param playerId player for whom we are tracking the count
   * @param value value to set
   */
  private void set(MessageNode node, int playerId, int value) {
    Validate.isTrue(value >= 0, "Count has to be positive");
    Connection conn = null;
    Statement statement = null;
    try {
      conn = retrieveConnection();
      statement = conn.createStatement();

      // Set the count to the provided value
      String setQuery =
          String.format(
              "UPDATE %s SET %s = %s WHERE id = %s",
              msgTable, node.getColumnName(), value, playerId);
      statement.execute(setQuery);
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      try {
        if (conn != null) conn.close();
        if (statement != null) statement.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
 /**
  * The parameters for the CGMY process
  *
  * @param c C, > 0
  * @param g G, > 0
  * @param m M, > 1
  * @param y Y, < 2
  */
 public CGMYCharacteristicExponent(
     final double c, final double g, final double m, final double y) {
   Validate.isTrue(c > 0, "C > 0");
   Validate.isTrue(g > 0, "G > 0");
   Validate.isTrue(m > 1, "M > 1");
   Validate.isTrue(y < 2, "Y < 2");
   _c = c;
   _g = g;
   _m = m;
   _y = y;
   _minAlpha = -(_g + 1.0);
   _maxAlpha = _m - 1.0;
   _r1 = Math.pow(_m, _y) + Math.pow(_g, _y);
   _r2 = _c * GAMMA_FUNCTION.evaluate(-_y);
   _r3 = (Math.pow(_m - 1, _y) + Math.pow(_g + 1, _y) - _r1);
 }
 @Override
 public Coupon toDerivative(final ZonedDateTime date, final String... yieldCurveNames) {
   Validate.notNull(date, "date");
   Validate.isTrue(
       date.isBefore(getFixingDate()),
       "Do not have any fixing data but are asking for a derivative after the fixing date "
           + getFixingDate()
           + " "
           + date);
   Validate.notNull(yieldCurveNames, "yield curve names");
   Validate.isTrue(yieldCurveNames.length > 1, "at least two curves required");
   Validate.isTrue(!date.isAfter(getPaymentDate()), "date is after payment date");
   // CMS is not fixed yet, all the details are required.
   final CouponCMS cmsCoupon = (CouponCMS) super.toDerivative(date, yieldCurveNames);
   return CapFloorCMS.from(cmsCoupon, _strike, _isCap);
 }
  public static Map<Sensor, List<Move>> makeSameLength(Map<Sensor, List<Location>> paths) {
    int maxSize = 1;

    for (List<Location> path : paths.values()) {
      maxSize = Math.max(maxSize, path.size());
    }

    Map<Sensor, List<Move>> result = new HashMap<Sensor, List<Move>>();
    for (Sensor sensor : paths.keySet()) {
      List<Location> path = paths.get(sensor);

      Location last;
      if (!path.isEmpty()) {
        last = path.get(path.size() - 1);
        path = path.subList(1, path.size());
      } else last = sensor.getLocation();

      int currentSize = path.size();
      if (path.isEmpty()) currentSize--;

      for (int i = 0; i < maxSize - currentSize - 1; i++) {
        path.add(last);
      }

      result.put(sensor, Move.convertToMoves(path));
    }

    for (List<Location> path : paths.values()) {
      Validate.isTrue(path.size() == maxSize);
    }

    return result;
  }
Exemple #21
0
  public static Communication getReportCommunication(
      Communication now, Communication old, int totalStage) {
    Validate.isTrue(now != null && old != null, "为汇报准备的新旧metric不能为null");

    long totalReadRecords = getTotalReadRecords(now);
    long totalReadBytes = getTotalReadBytes(now);
    now.setLongCounter(TOTAL_READ_RECORDS, totalReadRecords);
    now.setLongCounter(TOTAL_READ_BYTES, totalReadBytes);
    now.setLongCounter(TOTAL_ERROR_RECORDS, getTotalErrorRecords(now));
    now.setLongCounter(TOTAL_ERROR_BYTES, getTotalErrorBytes(now));
    now.setLongCounter(WRITE_SUCCEED_RECORDS, getWriteSucceedRecords(now));
    now.setLongCounter(WRITE_SUCCEED_BYTES, getWriteSucceedBytes(now));

    long timeInterval = now.getTimestamp() - old.getTimestamp();
    long sec = timeInterval <= 1000 ? 1 : timeInterval / 1000;
    long bytesSpeed = (totalReadBytes - getTotalReadBytes(old)) / sec;
    long recordsSpeed = (totalReadRecords - getTotalReadRecords(old)) / sec;

    now.setLongCounter(BYTE_SPEED, bytesSpeed < 0 ? 0 : bytesSpeed);
    now.setLongCounter(RECORD_SPEED, recordsSpeed < 0 ? 0 : recordsSpeed);
    now.setDoubleCounter(PERCENTAGE, now.getLongCounter(STAGE) / (double) totalStage);

    if (old.getThrowable() != null) {
      now.setThrowable(old.getThrowable());
    }

    return now;
  }
  /**
   * Begins an experience gain. The amount will be affected by skill modifiers, global rate, perks,
   * and may be shared with the party
   *
   * @param skill Skill being used
   * @param xp Experience amount to process
   */
  public void beginXpGain(SkillType skill, float xp, XPGainReason xpGainReason) {
    Validate.isTrue(xp >= 0.0, "XP gained should be greater than or equal to zero.");

    if (xp <= 0.0) {
      return;
    }

    if (skill.isChildSkill()) {
      Set<SkillType> parentSkills = FamilyTree.getParents(skill);
      float splitXp = xp / parentSkills.size();

      for (SkillType parentSkill : parentSkills) {
        if (parentSkill.getPermissions(player)) {
          beginXpGain(parentSkill, splitXp, xpGainReason);
        }
      }

      return;
    }

    // Return if the experience has been shared
    if (party != null
        && ShareHandler.handleXpShare(
            xp, this, skill, ShareHandler.getSharedXpGainReason(xpGainReason))) {
      return;
    }

    beginUnsharedXpGain(skill, xp, xpGainReason);
  }
 public VarianceSwapStaticReplication(final double tolerance) {
   Validate.isTrue(
       tolerance >= EPS && tolerance < 0.1,
       "Please specifiy tolerance in the range 1e-12 to 1e-1 or use other constructor");
   _tol = tolerance;
   _integrator = DEFAULT_INTEGRAL;
 }
    /**
     * Only use if the integral limits have been calculated elsewhere, or you need the contribution
     * from a specific range
     */
    @SuppressWarnings("synthetic-access")
    @Override
    public Double visitLogMoneyness(
        final BlackVolatilitySurfaceLogMoneyness surface, final DoublesPair data) {
      final double lower = data.first;
      final double upper = data.second;
      Validate.isTrue(upper > lower, "lower limit >= upper limit");
      final double atmVol = surface.getVolatilityForLogMoneyness(_t, 0.0);
      if (_t
          < 1e-4) { // if less than a hour from expiry, only the ATM-vol will count, so must check
                    // the integral range spans ATM
        if (lower * upper < 0.0) {
          return atmVol * atmVol;
        }
        return 0.0;
      }

      final Function1D<Double, Double> integrand = getLogMoneynessIntegrand(surface);
      double putPart;
      if (_addResidual) {
        putPart = _integrator.integrate(integrand, Math.log(_lowStrikeCutoff / _f), 0.0);
        putPart += _residual;
      } else {
        putPart = _integrator.integrate(integrand, lower, 0.0);
      }
      final double callPart = _integrator.integrate(integrand, 0.0, upper);
      return 2 * (putPart + callPart) / _t;
    }
 /**
  * @param n The number of sample points to be used in the integration, not negative or zero
  * @param generator The generator of weights and abscissas
  */
 public GaussianQuadratureIntegrator1D(
     final int n, final QuadratureWeightAndAbscissaFunction generator) {
   Validate.isTrue(n > 0, "number of intervals must be > 0");
   Validate.notNull(generator, "generating function");
   _n = n;
   _generator = generator;
 }
Exemple #26
0
  public InstrumentDefinition<?> convert(final Trade trade) {
    Validate.notNull(trade, "trade");
    Validate.isTrue(
        trade.getSecurity() instanceof IRFutureOptionSecurity,
        "Can only handle trades with security type IRFutureOptionSecurity");
    final Object securityDefinition =
        _securityConverter.convert((IRFutureOptionSecurity) trade.getSecurity());
    final int quantity =
        1; // trade.getQuantity().intValue(); TODO: correct when position/trade dilemma is solved.
    // TODO trade time or premium time?
    //    final ZonedDateTime tradeDate =
    // ZonedDateTime.of(trade.getPremiumDate().atTime(trade.getPremiumTime()),
    //        TimeZone.UTC); //TODO get the real time zone
    final ZonedDateTime tradeDate =
        ZonedDateTime.of(
            trade.getTradeDate().atTime(trade.getTradeTime()),
            TimeZone.UTC); // TODO get the real time zone

    final Double tradePrice = trade.getPremium();
    Validate.notNull(
        tradePrice,
        "IRFutureOption trade must have a premium set. The interpretation of premium is the market price, without unit, i.e. not %");
    // TODO: The premium is not the right place to store the trade price...

    if (securityDefinition instanceof InterestRateFutureOptionMarginSecurityDefinition) {
      final InterestRateFutureOptionMarginSecurityDefinition underlyingOption =
          (InterestRateFutureOptionMarginSecurityDefinition) securityDefinition;
      return new InterestRateFutureOptionMarginTransactionDefinition(
          underlyingOption, quantity, tradeDate, tradePrice);
    }
    final InterestRateFutureOptionPremiumSecurityDefinition underlyingOption =
        (InterestRateFutureOptionPremiumSecurityDefinition) securityDefinition;
    return new InterestRateFutureOptionPremiumTransactionDefinition(
        underlyingOption, quantity, tradeDate, tradePrice);
  }
 /**
  * Constructor from all the details.
  *
  * @param currency The payment currency.
  * @param paymentTime Time (in years) up to the payment.
  * @param discountingCurveName Name of the funding curve.
  * @param paymentYearFraction The year fraction (or accrual factor) for the coupon payment.
  * @param notional Coupon notional.
  * @param fixingTime Time (in years) up to fixing.
  * @param index Ibor-like index on which the coupon fixes. The index currency should be the same
  *     as the index currency.
  * @param fixingPeriodStartTime The fixing period start time (in years).
  * @param fixingPeriodEndTime The fixing period end time (in years).
  * @param fixingAccrualFactor The fixing period accrual factor (or year fraction) in the fixing
  *     convention.
  * @param spread The spread paid above the Ibor rate.
  * @param factor The gearing (multiplicative) factor applied to the Ibor rate.
  * @param forwardCurveName The forward curve name used in to estimate the fixing index.
  */
 public CouponIborGearing(
     Currency currency,
     double paymentTime,
     String discountingCurveName,
     double paymentYearFraction,
     double notional,
     double fixingTime,
     IborIndex index,
     double fixingPeriodStartTime,
     double fixingPeriodEndTime,
     double fixingAccrualFactor,
     double spread,
     double factor,
     String forwardCurveName) {
   super(currency, paymentTime, discountingCurveName, paymentYearFraction, notional, fixingTime);
   Validate.notNull(index, "Index");
   Validate.notNull(forwardCurveName, "Forward curve");
   Validate.isTrue(currency.equals(index.getCurrency()));
   this._index = index;
   this._fixingPeriodStartTime = fixingPeriodStartTime;
   this._fixingPeriodEndTime = fixingPeriodEndTime;
   this._fixingAccrualFactor = fixingAccrualFactor;
   this._spread = spread;
   this._factor = factor;
   this._forwardCurveName = forwardCurveName;
   _spreadAmount = getNotional() * getPaymentYearFraction() * spread;
 }
  /**
   * @param target Queue que se "wrappea". Es quien en realidad tiene implementada las operaciones
   * @param timeout Como las {@link BlockingQueue} retornan null si no hay elementos, se le debe
   *     indicar un timeout de espera para volver a ver si hay elementos (y de esta forma
   *     "blockear"). Está dicho en milisegundos.
   * @param queueTimeout milisegundos minimos entre que se entregan dos requests
   * @param unit
   */
  public RateLimitBlockingQueueJobQueue(
      final BlockingQueue<T> target, final long timeout, final long queueTimeout) {
    super(target, timeout);
    Validate.isTrue(queueTimeout >= 0);

    this.queueTimeout = queueTimeout;
  }
Exemple #29
0
  @SuppressWarnings("ConstantConditions")
  public static ConfigImpl loadConfig(
      final ConfigFile config,
      final JavaPlugin plugin,
      final ClassLoader classLoader,
      final File dataFolder) {
    // Plugin or classloader must be specified
    Validate.isTrue(plugin != null || classLoader != null, "Plugin or classloader can't be null");

    final ConfigImpl cached;
    if ((cached = ConfigImpl.cache.get(config)) != null) {
      cached.reload(); // Make sure the config is up-to-date
      return cached;
    }

    final File file =
        new File(
            dataFolder != null ? dataFolder : (plugin != null ? plugin.getDataFolder() : null),
            config.getFileName());

    if (!file.exists()) // Copy the config from jar file
    {
      final InputStream inJarFile =
          classLoader != null
              ? classLoader.getResourceAsStream(config.getFileName())
              : plugin.getResource(config.getFileName());

      IOUtils.saveToFile(inJarFile, file);
    }

    final ConfigImpl configuration =
        new ConfigImpl(YamlConfiguration.loadConfiguration(file), file, config);
    ConfigImpl.cache.put(config, configuration);
    return configuration;
  }
 /**
  * Constructor.
  *
  * @param calendar The calendar used to calculate the termination time
  * @param retentionDays The number of days that the marked ASG is retained before being terminated
  * @param launchConfigAgeThreshold The number of days that the launch configuration for the ASG
  *     has been created that makes the ASG be considered obsolete
  * @param lastChangeDaysThreshold The number of days that the launch configuration has not been
  *     changed. An ASG is considered as a cleanup candidate only if it has no change during the
  *     last n days. The parameter can be null.
  * @param instanceValidator The instance validator to check if an instance is active
  */
 public OldEmptyASGRule(
     MonkeyCalendar calendar,
     int launchConfigAgeThreshold,
     Integer lastChangeDaysThreshold,
     int retentionDays,
     ASGInstanceValidator instanceValidator) {
   Validate.notNull(calendar);
   Validate.isTrue(retentionDays >= 0);
   Validate.isTrue(launchConfigAgeThreshold >= 0);
   Validate.isTrue(lastChangeDaysThreshold == null || lastChangeDaysThreshold >= 0);
   Validate.notNull(instanceValidator);
   this.calendar = calendar;
   this.retentionDays = retentionDays;
   this.launchConfigAgeThreshold = launchConfigAgeThreshold;
   this.lastChangeDaysThreshold = lastChangeDaysThreshold;
   this.instanceValidator = instanceValidator;
 }