Ejemplo n.º 1
0
def Pricing_by_QuantLib(v0, S0, K, tau, mu, kappa, theta, sigma, rho, Type):
    # construct the European Option
    payoff = ql.PlainVanillaPayoff(
        Type,
        K)  # (option_type, strike_price) enum Type { Put = -1,. Call = 1. }
    european_option = ql.VanillaOption(payoff, exercise)

    ql.Settings.instance().evaluationDate = calculation_date
    day_count = ql.Actual365Fixed()

    #dividend_yield = ql.QuoteHandle(ql.SimpleQuote(0.0))
    risk_free_rate = 0.0
    dividend_rate = 0.0

    flat_ts = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, risk_free_rate, day_count))

    dividend_ts = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, dividend_rate, day_count))

    # parameters initialization
    heston_process = ql.HestonProcess(flat_ts, dividend_ts,
                                      ql.QuoteHandle(ql.SimpleQuote(spot)), v0,
                                      kappa, theta, sigma, rho)

    engine = ql.AnalyticHestonEngine(
        ql.HestonModel(heston_process))  #,0.01, 1000)
    european_option.setPricingEngine(engine)
    h_price = european_option.NPV()
    #    print ("The Heston model price is", h_price)
    #     ql.HestonModel(2.3) # HestonProcessPtr const &
    #     iv = european_option.impliedVolatility(6.51, heston_process)
    #     # VanillaOptionPtr::impliedVolatility(Real,GeneralizedBlackScholesProcessPtr const &)
    #     print("iv is ", iv)
    return h_price
Ejemplo n.º 2
0
def call_price_exact(kappa, theta, beta, rho, v0, r, T, s0, K):
    strike_price = 110.0
    payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike_price)
    # option data
    calculation_date = ql.Date(15, 1, 2011)
    maturity_date = ql.Date(15, 1, 2011 + T)
    spot_price = s0
    strike_price = K
    dividend_rate = 0.00
    option_type = ql.Option.Call
    risk_free_rate = r
    day_count = ql.Actual365Fixed()
    ql.Settings.instance().evaluationDate = calculation_date
    # construct the Heston process
    payoff = ql.PlainVanillaPayoff(option_type, strike_price)
    exercise = ql.EuropeanExercise(maturity_date)
    european_option = ql.VanillaOption(payoff, exercise)
    sigma = beta
    spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
    flat_ts = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, risk_free_rate, day_count))
    dividend_yield = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, dividend_rate, day_count))
    heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, v0,
                                      kappa, theta, sigma, rho)
    engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process), 0.0000001,
                                     100000)
    european_option.setPricingEngine(engine)
    h_price = european_option.NPV()
    return h_price
Ejemplo n.º 3
0
 def get_vanilla_option_price_analytic(self, strike, maturity_period,
                                       option_type = ql.Option.Call):
     self.option = self.vanilla_option_helper(
             strike, maturity_period, option_type)
     self.model = ql.HestonModel(self.process)
     self.engine = ql.AnalyticHestonEngine(self.model)
     self.option.setPricingEngine(self.engine)
     return self.option.NPV()
Ejemplo n.º 4
0
def setup_model(_yield_ts,
                _dividend_ts,
                _spot,
                init_condition=(0.02, 0.2, 0.5, 0.1, 0.01)):
    theta, kappa, sigma, rho, v0 = init_condition
    process = ql.HestonProcess(_yield_ts, _dividend_ts,
                               ql.QuoteHandle(ql.SimpleQuote(_spot)), v0,
                               kappa, theta, sigma, rho)
    model = ql.HestonModel(process)
    engine = ql.AnalyticHestonEngine(model)
    return model, engine
 def __init__(self, calc_date=calibration_date, option_type=ql.Option.Call):
     super().__init__()
     tf.set_random_seed(self.seed)
     np.random.seed(self.seed)
     self.spot = self.S0
     self.calc_date = calc_date
     self.spot = ql.SimpleQuote(self.spot)
     self.s0 = ql.QuoteHandle(self.spot)
     self.rf = set_rf(calc_date, self.r)
     self.ir = set_dividend(calc_date, self.q)
     self.process = ql.HestonProcess(self.rf, self.ir, self.s0, self.v0,
                                     self.kappa, self.theta, self.sigma,
                                     self.rho)
     self.engine = ql.AnalyticHestonEngine(ql.HestonModel(self.process))
     self.option = EU_option(calc_date, option_type, self.K, self.ttm)
     self.option.setPricingEngine(self.engine)
Ejemplo n.º 6
0
def to_ql_option_engine(engine_name=None, process=None, model=None):
    """ Returns a QuantLib.PricingEngine for Options

    :param engine_name: str
        The engine name
    :param process: QuantLib.StochasticProcess
        The QuantLib object with the option Stochastic Process.
    :param model: QuantLib.CalibratedModel
    :return: QuantLib.PricingEngine
    """
    if engine_name.upper() == 'BINOMIAL_VANILLA':
        return ql.BinomialVanillaEngine(process, 'LR', 801)
    elif engine_name.upper() == 'ANALYTIC_HESTON':
        if model is None:
            model = ql.HestonModel(process)
        elif model is not None and process is not None:
            model = model(process)
        return ql.AnalyticHestonEngine(model)
    elif engine_name.upper() == 'ANALYTIC_EUROPEAN':
        return ql.AnalyticEuropeanEngine(process)
    elif engine_name.upper() == 'ANALYTIC_EUROPEAN_DIVIDEND':
        return ql.AnalyticDividendEuropeanEngine(process)
    elif engine_name.upper() == "FINITE_DIFFERENCES":
        return ql.FdBlackScholesVanillaEngine(process)
    elif engine_name.upper() == 'HESTON_FINITE_DIFFERENCES':
        if model is None:
            model = ql.HestonModel(process)
        elif model is not None and process is not None:
            model = model(process)
        return ql.FdHestonVanillaEngine(model)
    elif engine_name.upper() == "BARONE_ADESI_WHALEY":
        return ql.BaroneAdesiWhaleyEngine(process)
    elif engine_name.upper() == "BJERKSUND_STENSLAND":
        return ql.BjerksundStenslandEngine(process)
    elif engine_name.upper() == "ANALYTIC_GJR_GARCH":
        if model is None:
            model = ql.GJRGARCHModel(process)
        elif model is not None and process is not None:
            model = model(process)
        return ql.AnalyticGJRGARCHEngine(model)
    elif engine_name.upper() == 'MC_GJR_GARCH':
        return ql.MCEuropeanGJRGARCHEngine(process=process,
                                           traits='pseudorandom',
                                           timeStepsPerYear=20,
                                           requiredTolerance=0.02)
    else:
        return None
Ejemplo n.º 7
0
    def __init__(self, vol_data):
        super().__init__(vol_data)
        self.process = ql.HestonProcess(
            self.dom_ts, self.for_ts,
            ql.QuoteHandle(ql.SimpleQuote(self.spot)), self.v0, self.kappa,
            self.theta, self.sigma, self.rho)
        self.model = ql.HestonModel(self.process)
        self.engine = ql.AnalyticHestonEngine(self.model)
        self.bl_surface = ql.BlackVarianceSurface(
            self.calculation_date, self.calendar, self.expiration_dates,
            self.strikes, self.implied_vols, self.day_count)

        self.bl_surface.setInterpolation("bicubic")
        vol_ts = ql.BlackVolTermStructureHandle(self.bl_surface)
        self.bs_process = BlackScholesMertonProcess(
            ql.QuoteHandle(ql.SimpleQuote(self.spot)), self.for_ts,
            self.dom_ts, vol_ts)
Ejemplo n.º 8
0
def price(S0=100,
          K=100,
          r=0.025,
          T=30,
          V0=0.04,
          kappa=1.0,
          theta=0.04,
          sigma=0.8,
          rho=-0.7,
          type='c'):
    assert type == 'c' or type == 'p'
    today = ql.Date(1, ql.December, 2018)
    ql.Settings.instance().evaluationDate = today
    riskFreeRate = ql.FlatForward(today, r, ql.Actual365Fixed())
    dividendRate = ql.FlatForward(today, 0.0, ql.Actual365Fixed())

    # maturity_date = ql.Date(31, ql.December, 2018)
    maturity_date = today + T

    payoff = ql.PlainVanillaPayoff(
        ql.Option.Call if type == 'c' else ql.Option.Put, K)
    exercise = ql.EuropeanExercise(maturity_date)
    european_option = ql.VanillaOption(payoff, exercise)

    heston_process = ql.HestonProcess(
        ql.YieldTermStructureHandle(riskFreeRate),
        ql.YieldTermStructureHandle(dividendRate),
        ql.QuoteHandle(ql.SimpleQuote(S0)),  # S0
        V0,  # v0
        kappa,  # kappa
        theta,  # theta
        sigma,  # sigma
        rho,  # rho
    )

    engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process))
    european_option.setPricingEngine(engine)
    h_price = european_option.NPV()
    return h_price
Ejemplo n.º 9
0
def HestonModelCalibrator(valuationDate, calendar, spot, curveHandle,
                          dividendHandle, v0, kappa, theta, sigma, rho,
                          expiration_dates, strikes, data, optimizer, bounds):

    # container for heston calibration helpers
    helpers = []

    # create Heston process, model and pricing engine
    # use given initial parameters for model
    process = ql.HestonProcess(curveHandle, dividendHandle,
                               ql.QuoteHandle(ql.SimpleQuote(spot)), v0, kappa,
                               theta, sigma, rho)
    model = ql.HestonModel(process)
    engine = ql.AnalyticHestonEngine(model)

    # nested cost function for model optimization
    def CostFunction(x):
        parameters = ql.Array(list(x))
        model.setParams(parameters)
        error = [helper.calibrationError() for helper in helpers]
        return np.sqrt(np.sum(np.abs(error)))

    # create Heston calibration helpers, set pricing engines
    for i in range(len(expiration_dates)):
        for j in range(len(strikes)):
            expiration = expiration_dates[i]
            days = expiration - valuationDate
            period = ql.Period(days, ql.Days)
            vol = data[i][j]
            strike = strikes[j]
            helper = ql.HestonModelHelper(period, calendar, spot, strike,
                                          ql.QuoteHandle(ql.SimpleQuote(vol)),
                                          curveHandle, dividendHandle)
            helper.setPricingEngine(engine)
            helpers.append(helper)

    # run optimization, return calibrated model and process
    optimizer(CostFunction, bounds)
    return process, model
Ejemplo n.º 10
0
def heston_sensitivity(volatility, maturity_date, spot_price, strike_price,
                       dividend_rate, option_type, risk_free_rate,
                       calculation_date, hestonparams):
    day_count = ql.Actual365Fixed()
    calendar = ql.UnitedStates()
    ql.Settings.instance().evaluationDate = calculation_date
    payoff = ql.PlainVanillaPayoff(option_type, strike_price)
    exercise = ql.EuropeanExercise(maturity_date)
    european_option = ql.VanillaOption(payoff, exercise)
    spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
    flat_ts = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, risk_free_rate, day_count))
    dividend_yield = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, dividend_rate, day_count))
    volatility = volatility[0]
    flat_vol_ts = ql.BlackVolTermStructureHandle(
        ql.BlackConstantVol(calculation_date, calendar, volatility, day_count))
    bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield,
                                               flat_ts, flat_vol_ts)
    european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process))
    bs_price = european_option.NPV()
    spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
    flat_ts = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, risk_free_rate, day_count))
    dividend_yield = ql.YieldTermStructureHandle(
        ql.FlatForward(calculation_date, dividend_rate, day_count))
    heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle,
                                      hestonparams[0], hestonparams[1],
                                      hestonparams[2], hestonparams[3],
                                      hestonparams[4])
    engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process), 0.01,
                                     1000)
    european_option.setPricingEngine(engine)
    h_price = european_option.NPV()
    #return h_price,bs_price
    return h_price
# Analytic formulas:

# Black-Scholes for European
method = 'Black-Scholes'
europeanOption.setPricingEngine(
    ql.AnalyticEuropeanEngine(bsmProcess))
tab.add_row([method, europeanOption.NPV(), 'N/A', 'N/A'])

# semi-analytic Heston for European
method = 'Heston semi-analytic'
hestonProcess = ql.HestonProcess(
    flatTermStructure, flatDividendTS, underlyingH,
    volatility * volatility, 1.0, volatility * volatility, 0.001, 0.0)
hestonModel = ql.HestonModel(hestonProcess)
europeanOption.setPricingEngine(
    ql.AnalyticHestonEngine(hestonModel))
tab.add_row([method, europeanOption.NPV(), 'N/A', 'N/A'])

# semi-analytic Bates for European
method = 'Bates semi-analytic'
batesProcess = ql.BatesProcess(
    flatTermStructure, flatDividendTS, underlyingH,
    volatility * volatility, 1.0, volatility * volatility,
    0.001, 0.0, 1e-14, 1e-14, 1e-14)
batesModel = ql.BatesModel(batesProcess)
europeanOption.setPricingEngine(
    ql.BatesEngine(batesModel))
tab.add_row([method, europeanOption.NPV(), 'N/A', 'N/A'])

# Barone-Adesi and Whaley approximation for American
method = 'Barone-Adesi/Whaley'
Ejemplo n.º 12
0
ql.Settings.instance().evaluationDate = calculation_date
dividend_yield = ql.QuoteHandle(ql.SimpleQuote(0.0))
risk_free_rate = 0.01
dividend_rate = 0.0
flat_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, risk_free_rate, day_count))
dividend_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, dividend_rate, day_count))
# dummy parameters
initial_var = 0.2; rate_reversion = 0.5; long_term_var = 0.2; corr = -0.75; vol_of_vol = 0.2;
# initial_var = 0.2; rate_reversion = 0.15; long_term_var = 0.6; corr = -0.75; vol_of_vol = 0.2;
process = ql.HestonProcess(flat_ts, dividend_ts,
                           ql.QuoteHandle(ql.SimpleQuote(spot)),
                           initial_var, rate_reversion, long_term_var, vol_of_vol, corr)
model = ql.HestonModel(process)
engine = ql.AnalyticHestonEngine(model)
heston_helpers = []
date = expiration_dates[expiry_index]
for j, s in enumerate(strikes):
    t = (date - calculation_date)
    p = ql.Period(t, ql.Days)
    sigma = premium[j]
    helper = ql.HestonModelHelper(p, calendar, spot, s,
                                  ql.QuoteHandle(ql.SimpleQuote(sigma)),
                                  flat_ts,
                                  dividend_ts)
    helper.setPricingEngine(engine)
    heston_helpers.append(helper)
lm = ql.LevenbergMarquardt(1e-8, 1e-8, 1e-8)
model.calibrate(heston_helpers, lm,
                 ql.EndCriteria(500, 50, 1.0e-8,1.0e-8, 1.0e-8))
Ejemplo n.º 13
0
 def _QLBuild(self):
     self._QLFactory = ql.AnalyticHestonEngine(
         self._HestonModel(), self._params.get('relTolerance'),
         self._params.get('maxEval'))
Ejemplo n.º 14
0
# -----------------------------------------------------------
# The Heston process is constructed here.
#
# The Heston process calculates with changing volatility during the trade
# -----------------------------------------------------------
v0 = volatility * volatility  # spot variance
kappa = 0.1
theta = v0
sigma = 0.1
rho = -0.75

spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
flat_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, risk_free_rate, day_count))
dividend_yield = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, dividend_rate, day_count))
heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, v0,
                                  kappa, theta, sigma, rho)

# ------------------------------------------------
# -----------------------------------------------
# Computation - ver. 3 - Heston
# -----------------------------------------------
# -----------------------------------------------
pricing_engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process), 0.01,
                                         1000)
european_option.setPricingEngine(pricing_engine)
h_price = european_option.NPV()
print("The Heston model price is ", h_price)
Ejemplo n.º 15
0
    0.1 * 0.1,
    0.0001,
    0.0,
)
hestonModel = ql.HestonModel(hestonProcess)

option = ql.VanillaOption(payoff, exercise)

# method: analytic
option.setPricingEngine(ql.AnalyticEuropeanEngine(process))
value = option.NPV()
refValue = value
report("analytic", value)

# method: Heston semi-analytic
option.setPricingEngine(ql.AnalyticHestonEngine(hestonModel))
report("Heston analytic", option.NPV())

# method: Heston COS method
option.setPricingEngine(ql.COSHestonEngine(hestonModel))
report("Heston COS Method", option.NPV())

# method: integral
option.setPricingEngine(ql.IntegralEngine(process))
report("integral", option.NPV())

# method: finite differences
timeSteps = 801
gridPoints = 800

option.setPricingEngine(ql.FDEuropeanEngine(process, timeSteps, gridPoints))
Ejemplo n.º 16
0
# HESTON ENGINE
v0 = 0.01
kappa = 0.5
theta = 0.01
sigma = 0.0001
rho = -0.5
HestonParams = [theta, kappa, sigma, rho, v0]
relTolerance = 0.01
maxEval = 1000
HestonProcess = ql.HestonProcess(ql.YieldTermStructureHandle(r_ts),
                                 ql.YieldTermStructureHandle(q_ts),
                                 ql.QuoteHandle(s0), v0, kappa, theta, sigma,
                                 rho)
HestonModel = ql.HestonModel(HestonProcess)
HestonEngine = ql.AnalyticHestonEngine(HestonModel, relTolerance, maxEval)
for i in range(len(EuropeanOptions)):
    EuropeanOptions[i].setPricingEngine(HestonEngine)

# GENERATE DATAS
nRand = 1000
start = time.time()
MinParamsValues = [0.1, 0.01, 0.01, -0.999, 0.01]
MaxParamsValues = [1.0, 0.50, 0.50, -0.1, 0.50]
local_start = 0
local_end = 0
ArrParams = MakeUniformRandParams(MinParamsValues, MaxParamsValues, nRand)
intermediary = time.time()

#npv = np.zeros(nRand)
#iv = np.zeros(nRand)
Ejemplo n.º 17
0
def evaluate_european_option(input_dict):

    tparams = input_dict["tradeParameters"]

    # Option Construction
    todaysDate = construct_date(tparams["evaluationDate"])
    ql.Settings.instance().evaluationDate = todaysDate

    exercise = ql.EuropeanExercise(construct_date(tparams["exerciseDate"]))
    payoff = ql.PlainVanillaPayoff(ql.Option.Call, tparams["payoff"])

    option = ql.VanillaOption(payoff, exercise)

    # Market Data
    underlying = ql.SimpleQuote(tparams["underlying"])
    dividendYield = ql.FlatForward(todaysDate, tparams["dividendYield"],
                                   ql.Actual365Fixed())
    volatility = ql.BlackConstantVol(todaysDate,
                                     ql.TARGET(), tparams["volatility"],
                                     ql.Actual365Fixed())
    riskFreeRate = ql.FlatForward(todaysDate, tparams["riskFreeRate"],
                                  ql.Actual365Fixed())

    process = ql.BlackScholesMertonProcess(
        ql.QuoteHandle(underlying),
        ql.YieldTermStructureHandle(dividendYield),
        ql.YieldTermStructureHandle(riskFreeRate),
        ql.BlackVolTermStructureHandle(volatility),
    )

    hestonModel = init_heston_model(input_dict, riskFreeRate, dividendYield,
                                    underlying)

    if input_dict["engineName"] == "AnalyticEuropeanEngine":
        option.setPricingEngine(ql.AnalyticEuropeanEngine(process))

    elif input_dict["engineName"] == "AnalyticHestonEngine":
        option.setPricingEngine(ql.AnalyticHestonEngine(hestonModel))

    elif input_dict["engineName"] == "COSHestonEngine":
        option.setPricingEngine(ql.COSHestonEngine(hestonModel))

    elif input_dict["engineName"] == "IntegralEngine":
        option.setPricingEngine(ql.IntegralEngine(process))

    elif input_dict["engineName"] == "FdBlackScholesVanillaEngine":
        timeSteps = input_dict["engineParameters"]["timeSteps"]
        gridPoints = input_dict["engineParameters"]["gridPoints"]
        option.setPricingEngine(
            ql.FdBlackScholesVanillaEngine(process, timeSteps, gridPoints))

    elif input_dict["engineName"] == "BinomialVanillaEngine":
        timeSteps = input_dict["engineParameters"]["timeSteps"]
        # possible tree settings: ["JR", "CRR", "EQP", "Trigeorgis", "Tian", "LR", "Joshi4"]
        tree = input_dict["engineParameters"]["tree"]
        option.setPricingEngine(
            ql.BinomialVanillaEngine(process, tree, timeSteps))

    elif input_dict["engineName"] == "MCEuropeanEngine":

        if input_dict["engineParameters"]["random_source"] == "pseudorandom":
            option.setPricingEngine(
                ql.MCEuropeanEngine(
                    process,
                    "pseudorandom",
                    timeSteps=input_dict["engineParameters"]["timeSteps"],
                    requiredTolerance=input_dict["engineParameters"]
                    ["requiredTolerance"],
                    seed=input_dict["engineParameters"]["seed"]))

        elif input_dict["engineParameters"][
                "random_source"] == "lowdiscrepancy":

            option.setPricingEngine(
                ql.MCEuropeanEngine(
                    process,
                    "lowdiscrepancy",
                    timeSteps=input_dict["engineParameters"]["timeSteps"],
                    requiredSamples=input_dict["engineParameters"]
                    ["requiredSamples"]))

        else:
            raise Exception("Unimplemented engineName [{}]".format(
                input_dict["engineName"]))

    else:
        raise Exception("Unimplemented engineName [{}]".format(
            input_dict["engineName"]))

    value = option.NPV()
    return value
Ejemplo n.º 18
0
payoff = ql.PlainVanillaPayoff(option_type, strike_price)
exercise = ql.EuropeanExercise(maturity_date)
european_option = ql.VanillaOption(payoff, exercise)

v0 = volatility * volatility
kappa = 0.1
theta = v0
sigma = 0.1
rho = -0.75

spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
flat_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, risk_free_rate, day_count))
dividend_yield = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, dividend_rate, day_count))
heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, v0,
                                  kappa, theta, sigma, rho)
engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process))
european_option.setPricingEngine(engine)
h_price = european_option.NPV()
print(h_price)

flat_vol_ts = ql.BlackVolTermStructureHandle(
    ql.BlackConstantVol(calculation_date, calendar, volatility, day_count))
bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield,
                                           flat_ts, flat_vol_ts)
european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process))
bs_price = european_option.NPV()
print(bs_price)
Ejemplo n.º 19
0
 def _QLBuild(self):
     self._QLFactory = ql.AnalyticHestonEngine(self._HestonModel(),
                                               self._RelTolerance,
                                               self._MaxEval)