def test_bucket_analysis_option(self): settings = Settings() calendar = TARGET() todays_date = Date(15, May, 1998) settlement_date = Date(17, May, 1998) settings.evaluation_date = todays_date option_type = Put underlying = 40 strike = 40 dividend_yield = 0.00 risk_free_rate = 0.001 volatility = 0.20 maturity = Date(17, May, 1999) daycounter = Actual365Fixed() underlyingH = SimpleQuote(underlying) payoff = PlainVanillaPayoff(option_type, strike) 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) european_exercise = EuropeanExercise(maturity) european_option = VanillaOption(payoff, european_exercise) analytic_european_engine = AnalyticEuropeanEngine( black_scholes_merton_process) european_option.set_pricing_engine(analytic_european_engine) ba_eo = bucket_analysis([[underlyingH]], [european_option], [1], 0.50, 1) self.assertTrue(2, ba_eo) self.assertTrue(type(tuple), ba_eo) self.assertEqual(1, len(ba_eo[0][0])) self.assertAlmostEqual(-0.4582666150152517, ba_eo[0][0][0])
def test_bucket_analysis_option(self): settings = Settings() calendar = TARGET() todays_date = Date(15, May, 1998) settlement_date = Date(17, May, 1998) settings.evaluation_date = todays_date option_type = Put underlying = 40 strike = 40 dividend_yield = 0.00 risk_free_rate = 0.001 volatility = SimpleQuote(0.20) maturity = Date(17, May, 1999) daycounter = Actual365Fixed() underlyingH = SimpleQuote(underlying) payoff = PlainVanillaPayoff(option_type, strike) 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) european_exercise = EuropeanExercise(maturity) european_option = VanillaOption(payoff, european_exercise) analytic_european_engine = AnalyticEuropeanEngine( black_scholes_merton_process) european_option.set_pricing_engine(analytic_european_engine) delta, gamma = bucket_analysis([underlyingH, volatility], [european_option], shift=1e-4, type=Centered) self.assertAlmostEqual(delta[0], european_option.delta) self.assertAlmostEqual(delta[1], european_option.vega) self.assertAlmostEqual(gamma[0], european_option.gamma, 5)
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)
def _get_option_npv(self): """ Suboptimal getter for the npv. FIXME: We currently have to recreate most of the objects because we do not expose enough of the QuantLib api. """ # convert datetime object to QlDate maturity = QlDate.from_datetime(self.maturity) underlyingH = SimpleQuote(self.underlying) # bootstrap the yield/dividend/vol curves flat_term_structure = FlatForward( reference_date = settlement_date, forward = self.risk_free_rate, daycounter = self.daycounter ) flat_dividend_ts = FlatForward( reference_date = settlement_date, forward = self.dividend_yield, daycounter = self.daycounter ) flat_vol_ts = BlackConstantVol( settlement_date, calendar, self.volatility, self.daycounter ) black_scholes_merton_process = BlackScholesMertonProcess( underlyingH, flat_dividend_ts, flat_term_structure,flat_vol_ts ) payoff = PlainVanillaPayoff(self.option_type, self.strike) european_exercise = EuropeanExercise(maturity) european_option = VanillaOption(payoff, european_exercise) analytic_european_engine = AnalyticEuropeanEngine(black_scholes_merton_process) european_option.set_pricing_engine(analytic_european_engine) return european_option.net_present_value
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)
def main(): # global data todays_date = Date(15, May, 1998) Settings.instance().evaluation_date = todays_date settlement_date = Date(17, May, 1998) risk_free_rate = FlatForward(reference_date=settlement_date, forward=0.06, daycounter=Actual365Fixed()) # option parameters exercise = AmericanExercise(earliest_exercise_date=settlement_date, latest_exercise_date=Date(17, May, 1999)) payoff = PlainVanillaPayoff(Put, 40.0) # market data underlying = SimpleQuote(36.0) volatility = BlackConstantVol(todays_date, TARGET(), 0.20, Actual365Fixed()) dividend_yield = FlatForward(reference_date=settlement_date, forward=0.00, daycounter=Actual365Fixed()) # report header = '%19s' % 'method' + ' |' + \ ' |'.join(['%17s' % tag for tag in ['value', 'estimated error', 'actual error']]) print() print(header) print('-' * len(header)) refValue = None def report(method, x, dx=None): e = '%.4f' % abs(x - refValue) x = '%.5f' % x if dx: dx = '%.4f' % dx else: dx = 'n/a' print('%19s' % method + ' |' + ' |'.join(['%17s' % y for y in [x, dx, e]])) # good to go process = BlackScholesMertonProcess(underlying, dividend_yield, risk_free_rate, volatility) option = VanillaOption(payoff, exercise) refValue = 4.48667344 report('reference value', refValue) # method: analytic option.set_pricing_engine(BaroneAdesiWhaleyApproximationEngine(process)) report('Barone-Adesi-Whaley', option.net_present_value) # method: finite differences time_steps = 801 grid_points = 800 option.set_pricing_engine( FDAmericanEngine('CrankNicolson', process, time_steps, grid_points)) report('finite differences', option.net_present_value) print('This is work in progress.') print('Some pricing engines are not yet interfaced.') return option.set_pricing_engine(BjerksundStenslandEngine(process)) report('Bjerksund-Stensland', option.NPV()) # method: binomial timeSteps = 801 option.setPricingEngine(BinomialVanillaEngine(process, 'jr', timeSteps)) report('binomial (JR)', option.NPV()) option.setPricingEngine(BinomialVanillaEngine(process, 'crr', timeSteps)) report('binomial (CRR)', option.NPV()) option.setPricingEngine(BinomialVanillaEngine(process, 'eqp', timeSteps)) report('binomial (EQP)', option.NPV()) option.setPricingEngine( BinomialVanillaEngine(process, 'trigeorgis', timeSteps)) report('bin. (Trigeorgis)', option.NPV()) option.setPricingEngine(BinomialVanillaEngine(process, 'tian', timeSteps)) report('binomial (Tian)', option.NPV()) option.setPricingEngine(BinomialVanillaEngine(process, 'lr', timeSteps)) report('binomial (LR)', option.NPV())
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) print('today: %s settlement: %s maturity: %s' % (todays_date, settlement_date, maturity)) print('NPV: %f\n' % european_option.net_present_value)
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