class BlackFormulaRepository {

  public static double impliedVolatility(
      double price,
      double forward,
      double strike,
      double timeToExpiry,
      boolean isCall) {

    ArgChecker.isTrue(price >= 0d, "negative/NaN price; have {}", price);
    ArgChecker.isTrue(forward > 0d, "negative/NaN forward; have {}", forward);
    ArgChecker.isTrue(strike >= 0d, "negative/NaN strike; have {}", strike);
    ArgChecker.isTrue(timeToExpiry >= 0d, "negative/NaN timeToExpiry; have {}", timeToExpiry);

    ArgChecker.isFalse(Double.isInfinite(forward), "forward is Infinity");
    ArgChecker.isFalse(Double.isInfinite(strike), "strike is Infinity");
    ArgChecker.isFalse(Double.isInfinite(timeToExpiry), "timeToExpiry is Infinity");

    double intrinsicPrice = Math.max(0., (isCall ? 1 : -1) * (forward - strike));

    double targetPrice = price - intrinsicPrice;
    // Math.max(0., price - intrinsicPrice) should not used for least chi square
    double sigmaGuess = 0.3;
    return impliedVolatility(targetPrice, forward, strike, timeToExpiry, sigmaGuess);
  }

  private  BlackFormulaRepository();

}