예제 #1
0
    def testCalibration(self):

        m1 = (self.beta +
              (self.alpha + self.gamma * ql.CumulativeNormalDistribution()
               (self.lambda_value)) *
              (1 + self.lambda_value * self.lambda_value) +
              self.gamma * self.lambda_value *
              exp(-self.lambda_value * self.lambda_value / 2) / sqrt(2 * pi))
        v0 = self.omega / (1 - m1)

        helpers = list()
        for s in range(3, 10):
            for m in range(0, 3):
                vol = ql.QuoteHandle(ql.SimpleQuote(self.Volatility[s * 8 +
                                                                    m]))
                maturity = ql.Period(int((self.days[m + 1] + 3) / 7), ql.Weeks)
                heston_helper = ql.HestonModelHelper(
                    maturity,
                    self.calendar,
                    self.s0,
                    self.strike[s],
                    vol,
                    self.risk_free_ts,
                    self.dividend_yield_handle,
                    ql.BlackCalibrationHelper.ImpliedVolError,
                )
                helpers.append(heston_helper)

        new_garch_process = ql.GJRGARCHProcess(
            self.risk_free_ts,
            self.dividend_yield_handle,
            ql.QuoteHandle(ql.SimpleQuote(self.s0)),
            v0,
            self.omega,
            self.alpha,
            self.beta,
            self.gamma,
            self.lambda_value,
            self.daysPerYear,
        )
        new_garch_model = ql.GJRGARCHModel(new_garch_process)
        new_garch_engine = ql.AnalyticGJRGARCHEngine(new_garch_model)
        for helper in helpers:
            helper.setPricingEngine(new_garch_engine)

        om = ql.Simplex(0.05)
        new_garch_model.calibrate(
            helpers, om, ql.EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8))

        sse = 0
        for helper in helpers:
            diff = helper.calibrationError() * 100
            sse += diff * diff

        maxExpected = 15
        self.assertTrue(sse <= maxExpected)
예제 #2
0
    def testOptionPricing(self):

        tolerance = 0.075
        for k in range(3):
            lambda_value = self.lambda_values[k]
            m1 = (self.beta +
                  (self.alpha + self.gamma * ql.CumulativeNormalDistribution()
                   (lambda_value)) * (1 + lambda_value * lambda_value) +
                  self.gamma * lambda_value *
                  exp(-lambda_value * lambda_value / 2) / sqrt(2 * pi))
            v0 = self.omega / (1 - m1)
            quote = ql.QuoteHandle(ql.SimpleQuote(self.s0))
            garch = ql.GJRGARCHProcess(
                self.risk_free_handle,
                self.dividend_yield_handle,
                quote,
                v0,
                self.omega,
                self.alpha,
                self.beta,
                self.gamma,
                lambda_value,
                self.daysPerYear,
            )
            garch_model = ql.GJRGARCHModel(garch)
            analytic_engine = ql.AnalyticGJRGARCHEngine(garch_model)
            mc_engine = ql.MCEuropeanGJRGARCHEngine(process=garch,
                                                    traits="pseudorandom",
                                                    timeStepsPerYear=20,
                                                    requiredTolerance=0.02,
                                                    seed=1234)
            for i in range(2):
                for j in range(6):
                    payoff = ql.PlainVanillaPayoff(ql.Option.Call,
                                                   self.strike[j])
                    ex_date = self.settle_date + ql.Period(
                        self.maturity[i], ql.Days)
                    exercise = ql.EuropeanExercise(ex_date)
                    option = ql.VanillaOption(payoff, exercise)
                    option.setPricingEngine(analytic_engine)
                    analytic_price = option.NPV()
                    analytic_difference = analytic_price - self.analytic[k][i][
                        j]
                    self.assertTrue(analytic_difference <= 2 * tolerance)
                    option.setPricingEngine(mc_engine)
                    mc_price = option.NPV()
                    mc_difference = mc_price - self.mc_values[k][i][j]
                    self.assertTrue(mc_difference <= 2 * tolerance)
예제 #3
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