Ejemplo n.º 1
0
    def GreeksFunc(self, option, process):

        try:
            if self.product.exercise_type == 'E':
                engine = ql.AnalyticEuropeanEngine(process)
                option.setPricingEngine(engine)
                Greeks = pd.DataFrame([option.delta(),option.gamma(),option.vega()/100,option.theta()/365,option.rho()/100], columns = [''], \
                                       index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)'])
            elif self.product.exercise_type == 'A':
                #用BaroneAdesiWhaley离散法计算Greeks
                engine = ql.BaroneAdesiWhaleyEngine(process)
                #engine = ql.BinomialVanillaEngine(process, "crr", 100)  #BTM
                option.setPricingEngine(engine)
                Greeks = self.Numerical_Greeks(option)
            else:
                raise ValueError  #传入的参数self.product.exercise_type 无效

        #缺少解析解时用离散法蒙特卡洛模拟,计算Greeks
        except:
            engine = ql.MCDiscreteArithmeticAPEngine(
                process, self.product.mc_str, self.product.is_bb,
                self.product.is_av, self.product.is_cv, self.product.n_require,
                self.product.tolerance, self.product.n_max, self.product.seed)
            option.setPricingEngine(engine)
            Greeks = self.Numerical_Greeks(option)

# =============================================================================
#         #无论亚美还是亚欧都一样
#         engine = ql.MCDiscreteArithmeticAPEngine(process, self.product.mc_str, self.product.is_bb, self.product.is_av, self.product.is_cv, self.product.n_require, self.product.tolerance, self.product.n_max, self.product.seed)
#         option.setPricingEngine(engine)
#         Greeks = self.Numerical_Greeks(option)  #进入离散法计算Greeks
# =============================================================================

        return Greeks
Ejemplo n.º 2
0
 def reset_vol(self, vol):
     self.flat_vol_ts = ql.BlackVolTermStructureHandle(
         ql.BlackConstantVol(self.settlement, self.calendar, vol,
                             self.day_count))
     self.bsm_process = ql.BlackScholesMertonProcess(
         self.spot_handle, self.dividend_yield, self.flat_ts,
         self.flat_vol_ts)
     engine = ql.BaroneAdesiWhaleyEngine(self.bsm_process)
     self.ql_option.setPricingEngine(engine)
Ejemplo n.º 3
0
    def GreeksFunc(self, option, process):
        if self.exercise_type == 'E':
            engine = ql.AnalyticEuropeanEngine(process)
            option.setPricingEngine(engine)
            Greeks = pd.DataFrame([option.delta(),option.gamma(),option.vega()/100,option.theta()/365,option.rho()/100],\
                                   index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)'])
        elif self.exercise_type == 'A':
            #用离散法计算Greeks
            engine = ql.BaroneAdesiWhaleyEngine(process)
            #engine = ql.BinomialVanillaEngine(process, "crr", 100)  #BTM
            option.setPricingEngine(engine)

            #Delta Gamma
            u0 = self.underlying_price.value()
            p0 = option.NPV()
            h = 0.01  #dS
            self.underlying_price.setValue(u0 + h)
            p_plus = option.NPV()
            #print(p_plus)
            self.underlying_price.setValue(u0 - h)
            p_minus = option.NPV()
            self.underlying_price.setValue(u0)
            delta = (p_plus - p_minus) / (2 * h)
            gamma = (p_plus - 2 * p0 + p_minus) / (h * h)

            #Vega
            v0 = self.volatility.value()
            h = 0.1
            self.volatility.setValue(v0 + h)
            print(self.volatility.value())
            p_plus = option.NPV()
            print(p_plus)
            self.volatility.setValue(v0)
            vega = (p_plus - p0) / h

            #Theta
            ql.Settings.instance().evaluationDate = self.vDate + 1
            p1 = option.NPV()
            h = 1 / 365.0
            theta = (p1 - p0) / h
            ql.Settings.instance().evaluationDate = self.vDate

            #Rho
            r0 = self.interest_rate.value()
            h = 0.0001
            self.interest_rate.setValue(r0 + h)
            p_plus = option.NPV()
            self.interest_rate.setValue(r0)
            rho = (p_plus - p0) / h

            Greeks = pd.DataFrame([delta,gamma,vega/100,theta/365,rho/100],\
                                   index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)'])

        else:
            pass

        return Greeks
Ejemplo n.º 4
0
 def __init__(self,
              dt_eval: datetime.date,
              dt_maturity: datetime.date,
              option_type: constant.OptionType,
              option_exercise_type: constant.OptionExerciseType,
              spot: float,
              strike: float,
              vol: float = 0.2,
              rf: float = 0.03,
              n: int = 801,
              dividend_rate: float = 0.0):
     super().__init__()
     self.values: typing.List[typing.List[float]] = []
     self.asset_values: typing.List[typing.List[float]] = []
     self.exercise_values: typing.List[typing.List[float]] = []
     self.strike = strike
     self.spot = spot
     self.vol = vol
     self.rf = rf
     self.dividend_rate = dividend_rate
     self.steps: int = n
     self.maturity_date = constant.QuantlibUtil.to_ql_date(dt_maturity)
     self.settlement = constant.QuantlibUtil.to_ql_date(dt_eval)
     ql.Settings.instance().evaluationDate = self.settlement
     if option_type == constant.OptionType.PUT:
         self.option_type = ql.Option.Put
     else:
         self.option_type = ql.Option.Call
     payoff = ql.PlainVanillaPayoff(self.option_type, strike)
     if option_exercise_type == constant.OptionExerciseType.AMERICAN:
         self.exercise = ql.AmericanExercise(self.settlement,
                                             self.maturity_date)
         self.ql_option = ql.VanillaOption(payoff, self.exercise)
     else:
         self.exercise = ql.EuropeanExercise(self.maturity_date)
         self.ql_option = ql.VanillaOption(payoff, self.exercise)
     self.day_count = ql.ActualActual()
     self.calendar = ql.China()
     self.spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot))
     self.flat_ts = ql.YieldTermStructureHandle(
         ql.FlatForward(self.settlement, rf, self.day_count))
     self.dividend_yield = ql.YieldTermStructureHandle(
         ql.FlatForward(self.settlement, self.dividend_rate,
                        self.day_count))
     self.flat_vol_ts = ql.BlackVolTermStructureHandle(
         ql.BlackConstantVol(self.settlement, self.calendar, self.vol,
                             self.day_count))
     self.bsm_process = ql.BlackScholesMertonProcess(
         self.spot_handle, self.dividend_yield, self.flat_ts,
         self.flat_vol_ts)
     binomial_engine = ql.BinomialVanillaEngine(self.bsm_process, "crr",
                                                self.steps)
     self.ql_option.setPricingEngine(binomial_engine)
     ql.BaroneAdesiWhaleyEngine(self.bsm_process)
Ejemplo n.º 5
0
 def PricingFunc(self, option, process):
     '''------------- Set pricing engine, return both option and process -------------'''
     if self.exercise_type == 'E':
         engine = ql.AnalyticEuropeanEngine(process)
     elif self.exercise_type == 'A':
         engine = ql.BaroneAdesiWhaleyEngine(process)
         #engine = ql.BinomialVanillaEngine(process, "crr", 100)
     else:
         pass
     option.setPricingEngine(engine)
     return option.NPV()
Ejemplo n.º 6
0
 def PricingFunc(self, option, process):
     '''设置定价引擎'''
     # 欧式、美式均为QuantLib.AnalyticBarrierEngine
     if self.product.exercise_type == 'E':
         engine = ql.AnalyticBarrierEngine(process)
     elif self.product.exercise_type == 'A':
         engine = ql.BaroneAdesiWhaleyEngine(process)
     else:
         pass
     option.setPricingEngine(engine)
     return option.NPV()
Ejemplo n.º 7
0
 def PricingFunc(self, option, process):
     '''设置定价引擎,返回 option, process'''
     if self.product.exercise_type == 'E':
         engine = ql.AnalyticEuropeanEngine(process)
     elif self.product.exercise_type == 'A':
         engine = ql.BaroneAdesiWhaleyEngine(process)
         #engine = ql.BinomialVanillaEngine(process, "crr", 100)
     else:
         pass
     option.setPricingEngine(engine)
     return option.NPV()
Ejemplo n.º 8
0
 def GreeksFunc(self, option, process):
     if self.product.exercise_type == 'E':
         engine = ql.AnalyticEuropeanEngine(process)
         option.setPricingEngine(engine)
         Greeks = pd.DataFrame([option.delta(),option.gamma(),option.vega()/100,option.theta()/365,option.rho()/100], columns = [''], \
                                index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)'])
     elif self.product.exercise_type == 'A':
         #用离散法计算Greeks
         engine = ql.BaroneAdesiWhaleyEngine(process)
         #engine = ql.BinomialVanillaEngine(process, "crr", 100)  #BTM
         option.setPricingEngine(engine)
         Greeks = self.Numerical_Greeks(option)  #进入离散法计算Greeks
     else:
         pass
     return Greeks
Ejemplo n.º 9
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.º 10
0
# market data
underlying = ql.SimpleQuote(36.0)
volatilityQuote = ql.SimpleQuote(0.05)
volatility = ql.BlackConstantVol(todaysDate, ql.QuoteHandle(volatilityQuote),
                                 ql.Actual365Fixed())
dividendYield = ql.FlatForward(settlementDate, 0.00, ql.Actual365Fixed())

# good to go
process = ql.BlackScholesMertonProcess(
    ql.QuoteHandle(underlying),
    ql.YieldTermStructureHandle(dividendYield),
    ql.YieldTermStructureHandle(riskFreeRate),
    ql.BlackVolTermStructureHandle(volatility),
)
option1 = ql.VanillaOption(process, payoff, exercise1)
option1.setPricingEngine(ql.BaroneAdesiWhaleyEngine())


def f(x, y):
    underlying.setValue(x)
    volatilityQuote.setValue(y)
    return option1.NPV()


def add_data(tvtk_data):
    """Add a TVTK data object `tvtk_data` to the mayavi pipleine.
    """
    d = VTKDataSource()
    d.data = tvtk_data
    mayavi.add_source(d)
    return d
def get_option_greeks(**kwargs):

    # risk_free_rate and volatility in whole points not percentage points
    # for example enter 0.02 for 2 percent interest rate
    # enter 0.25 for 25 percent annual volatility

    underlying = kwargs['underlying']
    strike = kwargs['strike']
    risk_free_rate = kwargs['risk_free_rate']
    expiration_date = kwargs['expiration_date']
    calculation_date = kwargs['calculation_date']
    option_type = kwargs['option_type'].upper()
    exercise_type = kwargs['exercise_type'].upper()
    dividend_rate = 0

    expiration_datetime = cu.convert_doubledate_2datetime(expiration_date)
    calculation_datetime = cu.convert_doubledate_2datetime(calculation_date)

    expiration_date_obj = ql.Date(expiration_datetime.day, expiration_datetime.month, expiration_datetime.year)
    calculation_date_obj = ql.Date(calculation_datetime.day, calculation_datetime.month, calculation_datetime.year)

    cal_dte = day_count_obj.dayCount(calculation_date_obj, expiration_date_obj)

    nan_greeks = {'option_price': np.NaN,
            'implied_vol': np.NaN,
            'delta': np.NaN,
            'vega': np.NaN,
            'theta': np.NaN,
            'cal_dte': cal_dte,
            'gamma': np.NaN}

    if 'option_price' in kwargs.keys():
        if option_type == 'C':
            if kwargs['option_price']+strike-underlying <= 10**(-12):
                nan_greeks['delta'] = 1
                return nan_greeks
        elif option_type == 'P':
            if kwargs['option_price']-strike+underlying <= 10**(-12):
                nan_greeks['delta'] = -1
                return nan_greeks

    if cal_dte == 0:
        if option_type == 'C':
            if strike <= underlying:
                nan_greeks['delta'] = 1
            else:
                nan_greeks['delta'] = 0
        elif option_type == 'P':
            if strike >= underlying:
                nan_greeks['delta'] = -1
            else:
                nan_greeks['delta'] = 0

        return nan_greeks

    if 'implied_vol' in kwargs.keys():
        implied_vol = kwargs['implied_vol']
    else:
        implied_vol = 0.15

    if 'engine_name' in kwargs.keys():
        engine_name = kwargs['engine_name']
    else:
        engine_name = 'baw'

    if option_type == 'C':
        option_type_obj = ql.Option.Call
    elif option_type == 'P':
        option_type_obj = ql.Option.Put

    ql.Settings.instance().evaluationDate = calculation_date_obj

    if exercise_type == 'E':
        exercise_obj = ql.EuropeanExercise(expiration_date_obj)
    elif exercise_type == 'A':
        exercise_obj = ql.AmericanExercise(calculation_date_obj, expiration_date_obj)

    #print('years to expitation: ' + str(day_count_obj.yearFraction(calculation_date_obj, expiration_date_obj)))

    #print('spot: ' + str(underlying/m.exp(day_count_obj.yearFraction(calculation_date_obj, expiration_date_obj)*risk_free_rate)))

    #underlying_obj = ql.QuoteHandle(ql.SimpleQuote(underlying/m.exp(day_count_obj.yearFraction(calculation_date_obj, expiration_date_obj)*risk_free_rate)))
    underlying_obj = ql.QuoteHandle(ql.SimpleQuote(underlying))

    flat_ts_obj = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date_obj, risk_free_rate, day_count_obj))

    dividend_yield_obj = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date_obj, dividend_rate, day_count_obj))
    flat_vol_ts_obj = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date_obj, calendar_obj, implied_vol, day_count_obj))

    #bsm_process = ql.BlackScholesMertonProcess(underlying_obj, dividend_yield_obj, flat_ts_obj, flat_vol_ts_obj)
    bsm_process = ql.BlackProcess(underlying_obj, flat_ts_obj, flat_vol_ts_obj)

    payoff = ql.PlainVanillaPayoff(option_type_obj, strike)
    option_obj = ql.VanillaOption(payoff, exercise_obj)

    if (engine_name == 'baw')&(exercise_type == 'A'):
        option_obj.setPricingEngine(ql.BaroneAdesiWhaleyEngine(bsm_process))
    elif (engine_name == 'fda')&(exercise_type == 'A'):
        option_obj.setPricingEngine(ql.FDAmericanEngine(bsm_process, 100, 100))
    elif exercise_type == 'E':
        option_obj.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process))
    option_price = option_obj.NPV()

    if 'option_price' in kwargs.keys():
        try:
            implied_vol = option_obj.impliedVolatility(targetValue=kwargs['option_price'], process=bsm_process,accuracy=0.00001)

            flat_vol_ts_obj = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date_obj, calendar_obj, implied_vol, day_count_obj))
            #bsm_process = ql.BlackScholesMertonProcess(underlying_obj, dividend_yield_obj, flat_ts_obj, flat_vol_ts_obj)
            bsm_process = ql.BlackProcess(underlying_obj, flat_ts_obj, flat_vol_ts_obj)

            if (engine_name == 'baw')&(exercise_type == 'A'):
                option_obj.setPricingEngine(ql.BaroneAdesiWhaleyEngine(bsm_process))
            elif (engine_name == 'fda')&(exercise_type == 'A'):
                option_obj.setPricingEngine(ql.FDAmericanEngine(bsm_process, 100, 100))
            elif exercise_type == 'E':
                option_obj.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process))

            option_price = option_obj.NPV()
        except Exception:
            return nan_greeks

    option_obj = ql.VanillaOption(payoff, ql.EuropeanExercise(expiration_date_obj))
    option_obj.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process))

    return {'option_price': option_price,
            'implied_vol': implied_vol,
            'delta': option_obj.delta(),
            'vega': option_obj.vega(),
            'theta': option_obj.thetaPerDay(),
            'cal_dte': cal_dte,
            'gamma': option_obj.gamma()}
# Option Process
process = ql.BlackScholesMertonProcess(
    ql.QuoteHandle(S),
    ql.YieldTermStructureHandle(q),
    ql.YieldTermStructureHandle(r),
    ql.BlackVolTermStructureHandle(v),
)

option = ql.VanillaOption(payoff, exercise)

refValue = $reference value$
report("reference value", refValue)

# method - analytic
option.setPricingEngine(ql.BaroneAdesiWhaleyEngine(process))
report("Barone-Adesi-Whaley", option.NPV())

option.setPricingEngine(ql.BjerksundStenslandEngine(process))
report("Bjerksund-Stensland", option.NPV())

# method - finite differences
timeSteps = 801
gridPoints = 800

option.setPricingEngine(ql.FDAmericanEngine(process, timeSteps, gridPoints))
report("finite differences", option.NPV())

# method - binomial
timeSteps = 801