Beispiel #1
0
def _blsimpv(price, spot, strike, risk_free_rate, time, option_type, dividend):

    spot = SimpleQuote(spot)
    daycounter = ActualActual(ISMA)
    risk_free_ts = FlatForward(today(), risk_free_rate, daycounter)
    dividend_ts = FlatForward(today(), dividend, daycounter)
    volatility_ts = BlackConstantVol(today(), NullCalendar(), .3, daycounter)

    process = BlackScholesMertonProcess(spot, dividend_ts, risk_free_ts,
                                        volatility_ts)

    exercise_date = today() + Period(time * 365, Days)
    exercise = EuropeanExercise(exercise_date)

    payoff = PlainVanillaPayoff(option_type, strike)

    option = EuropeanOption(payoff, exercise)
    engine = AnalyticEuropeanEngine(process)
    option.set_pricing_engine(engine)

    accuracy = 0.001
    max_evaluations = 1000
    min_vol = 0.01
    max_vol = 2

    vol = option.implied_volatility(price, process, accuracy, max_evaluations,
                                    min_vol, max_vol)

    return vol
    def setUp(self):

        self.settings = Settings()

        self.calendar = TARGET()

        self.todays_date = Date(15, May, 1998)
        self.settlement_date = Date(17, May, 1998)

        self.settings.evaluation_date = self.todays_date

        # options parameters
        self.option_type = Put
        self.underlying = 36
        self.strike = 40
        self.dividend_yield = 0.00
        self.risk_free_rate = 0.06
        self.volatility = 0.20
        self.maturity = Date(17, May, 1999)
        self.daycounter = Actual365Fixed()

        self.underlyingH = SimpleQuote(self.underlying)

        # bootstrap the yield/dividend/vol curves
        self.flat_term_structure = FlatForward(
            reference_date=self.settlement_date,
            forward=self.risk_free_rate,
            daycounter=self.daycounter)
        self.flat_dividend_ts = FlatForward(
            reference_date=self.settlement_date,
            forward=self.dividend_yield,
            daycounter=self.daycounter)

        self.flat_vol_ts = BlackConstantVol(self.settlement_date,
                                            self.calendar, self.volatility,
                                            self.daycounter)

        self.black_scholes_merton_process = BlackScholesMertonProcess(
            self.underlyingH, self.flat_dividend_ts, self.flat_term_structure,
            self.flat_vol_ts)

        self.payoff = PlainVanillaPayoff(self.option_type, self.strike)

        #Additional parameters for testing DividendVanillaOption
        self.dividend_dates = []
        self.dividends = []
        self.american_time_steps = 600
        self.american_grid_points = 600

        #Parameters for implied volatility:
        self.accuracy = 0.001
        self.max_evaluations = 1000
        self.min_vol = 0.001
        self.max_vol = 4
        self.target_price = 4.485992
Beispiel #3
0
    def setUp(self):

        self.settings = Settings()

        self.calendar = NullCalendar()

        self.today = Date(6, June, 2021)
        self.settlement_date = self.today + 90

        self.settings.evaluation_date = self.today

        # options parameters
        self.option_type = Put
        self.underlying = 80.0
        self.strike = 85.0
        self.dividend_yield = -0.03
        self.risk_free_rate = 0.05
        self.volatility = 0.20
        # self.maturity = Date(17, May, 1999)
        self.daycounter = Actual360()

        self.underlyingH = SimpleQuote(self.underlying)

        # bootstrap the yield/dividend/vol curves
        self.flat_term_structure = FlatForward(
            reference_date=self.today,
            forward=self.risk_free_rate,
            daycounter=self.daycounter
        )
        self.flat_dividend_ts = FlatForward(
            reference_date=self.today,
            forward=self.dividend_yield,
            daycounter=self.daycounter
        )

        self.flat_vol_ts = BlackConstantVol(
            self.today,
            self.calendar,
            self.volatility,
            self.daycounter
        )

        self.black_scholes_merton_process = BlackScholesMertonProcess(
            self.underlyingH,
            self.flat_dividend_ts,
            self.flat_term_structure,
            self.flat_vol_ts
        )

        self.payoff = PlainVanillaPayoff(self.option_type, self.strike)
Beispiel #4
0
def _blsprice(spot,
              strike,
              risk_free_rate,
              time,
              volatility,
              option_type='Call',
              dividend=0.0,
              calc='price'):
    """
    Black-Scholes option pricing model + greeks.
    """
    _spot = SimpleQuote(spot)

    daycounter = ActualActual(ISMA)
    risk_free_ts = FlatForward(today(), risk_free_rate, daycounter)
    dividend_ts = FlatForward(today(), dividend, daycounter)
    volatility_ts = BlackConstantVol(today(), NullCalendar(), volatility,
                                     daycounter)

    process = BlackScholesMertonProcess(_spot, dividend_ts, risk_free_ts,
                                        volatility_ts)

    exercise_date = today() + Period(time * 365, Days)
    exercise = EuropeanExercise(exercise_date)

    payoff = PlainVanillaPayoff(option_type, strike)

    option = EuropeanOption(payoff, exercise)
    engine = AnalyticEuropeanEngine(process)
    option.set_pricing_engine(engine)

    if calc == 'price':
        res = option.npv
    elif calc == 'delta':
        res = option.delta
    elif calc == 'gamma':
        res = option.gamma
    elif calc == 'theta':
        res = option.theta
    elif calc == 'rho':
        res = option.rho
    elif calc == 'vega':
        res = option.vega
    elif calc == 'lambda':
        res = option.delta * spot / option.npv
    else:
        raise ValueError('calc type %s is unknown' % calc)

    return res
    def setUp(self):

        self.settings = Settings()

        self.calendar = NullCalendar()

        self.todays_date = Date(15, May, 1998)
        self.settlement_date = Date(17, May, 1998)

        self.settings.evaluation_date = self.todays_date

        # options parameters
        self.dividend_yield = 0.00
        self.risk_free_rate = 0.06
        self.volatility = 0.25
        self.spot = SimpleQuote(100)
        self.maturity = Date(17, May, 1999)
        self.daycounter = Actual365Fixed()
        self.tol = 1e-2

        # bootstrap the yield/dividend/vol curves
        dates = [self.settlement_date] + \
                [self.settlement_date + Period(i + 1, Years)
                 for i in range(40)]
        rates = [0.01] + \
            [0.01 + 0.0002 * np.exp(np.sin(i / 4.0)) for i in range(40)]
        divRates = [0.02] + \
                   [0.02 + 0.0001 * np.exp(np.sin(i / 5.0)) for i in range(40)]

        self.r_ts = ZeroCurve(dates, rates, self.daycounter)
        self.q_ts = ZeroCurve(dates, divRates, self.daycounter)

        self.vol_ts = BlackConstantVol(
            self.settlement_date,
            self.calendar,
            self.volatility,
            self.daycounter
        )

        self.black_scholes_merton_process = BlackScholesMertonProcess(
            self.spot,
            self.q_ts,
            self.r_ts,
            self.vol_ts
        )

        self.dates = dates
Beispiel #6
0
def blsprice(spot, strike, risk_free_rate, time, volatility, option_type='Call', dividend=0.0):
    """ """
    spot = SimpleQuote(spot)

    daycounter = Actual360()
    risk_free_ts = FlatForward(today(), risk_free_rate, daycounter)
    dividend_ts = FlatForward(today(), dividend, daycounter)
    volatility_ts = BlackConstantVol(today(), NullCalendar(), volatility, daycounter)

    process = BlackScholesMertonProcess(spot, dividend_ts, risk_free_ts, volatility_ts)

    exercise_date = today() + 90
    exercise = EuropeanExercise(exercise_date)

    payoff = PlainVanillaPayoff(option_type, strike)

    option = EuropeanOption(payoff, exercise)
    engine = AnalyticEuropeanEngine(process)
    option.set_pricing_engine(engine)
    return option.npv
Beispiel #7
0
    def test_bsm_hw(self):
        print("Testing European option pricing for a BSM process" +
              " with one-factor Hull-White model...")

        dc = Actual365Fixed()
        todays_date = today()
        maturity_date = todays_date + Period(20, Years)

        settings = Settings()
        settings.evaluation_date = todays_date

        spot = SimpleQuote(100)

        q_ts = flat_rate(todays_date, 0.04, dc)
        r_ts = flat_rate(todays_date, 0.0525, dc)
        vol_ts = BlackConstantVol(todays_date, NullCalendar(), 0.25, dc)

        hullWhiteModel = HullWhite(r_ts, 0.00883, 0.00526)

        bsm_process = BlackScholesMertonProcess(spot, q_ts, r_ts, vol_ts)

        exercise = EuropeanExercise(maturity_date)

        fwd = spot.value * q_ts.discount(maturity_date) / \
            r_ts.discount(maturity_date)

        payoff = PlainVanillaPayoff(Call, fwd)

        option = VanillaOption(payoff, exercise)

        tol = 1e-8
        corr = [-0.75, -0.25, 0.0, 0.25, 0.75]
        expectedVol = [
            0.217064577, 0.243995801, 0.256402830, 0.268236596, 0.290461343
        ]

        for c, v in zip(corr, expectedVol):
            bsm_hw_engine = AnalyticBSMHullWhiteEngine(c, bsm_process,
                                                       hullWhiteModel)

            option = VanillaOption(payoff, exercise)
            option.set_pricing_engine(bsm_hw_engine)
            npv = option.npv

            compVolTS = BlackConstantVol(todays_date, NullCalendar(), v, dc)

            bs_process = BlackScholesMertonProcess(spot, q_ts, r_ts, compVolTS)
            bsEngine = AnalyticEuropeanEngine(bs_process)

            comp = VanillaOption(payoff, exercise)
            comp.set_pricing_engine(bsEngine)

            impliedVol = comp.implied_volatility(npv,
                                                 bs_process,
                                                 1e-10,
                                                 500,
                                                 min_vol=0.1,
                                                 max_vol=0.4)

            if (abs(impliedVol - v) > tol):
                print("Failed to reproduce implied volatility cor: %f" % c)
                print("calculated: %f" % impliedVol)
                print("expected  : %f" % v)

            if abs((comp.npv - npv) / npv) > tol:
                print("Failed to reproduce NPV")
                print("calculated: %f" % comp.npv)
                print("expected  : %f" % npv)

            self.assertAlmostEqual(impliedVol, v, delta=tol)
            self.assertAlmostEqual(comp.npv / npv, 1, delta=tol)
Beispiel #8
0
    def test_compare_BsmHW_HestonHW(self):
        """
        From Quantlib test suite
        """

        print("Comparing European option pricing for a BSM " +
              "process with one-factor Hull-White model...")

        dc = Actual365Fixed()

        todays_date = today()
        settings = Settings()
        settings.evaluation_date = todays_date
        tol = 1.e-2

        spot = SimpleQuote(100)

        dates = [todays_date + Period(i, Years) for i in range(40)]

        rates = [0.01 + 0.0002 * np.exp(np.sin(i / 4.0)) for i in range(40)]
        divRates = [0.02 + 0.0001 * np.exp(np.sin(i / 5.0)) for i in range(40)]

        s0 = SimpleQuote(100)

        r_ts = ZeroCurve(dates, rates, dc)
        q_ts = ZeroCurve(dates, divRates, dc)

        vol = SimpleQuote(0.25)
        vol_ts = BlackConstantVol(todays_date, NullCalendar(), vol.value, dc)

        bsm_process = BlackScholesMertonProcess(spot, q_ts, r_ts, vol_ts)

        variance = vol.value * vol.value
        hestonProcess = HestonProcess(risk_free_rate_ts=r_ts,
                                      dividend_ts=q_ts,
                                      s0=s0,
                                      v0=variance,
                                      kappa=5.0,
                                      theta=variance,
                                      sigma=1e-4,
                                      rho=0.0)

        hestonModel = HestonModel(hestonProcess)

        hullWhiteModel = HullWhite(r_ts, a=0.01, sigma=0.01)

        bsmhwEngine = AnalyticBSMHullWhiteEngine(0.0, bsm_process,
                                                 hullWhiteModel)

        hestonHwEngine = AnalyticHestonHullWhiteEngine(hestonModel,
                                                       hullWhiteModel, 128)

        tol = 1e-5
        strikes = [0.25, 0.5, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.5, 2.0, 4.0]
        maturities = [1, 2, 3, 5, 10, 15, 20, 25, 30]
        types = [Put, Call]

        for type in types:
            for strike in strikes:
                for maturity in maturities:
                    maturity_date = todays_date + Period(maturity, Years)

                    exercise = EuropeanExercise(maturity_date)

                    fwd = strike * s0.value * \
                        q_ts.discount(maturity_date) / \
                        r_ts.discount(maturity_date)

                    payoff = PlainVanillaPayoff(type, fwd)

                    option = VanillaOption(payoff, exercise)

                    option.set_pricing_engine(bsmhwEngine)
                    calculated = option.npv

                    option.set_pricing_engine(hestonHwEngine)
                    expected = option.npv

                    if ((np.abs(expected - calculated) > calculated * tol)
                            and (np.abs(expected - calculated) > tol)):

                        cp = PAYOFF_TO_STR[type]
                        print("Failed to reproduce npv")
                        print("strike    : %f" % strike)
                        print("maturity  : %d" % maturity)
                        print("type      : %s" % cp)

                    self.assertAlmostEqual(expected, calculated, delta=tol)
Beispiel #9
0
    def test_compare_bsm_bsmhw_hestonhw(self):

        dc = Actual365Fixed()

        todays_date = today()
        settings = Settings()
        settings.evaluation_date = todays_date
        tol = 1.e-2

        spot = SimpleQuote(100)

        dates = [todays_date + Period(i, Years) for i in range(40)]

        rates = [0.01 + 0.0002 * np.exp(np.sin(i / 4.0)) for i in range(40)]
        divRates = [0.02 + 0.0001 * np.exp(np.sin(i / 5.0)) for i in range(40)]

        s0 = SimpleQuote(100)

        r_ts = ZeroCurve(dates, rates, dc)
        q_ts = ZeroCurve(dates, divRates, dc)

        vol = SimpleQuote(0.25)
        vol_ts = BlackConstantVol(todays_date, NullCalendar(), vol.value, dc)

        bsm_process = BlackScholesMertonProcess(spot, q_ts, r_ts, vol_ts)

        payoff = PlainVanillaPayoff(Call, 100)
        exercise = EuropeanExercise(dates[1])

        option = VanillaOption(payoff, exercise)

        analytic_european_engine = AnalyticEuropeanEngine(bsm_process)

        option.set_pricing_engine(analytic_european_engine)
        npv_bsm = option.npv

        variance = vol.value * vol.value
        hestonProcess = HestonProcess(risk_free_rate_ts=r_ts,
                                      dividend_ts=q_ts,
                                      s0=s0,
                                      v0=variance,
                                      kappa=5.0,
                                      theta=variance,
                                      sigma=1e-4,
                                      rho=0.0)

        hestonModel = HestonModel(hestonProcess)

        hullWhiteModel = HullWhite(r_ts, a=0.01, sigma=0.01)

        bsmhwEngine = AnalyticBSMHullWhiteEngine(0.0, bsm_process,
                                                 hullWhiteModel)

        hestonHwEngine = AnalyticHestonHullWhiteEngine(hestonModel,
                                                       hullWhiteModel, 128)

        hestonEngine = AnalyticHestonEngine(hestonModel, 144)
        option.set_pricing_engine(hestonEngine)

        npv_heston = option.npv

        option.set_pricing_engine(bsmhwEngine)
        npv_bsmhw = option.npv

        option.set_pricing_engine(hestonHwEngine)
        npv_hestonhw = option.npv

        print("calculated with BSM: %f" % npv_bsm)
        print("BSM-HW: %f" % npv_bsmhw)
        print("Heston: %f" % npv_heston)
        print("Heston-HW: %f" % npv_hestonhw)

        self.assertAlmostEqual(npv_bsm, npv_bsmhw, delta=tol)
        self.assertAlmostEqual(npv_bsm, npv_hestonhw, delta=tol)
Beispiel #10
0
    def test_analytic_cont_geo_av_price_greeks(self):
        
        tolerance = {}
        tolerance["delta"]  = 1.0e-5
        tolerance["gamma"]  = 1.0e-5
        # tolerance["theta"]  = 1.0e-5
        tolerance["rho"]    = 1.0e-5
        tolerance["divRho"] = 1.0e-5
        tolerance["vega"]   = 1.0e-5

        opt_types = [Call, Put]
        underlyings = [100.0]
        strikes = [90.0, 100.0, 110.0]
        q_rates = [0.04, 0.05, 0.06]
        r_rates = [0.01, 0.05, 0.15]
        lengths = [1, 2]
        vols = [0.11, 0.50, 1.20]
       
        spot = SimpleQuote(0.0)
        q_rate = SimpleQuote(0.0)
        r_rate = SimpleQuote(0.0)
        vol = SimpleQuote(0.0)

        q_ts = flat_rate(q_rate, self.daycounter)
        r_ts =  flat_rate(r_rate, self.daycounter)
        vol_ts = BlackConstantVol(self.today, self.calendar, vol, self.daycounter)

        process = BlackScholesMertonProcess(spot, q_ts, r_ts, vol_ts)

        calculated = {}
        expected = {}
        for opt_type, strike, length in product(opt_types, strikes, lengths):
            
            maturity = EuropeanExercise(self.today + length*Years)

            payoff = PlainVanillaPayoff(opt_type, strike)

            engine = AnalyticContinuousGeometricAveragePriceAsianEngine(process)

            option = ContinuousAveragingAsianOption(Geometric, payoff, maturity)
                
            option.set_pricing_engine(engine)

            for u, m, n, v in product(underlyings, q_rates, r_rates, vols):

                q = m 
                r = n
                spot.value = u
                q_rate.value = q
                r_rate.value = r
                vol.value = v

                value = option.npv
                calculated["delta"] = option.delta
                calculated["gamma"] = option.gamma
                # calculated["theta"] = option.theta
                calculated["rho"] = option.rho
                calculated["divRho"] = option.dividend_rho
                calculated["vega"] = option.vega

                if (value > spot.value*1.0e-5):
                    # perturb spot and get delta and gamma
                    du = u*1.0e-4
                    spot.value = u + du
                    value_p = option.npv
                    delta_p = option.delta
                    spot.value = u - du
                    value_m = option.npv
                    delta_m = option.delta
                    spot.value = u
                    expected["delta"] = (value_p - value_m)/(2*du)
                    expected["gamma"] = (delta_p - delta_m)/(2*du)

                    # perturb rates and get rho and dividend rho
                    dr = r*1.0e-4
                    r_rate.value = r + dr
                    value_p = option.npv
                    r_rate.value = r - dr
                    value_m = option.npv
                    r_rate.value = r
                    expected["rho"] = (value_p - value_m)/(2*dr)

                    dq = q*1.0e-4
                    q_rate.value = q + dq
                    value_p = option.npv
                    q_rate.value = q - dq
                    value_m = option.npv
                    q_rate.value = q
                    expected["divRho"] = (value_p - value_m)/(2*dq)

                    # perturb volatility and get vega
                    dv = v*1.0e-4
                    vol.value = v + dv
                    value_p = option.npv
                    vol.value = v - dv
                    value_m = option.npv
                    vol.value = v
                    expected["vega"] = (value_p - value_m)/(2*dv)

                    # perturb date and get theta
                    dt = self.daycounter.year_fraction(self.today - 1, self.today + 1)
                    self.settings.evaluation_date = self.today - 1
                    value_m = option.npv
                    self.settings.evaluation_date = self.today + 1
                    value_p = option.npv
                    self.settings.evaluation_date = self.today
                    expected["theta"] = (value_p - value_m)/dt

                    # compare
                    for greek, calcl in calculated.items():
                        expct = expected[greek]
                        tol = tolerance[greek]
                        error = relative_error(expct, calcl, u)
                        self.assertTrue(error < tol)
Beispiel #11
0
volatility = 0.20
maturity = settlement_date + 363
daycounter = Actual365Fixed()

underlyingH = SimpleQuote(underlying)

# bootstrap the yield/dividend/vol curves
flat_term_structure = FlatForward(reference_date=settlement_date,
                                  forward=risk_free_rate,
                                  daycounter=daycounter)

flat_dividend_ts = FlatForward(reference_date=settlement_date,
                               forward=dividend_yield,
                               daycounter=daycounter)

flat_vol_ts = BlackConstantVol(settlement_date, calendar, volatility,
                               daycounter)

black_scholes_merton_process = BlackScholesMertonProcess(
    underlyingH, flat_dividend_ts, flat_term_structure, flat_vol_ts)

payoff = PlainVanillaPayoff(option_type, strike)

european_exercise = EuropeanExercise(maturity)

european_option = VanillaOption(payoff, european_exercise)

method = 'Black-Scholes'
analytic_european_engine = AnalyticEuropeanEngine(black_scholes_merton_process)

european_option.set_pricing_engine(analytic_european_engine)