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
예제 #2
0
    def setUp(self):
        self.calendar = TARGET()
        self.today = Date(9, 6, 2009)
        settlement_date = self.calendar.advance(self.today, 2, Days)
        Settings().evaluation_date = self.today
        rates = [0.035, 0.035, 0.033, 0.034, 0.034, 0.036, 0.037, 0.039, 0.04]
        ts = [13, 41, 75, 165, 256, 345, 524, 703]
        dates = [settlement_date] + [self.calendar.advance(self.today, d, Days) for d in ts]
        self.day_counter = Actual360()
        self.term_structure = ZeroCurve(dates, rates, self.day_counter)
        self.spreads = [SimpleQuote(0.02), SimpleQuote(0.03)]
        self.spread_dates = [self.calendar.advance(self.today, 8, Months),
                             self.calendar.advance(self.today, 15, Months)]

        self.spreaded_term_structure = PiecewiseZeroSpreadedTermStructure(
            self.term_structure,
            self.spreads,
            self.spread_dates)
        self.spreaded_term_structure.extrapolation = True
예제 #3
0
    def test_zanette(self):
        """
        From paper by A. Zanette et al.
        """

        dc = Actual365Fixed()

        todays_date = today()
        settings = Settings()
        settings.evaluation_date = todays_date

        # constant yield and div curves

        dates = [todays_date + Period(i, Years) for i in range(3)]
        rates = [0.04 for i in range(3)]
        divRates = [0.03 for i in range(3)]
        r_ts = ZeroCurve(dates, rates, dc)
        q_ts = ZeroCurve(dates, divRates, dc)

        s0 = SimpleQuote(100)

        # Heston model

        v0 = .1
        kappa_v = 2
        theta_v = 0.1
        sigma_v = 0.3
        rho_sv = -0.5

        hestonProcess = HestonProcess(risk_free_rate_ts=r_ts,
                                      dividend_ts=q_ts,
                                      s0=s0,
                                      v0=v0,
                                      kappa=kappa_v,
                                      theta=theta_v,
                                      sigma=sigma_v,
                                      rho=rho_sv)

        hestonModel = HestonModel(hestonProcess)

        # Hull-White

        kappa_r = 1
        sigma_r = .2

        hullWhiteProcess = HullWhiteProcess(r_ts, a=kappa_r, sigma=sigma_r)

        strike = 100
        maturity = 1
        type = Call

        maturity_date = todays_date + Period(maturity, Years)

        exercise = EuropeanExercise(maturity_date)

        payoff = PlainVanillaPayoff(type, strike)

        option = VanillaOption(payoff, exercise)

        def price_cal(rho, tGrid):
            fd_hestonHwEngine = FdHestonHullWhiteVanillaEngine(
                hestonModel, hullWhiteProcess, rho, tGrid, 100, 40, 20, 0,
                True, FdmSchemeDesc.Hundsdorfer())
            option.set_pricing_engine(fd_hestonHwEngine)
            return option.npv

        calc_price = []
        for rho in [-0.5, 0, .5]:
            for tGrid in [50, 100, 150, 200]:
                tmp = price_cal(rho, tGrid)
                print("rho (S,r): %f Ns: %d Price: %f" % (rho, tGrid, tmp))
                calc_price.append(tmp)

        expected_price = [
            11.38,
        ] * 4 + [
            12.79,
        ] * 4 + [
            14.06,
        ] * 4

        np.testing.assert_almost_equal(calc_price, expected_price, 2)
예제 #4
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)
예제 #5
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)
예제 #6
0
                       forward=SimpleQuote(forward),
                       daycounter=daycounter)


dc = Actual365Fixed()

todays_date = today()
settings = Settings()
settings.evaluation_date = todays_date

# constant yield and div curves

dates = [todays_date + Period(i, Years) for i in range(3)]
rates = [0.04 for i in range(3)]
divRates = [0.03 for i in range(3)]
r_ts = ZeroCurve(dates, rates, dc)
q_ts = ZeroCurve(dates, divRates, dc)

s0 = SimpleQuote(100)

# Heston model

v0 = .1
kappa_v = 2
theta_v = 0.1
sigma_v = 0.3
rho_sv = -0.5

hestonProcess = HestonProcess(risk_free_rate_ts=r_ts,
                              dividend_ts=q_ts,
                              s0=s0,
    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 option_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(option_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)):

                        print("Failed to reproduce npv")
                        print("strike    : %f" % strike)
                        print("maturity  : %d" % maturity)
                        print("type      : %s" % option_type.name) 

                    self.assertAlmostEqual(expected, calculated,
                                            delta=tol)
예제 #8
0
class TestPiecewiseZeroSpreadedTermStructure(unittest.TestCase):

    def setUp(self):
        self.calendar = TARGET()
        self.today = Date(9, 6, 2009)
        settlement_date = self.calendar.advance(self.today, 2, Days)
        Settings().evaluation_date = self.today
        rates = [0.035, 0.035, 0.033, 0.034, 0.034, 0.036, 0.037, 0.039, 0.04]
        ts = [13, 41, 75, 165, 256, 345, 524, 703]
        dates = [settlement_date] + [self.calendar.advance(self.today, d, Days) for d in ts]
        self.day_counter = Actual360()
        self.term_structure = ZeroCurve(dates, rates, self.day_counter)
        self.spreads = [SimpleQuote(0.02), SimpleQuote(0.03)]
        self.spread_dates = [self.calendar.advance(self.today, 8, Months),
                             self.calendar.advance(self.today, 15, Months)]

        self.spreaded_term_structure = PiecewiseZeroSpreadedTermStructure(
            self.term_structure,
            self.spreads,
            self.spread_dates)
        self.spreaded_term_structure.extrapolation = True

    def test_flat_interpolation_left(self):
        interpolation_date = self.calendar.advance(self.today, 6, Months)
        t = self.day_counter.year_fraction(self.today, interpolation_date)
        interpolated_zero_rate = (self.spreaded_term_structure.
                                  zero_rate(t, compounding=Continuous).rate)

        expected_rate = self.term_structure.zero_rate(t, compounding=Continuous).rate + \
            self.spreads[0].value
        self.assertAlmostEqual(interpolated_zero_rate, expected_rate)

    def test_flat_interpolation_right(self):
        interpolation_date = self.calendar.advance(self.today, 20, Months)
        t = self.day_counter.year_fraction(self.today, interpolation_date)
        interpolated_zero_rate = (self.spreaded_term_structure.
                                  zero_rate(t, compounding=Continuous).rate)
        expected_rate = self.term_structure.zero_rate(t, compounding=Continuous).rate + \
            self.spreads[1].value
        self.assertAlmostEqual(interpolated_zero_rate, expected_rate)

    def test_linear_interpolation(self):
        interpolation_date = self.calendar.advance(self.today, 12, Months)
        t = self.term_structure.time_from_reference(interpolation_date)
        t1 = self.term_structure.time_from_reference(self.spread_dates[0])
        t2 = self.term_structure.time_from_reference(self.spread_dates[1])
        interpolated_zero_rate = (self.spreaded_term_structure.
                                  zero_rate(t, compounding=Continuous).rate)

        zero_rate = (self.term_structure.
                     zero_rate(t, compounding=Continuous, frequency=NoFrequency))
        expected_rate = zero_rate.rate + \
            (t - t1) / (t2 - t1 ) * self.spreads[1].value + \
            (t2 - t) / (t2 - t1) * self.spreads[0].value
        spreaded_rate = InterestRate(expected_rate,
                                     zero_rate.day_counter,
                                     zero_rate.compounding,
                                     zero_rate.frequency)

        self.assertAlmostEqual(interpolated_zero_rate,
                               spreaded_rate.equivalent_rate(Continuous, NoFrequency, t).rate)