def blsprice(spot, strike, risk_free_rate, time, volatility, option_type='Call', dividend=0.0): """ Black-Scholes option pricing model """ 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
def _blsimpv(price, spot, strike, risk_free_rate, time, option_type='Call', dividend=0.0): spot = SimpleQuote(spot) daycounter = ActualActual() 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 _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 test_settings_instance_method(self): Settings.instance().evaluation_date = today() self.assertEqual( today(), Settings.instance().evaluation_date )
def zero_curve(ts): days = range(10, 365*20, 30) dtMat = [calendar.advance(today(), d, Days) for d in days] df = np.array([ts.discount(dt) for dt in dtMat]) dtMat = [QLDateTodate(dt) for dt in dtMat] dtToday = QLDateTodate(today()) dt = np.array([(d-dtToday).days/365.0 for d in dtMat]) zc = -np.log(df) / dt return (dtMat, zc)
def zero_curve(ts): days = range(10, 365 * 20, 30) dtMat = [calendar.advance(today(), d, Days) for d in days] df = np.array([ts.discount(dt) for dt in dtMat]) dtMat = [QLDateTodate(dt) for dt in dtMat] dtToday = QLDateTodate(today()) dt = np.array([(d - dtToday).days / 365.0 for d in dtMat]) zc = -np.log(df) / dt return (dtMat, zc)
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): settlement_date = today() settings = Settings() settings.evaluation_date = settlement_date daycounter = ActualActual() self.calendar = NullCalendar() i_rate = .1 i_div = .04 self.risk_free_ts = flat_rate(i_rate, daycounter) self.dividend_ts = flat_rate(i_div, daycounter) self.s0 = SimpleQuote(32.0) # Bates model self.v0 = 0.05 self.kappa = 5.0 self.theta = 0.05 self.sigma = 1.0e-4 self.rho = 0.0 self.Lambda = .1 self.nu = .01 self.delta = .001
def test_create_libor_index(self): settings = Settings.instance() # Market information calendar = UnitedStates(LiborImpact) # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to(FlatForward(settlement_date, 0.05, Actual365Fixed())) index = Libor('USDLibor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), term_structure) default_libor = USDLibor(Period(6, Months)) for attribute in ["business_day_convention", "end_of_month", "fixing_calendar", "joint_calendar", "tenor", "fixing_days", "day_counter", "family_name", "name"]: self.assertEqual(getattr(index, attribute), getattr(default_libor, attribute))
def setUp(self): atm_option_tenors = [Period(1, Months), Period(6, Months)] + \ [Period(i, Years) for i in [1, 5, 10, 30]] atm_swap_tenors = [Period(1, Years), Period(5, Years), Period(10, Years), Period(30, Years)] m = np.array([[.1300, .1560, .1390, .1220], [.1440, .1580, .1460, .1260], [.1600, .1590, .1470, .1290], [.1640, .1470, .1370, .1220], [.1400, .1300, .1250, .1100], [.1130, .1090, .1070, .0930]]) M = Matrix.from_ndarray(m) calendar = UnitedStates() self.atm_vol = SwaptionVolatilityMatrix(calendar, Following, atm_option_tenors, atm_swap_tenors, M, Actual365Fixed()) reference_date = calendar.adjust(today()) Settings().evaluation_date = reference_date self.term_structure = FlatForward(reference_date, 0.05, Actual365Fixed()) self.swap_index = EuriborSwapIsdaFixA(Period(10, Years), forwarding=self.term_structure)
def test_create_libor_index(self): settings = Settings.instance() # Market information calendar = UnitedStates(LiborImpact) # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to( FlatForward(settlement_date, 0.05, Actual365Fixed())) index = Libor('USDLibor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), term_structure) default_libor = USDLibor(Period(6, Months)) for attribute in [ "business_day_convention", "end_of_month", "fixing_calendar", "joint_calendar", "tenor", "fixing_days", "day_counter", "family_name", "name" ]: self.assertEqual(getattr(index, attribute), getattr(default_libor, attribute))
def test_blsprice(self): from quantlib.settings import Settings from quantlib.time.api import today Settings.instance().evaluation_date = today() call_value = blsprice(100.0, 97.0, 0.1, 0.25, 0.5) self.assertAlmostEquals(call_value, 12.61, 2)
def test_create_swap_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date); ibor_index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360()) index = SwapIndex( 'family name', Period(3, Months), 10, USDCurrency(), TARGET(), Period(12, Months), Following, Actual360(), ibor_index) self.assertIsNotNone(index)
def test_create_libor_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to( FlatForward(settlement_date, 0.05, Actual365Fixed())) index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), term_structure) t = index.tenor self.assertEquals(t.length, 6) self.assertEquals(t.units, 2) self.assertEquals('USD Libor6M Actual/360', index.name)
def setUp(self): """""" self.today = today() self.settings = Settings() self.settings.evaluation_date = self.today self.dc = Actual365Fixed() self.spot = SimpleQuote(0.0) self.q_rate = SimpleQuote(0.0) self.q_ts = FlatForward(self.today, self.q_rate, self.dc) self.r_rate = SimpleQuote(0.0) self.r_ts = FlatForward(self.today, self.r_rate, self.dc) self.values = { 'type': SwapType.Long, 'strike': 0.04, 'nominal': 50000, 's': 100.0, 'q': 0.00, 'r': 0.05, 't': 0.246575, 'v': 0.20, 'result': 0.04189, 'tol': 1.0e-4, } self.spot.value = self.values['s'] self.q_rate.value = self.values['q'] self.r_rate.value = self.values['r'] self.ex_date = self.today + int(self.values['t'] * 365 + 0.5)
def test_create_swap_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to(FlatForward(settlement_date, 0.05, Actual365Fixed())) ibor_index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), term_structure) index = SwapIndex( 'family name', Period(3, Months), 10, USDCurrency(), TARGET(), Period(12, Months), Following, Actual360(), ibor_index) self.assertIsNotNone(index)
def test_create_swap_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to( FlatForward(settlement_date, 0.05, Actual365Fixed())) ibor_index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), term_structure) index = SwapIndex('family name', Period(3, Months), 10, USDCurrency(), TARGET(), Period(12, Months), Following, Actual360(), ibor_index) self.assertIsNotNone(index)
def test_create_libor_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to(FlatForward(settlement_date, 0.05, Actual365Fixed())) index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), term_structure) t = index.tenor self.assertEqual(t.length, 6) self.assertEqual(t.units, 2) self.assertEqual('USD Libor6M Actual/360', index.name)
def test_smith(self): # test against result published in # Journal of Computational Finance Vol. 11/1 Fall 2007 # An almost exact simulation method for the heston model settlement_date = today() self.settings.evaluation_date = settlement_date daycounter = ActualActual() timeToMaturity = 4 exercise_date = settlement_date + timeToMaturity * 365 c_payoff = PlainVanillaPayoff(Call, 100) exercise = EuropeanExercise(exercise_date) risk_free_ts = flat_rate(0., daycounter) dividend_ts = flat_rate(0., daycounter) s0 = SimpleQuote(100.0) v0 = 0.0194 kappa = 1.0407 theta = 0.0586 sigma = 0.5196 rho = -.6747 nb_steps_a = 100 nb_paths = 20000 seed = 12347 process = HestonProcess(risk_free_ts, dividend_ts, s0, v0, kappa, theta, sigma, rho, QUADRATICEXPONENTIAL) model = HestonModel(process) option = VanillaOption(c_payoff, exercise) engine = AnalyticHestonEngine(model, 144) option.set_pricing_engine(engine) price_fft = option.net_present_value engine = MCEuropeanHestonEngine(process, antithetic_variate=True, steps_per_year=nb_steps_a, required_samples=nb_paths, seed=seed) option.set_pricing_engine(engine) price_mc = option.net_present_value expected = 15.1796 tolerance = .05 self.assertAlmostEqual(price_fft, expected, delta=tolerance) self.assertAlmostEqual(price_mc, expected, delta=tolerance)
def test_creation(self): settings = Settings() # Market information calendar = TARGET() # must be a business day settings.evaluation_date = calendar.adjust(today()) settlement_date = Date(18, September, 2008) # must be a business day settlement_date = calendar.adjust(settlement_date); quotes = [SimpleQuote(0.0096), SimpleQuote(0.0145), SimpleQuote(0.0194)] tenors = [3, 6, 12] rate_helpers = [] calendar = TARGET() deposit_day_counter = Actual365Fixed() convention = ModifiedFollowing end_of_month = True for quote, month in zip(quotes, tenors): tenor = Period(month, Months) fixing_days = 3 helper = DepositRateHelper( quote, tenor, fixing_days, calendar, convention, end_of_month, deposit_day_counter ) rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date( settlement_date, rate_helpers, ts_day_counter, accuracy=tolerance ) self.assertIsNotNone(ts) self.assertEqual( Date(18, September, 2008), ts.reference_date) # this is not a real test ... self.assertAlmostEqual(0.9975, ts.discount(Date(21, 12, 2008)), 4) self.assertAlmostEqual(0.9944, ts.discount(Date(21, 4, 2009)), 4) self.assertAlmostEqual(0.9904, ts.discount(Date(21, 9, 2009)), 4) dates, dfs = zip(*ts.nodes) self.assertAlmostEqual(list(dates), ts.dates) self.assertAlmostEqual(list(dfs), ts.data)
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
def test_analytic_versus_black(self): settlement_date = today() self.settings.evaluation_date = settlement_date daycounter = ActualActual() exercise_date = settlement_date + 6 * Months payoff = PlainVanillaPayoff(Put, 30) exercise = EuropeanExercise(exercise_date) risk_free_ts = flat_rate(0.1, daycounter) dividend_ts = flat_rate(0.04, daycounter) s0 = SimpleQuote(32.0) v0 = 0.05 kappa = 5.0 theta = 0.05 sigma = 1.0e-4 rho = 0.0 process = HestonProcess( risk_free_ts, dividend_ts, s0, v0, kappa, theta, sigma, rho ) option = VanillaOption(payoff, exercise) engine = AnalyticHestonEngine(HestonModel(process), 144) option.set_pricing_engine(engine) calculated = option.net_present_value year_fraction = daycounter.year_fraction( settlement_date, exercise_date ) forward_price = 32 * np.exp((0.1 - 0.04) * year_fraction) expected = blackFormula( payoff.type, payoff.strike, forward_price, np.sqrt(0.05 * year_fraction) ) * np.exp(-0.1 * year_fraction) tolerance = 2.0e-7 self.assertAlmostEqual( calculated, expected, delta=tolerance )
def test_creation(self): settings = Settings() # Market information calendar = TARGET() # must be a business day settings.evaluation_date = calendar.adjust(today()) settlement_date = Date(18, September, 2008) # must be a business day settlement_date = calendar.adjust(settlement_date); quotes = [0.0096, 0.0145, 0.0194] tenors = [3, 6, 12] rate_helpers = [] calendar = TARGET() deposit_day_counter = Actual365Fixed() convention = ModifiedFollowing end_of_month = True for quote, month in zip(quotes, tenors): tenor = Period(month, Months) fixing_days = 3 helper = DepositRateHelper( quote, tenor, fixing_days, calendar, convention, end_of_month, deposit_day_counter ) rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 ts = term_structure_factory( 'discount', 'loglinear', settlement_date, rate_helpers, ts_day_counter, tolerance ) self.assertIsNotNone(ts) self.assertEquals( Date(18, September, 2008), ts.reference_date) # this is not a real test ... self.assertAlmostEquals(0.9975, ts.discount(Date(21, 12, 2008)), 4) self.assertAlmostEquals(0.9944, ts.discount(Date(21, 4, 2009)), 4) self.assertAlmostEquals(0.9904, ts.discount(Date(21, 9, 2009)), 4)
def test_creation(self): settings = Settings() # Market information calendar = TARGET() # must be a business day settings.evaluation_date = calendar.adjust(today()) settlement_date = Date(18, September, 2008) # must be a business day settlement_date = calendar.adjust(settlement_date); quotes = [SimpleQuote(0.0096), SimpleQuote(0.0145), SimpleQuote(0.0194)] tenors = [3, 6, 12] rate_helpers = [] calendar = TARGET() deposit_day_counter = Actual365Fixed() convention = ModifiedFollowing end_of_month = True for quote, month in zip(quotes, tenors): tenor = Period(month, Months) fixing_days = 3 helper = DepositRateHelper( quote, tenor, fixing_days, calendar, convention, end_of_month, deposit_day_counter ) rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve.from_reference_date( BootstrapTrait.Discount, Interpolator.LogLinear, settlement_date, rate_helpers, ts_day_counter, tolerance ) self.assertIsNotNone(ts) self.assertEqual( Date(18, September, 2008), ts.reference_date) # this is not a real test ... self.assertAlmostEqual(0.9975, ts.discount(Date(21, 12, 2008)), 4) self.assertAlmostEqual(0.9944, ts.discount(Date(21, 4, 2009)), 4) self.assertAlmostEqual(0.9904, ts.discount(Date(21, 9, 2009)), 4)
def test_using_settings(self): settings = Settings() evaluation_date = today() # have to set the evaluation date before the test as it is a global # attribute for the whole library ... meaning that previous test_cases # might have set this to another date settings.evaluation_date = evaluation_date self.assertEqual(settings.evaluation_date, evaluation_date) self.assertTrue(settings.version.startswith('1'))
def test_bond_schedule_today(self): '''Test date calculations and role of settings when evaluation date set to current date. ''' todays_date = today() settings = Settings() settings.evaluation_date = todays_date calendar = TARGET() effective_date = Date(10, Jul, 2006) termination_date = calendar.advance( effective_date, 10, Years, convention=Unadjusted) settlement_days = 3 face_amount = 100.0 coupon_rate = 0.05 redemption = 100.0 fixed_bond_schedule = Schedule.from_rule( effective_date, termination_date, Period(Annual), calendar, ModifiedFollowing, ModifiedFollowing, Rule.Backward ) issue_date = effective_date bond = FixedRateBond( settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], ActualActual(ISMA), Following, redemption, issue_date ) self.assertEqual( calendar.advance(todays_date, 3, Days), bond.settlement_date())
def setUp(self): calendar = TARGET() today_date = today() Settings().evaluation_date = today_date hazard_rate = SimpleQuote(0.01234) probability_curve = FlatHazardRate(0, calendar, hazard_rate, Actual360()) discount_curve = FlatForward(today_date, 0.06, Actual360()) issue_date = today_date #calendar.advance(today_date, -1, Years) maturity = calendar.advance(issue_date, 10, Years) self.convention = Following self.schedule = Schedule(issue_date, maturity, Period("3M"), calendar, self.convention, self.convention, Rule.TwentiethIMM) recovery_rate = 0.4 self.engine = MidPointCdsEngine(probability_curve, recovery_rate, discount_curve, True)
def test_simulate_heston_1(self): settings = self.settings settlement_date = today() settings.evaluation_date = settlement_date # simulate Heston paths paths = 4 steps = 10 horizon = 1 seed = 12345 grid = TimeGrid(horizon, steps) res = simulate_process(self.heston_process, paths, grid, seed) time = list(grid) time_expected = np.arange(0, 1.1, .1) np.testing.assert_array_almost_equal(time, time_expected, decimal=4)
def test_create_libor_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) index = Libor("USD Libor", Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360()) self.assertEquals("USD Libor6M Actual/360", index.name)
def test_create_libor_index(self): settings = Settings.instance() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360()) self.assertEquals('USD Libor6M Actual/360', index.name)
def test_simulate_heston_1(self): settings = self.settings settlement_date = today() settings.evaluation_date = settlement_date # simulate Heston paths paths = 4 steps = 10 horizon = 1 seed = 12345 model = HestonModel(self.heston_process) res = simulate_model(model, paths, steps, horizon, seed) time = res[0, :] time_expected = np.arange(0, 1.1, .1) simulations = res[1:, :].T np.testing.assert_array_almost_equal(time, time_expected, decimal=4)
def test_simulate_heston_1(self): settings = self.settings settlement_date = today() settings.evaluation_date = settlement_date # simulate Heston paths paths = 4 steps = 10 horizon = 1 seed = 12345 model = HestonModel(self.heston_process) res = simulateHeston(model, paths, steps, horizon, seed) time = res[0, :] time_expected = np.arange(0, 1.1, 0.1) simulations = res[1:, :].T np.testing.assert_array_almost_equal(time, time_expected, decimal=4)
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)
# The Heston Process # ------------------ # <codecell> def flat_rate(forward, daycounter): return FlatForward( quote = SimpleQuote(forward), settlement_days = 0, calendar = NullCalendar(), daycounter = daycounter ) settings = Settings.instance() settlement_date = today() settings.evaluation_date = settlement_date daycounter = ActualActual() calendar = NullCalendar() interest_rate = .1 dividend_yield = .04 risk_free_ts = flat_rate(interest_rate, daycounter) dividend_ts = flat_rate(dividend_yield, daycounter) s0 = SimpleQuote(100.0) # Heston model
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)
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)
def test_black_calibration(self): # calibrate a Heston model to a constant volatility surface without # smile. expected result is a vanishing volatility of the volatility. # In addition theta and v0 should be equal to the constant variance todays_date = today() self.settings.evaluation_date = todays_date daycounter = Actual360() calendar = NullCalendar() risk_free_ts = flat_rate(0.04, daycounter) dividend_ts = flat_rate(0.50, daycounter) option_maturities = [ Period(1, Months), Period(2, Months), Period(3, Months), Period(6, Months), Period(9, Months), Period(1, Years), Period(2, Years) ] options = [] s0 = SimpleQuote(1.0) vol = SimpleQuote(0.1) volatility = vol.value for maturity in option_maturities: for moneyness in np.arange(-1.0, 2.0, 1.): tau = daycounter.year_fraction( risk_free_ts.reference_date, calendar.advance( risk_free_ts.reference_date, period=maturity) ) forward_price = s0.value * dividend_ts.discount(tau) / \ risk_free_ts.discount(tau) strike_price = forward_price * np.exp( -moneyness * volatility * np.sqrt(tau) ) options.append( HestonModelHelper( maturity, calendar, s0.value, strike_price, vol, risk_free_ts, dividend_ts ) ) for sigma in np.arange(0.1, 0.7, 0.2): v0 = 0.01 kappa = 0.2 theta = 0.02 rho = -0.75 process = HestonProcess( risk_free_ts, dividend_ts, s0, v0, kappa, theta, sigma, rho ) self.assertEqual(v0, process.v0) self.assertEqual(kappa, process.kappa) self.assertEqual(theta, process.theta) self.assertEqual(sigma, process.sigma) self.assertEqual(rho, process.rho) self.assertEqual(1.0, process.s0().value) model = HestonModel(process) engine = AnalyticHestonEngine(model, 96) for option in options: option.set_pricing_engine(engine) optimisation_method = LevenbergMarquardt(1e-8, 1e-8, 1e-8) end_criteria = EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8) model.calibrate(options, optimisation_method, end_criteria) tolerance = 3.0e-3 self.assertFalse(model.sigma > tolerance) self.assertAlmostEqual( model.kappa * model.theta, model.kappa * volatility ** 2, delta=tolerance ) self.assertAlmostEqual(model.v0, volatility ** 2, delta=tolerance)
from quantlib.pricingengines.vanilla import AnalyticEuropeanEngine from quantlib.processes.black_scholes_process import BlackScholesMertonProcess from quantlib.quotes import SimpleQuote from quantlib.settings import Settings from quantlib.time.api import TARGET, Actual365Fixed, today, Date as QlDate from quantlib.termstructures.yields.api import FlatForward from quantlib.termstructures.volatility.equityfx.black_vol_term_structure \ import BlackConstantVol settings = Settings.instance() calendar = TARGET() offset = 366 todays_date = today() - offset settlement_date = todays_date + 2 settings.evaluation_date = todays_date class OptionValuation(HasTraits): # options parameters option_type = Enum(Put, Call) underlying = Float(36) strike = Float(40) dividend_yield = Range(0.0, 0.5) risk_free_rate = Range(0.0, 0.2) volatility = Range(0.0, 0.5) maturity = Date(datetime.date.today())
def test_bates_det_jump(self): # this looks like a bug in QL: # Bates Det Jump model does not have sigma as parameter, yet # changing sigma changes the result! settlement_date = today() self.settings.evaluation_date = settlement_date daycounter = ActualActual() exercise_date = settlement_date + 6 * Months payoff = PlainVanillaPayoff(Put, 1290) exercise = EuropeanExercise(exercise_date) option = VanillaOption(payoff, exercise) risk_free_ts = flat_rate(0.02, daycounter) dividend_ts = flat_rate(0.04, daycounter) spot = 1290 ival = {'delta': 3.6828677022272715e-06, 'kappa': 19.02581428347027, 'kappaLambda': 1.1209758060939223, 'lambda': 0.06524550732595163, 'nu': -1.8968106563601956, 'rho': -0.7480898462264719, 'sigma': 1.0206363887835108, 'theta': 0.01965384459461113, 'thetaLambda': 0.028915397380738218, 'v0': 0.06566800935242285} process = BatesProcess( risk_free_ts, dividend_ts, SimpleQuote(spot), ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model = BatesDetJumpModel(process, ival['kappaLambda'], ival['thetaLambda']) engine = BatesDetJumpEngine(model, 64) option.set_pricing_engine(engine) calc_1 = option.net_present_value ival['sigma'] = 1.e-6 process = BatesProcess( risk_free_ts, dividend_ts, SimpleQuote(spot), ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model = BatesDetJumpModel(process, ival['kappaLambda'], ival['thetaLambda']) engine = BatesDetJumpEngine(model, 64) option.set_pricing_engine(engine) calc_2 = option.net_present_value if(abs(calc_1-calc_2) > 1.e-5): print('calc 1 %f calc 2 %f' % (calc_1, calc_2)) self.assertNotEqual(calc_1, calc_2)
def test_smith(self): # test against result published in # Journal of Computational Finance Vol. 11/1 Fall 2007 # An almost exact simulation method for the heston model settlement_date = today() self.settings.evaluation_date = settlement_date daycounter = ActualActual() timeToMaturity = 4 exercise_date = settlement_date + timeToMaturity * 365 c_payoff = PlainVanillaPayoff(Call, 100) exercise = EuropeanExercise(exercise_date) risk_free_ts = flat_rate(0., daycounter) dividend_ts = flat_rate(0., daycounter) s0 = SimpleQuote(100.0) v0 = 0.0194 kappa = 1.0407 theta = 0.0586 sigma = 0.5196 rho = -.6747 nb_steps_a = 100 nb_paths = 20000 seed = 12347 process = HestonProcess( risk_free_ts, dividend_ts, s0, v0, kappa, theta, sigma, rho, QUADRATICEXPONENTIAL) model = HestonModel(process) option = VanillaOption(c_payoff, exercise) engine = AnalyticHestonEngine(model, 144) option.set_pricing_engine(engine) price_fft = option.net_present_value engine = MCVanillaEngine( trait='MCEuropeanHestonEngine', generator='PseudoRandom', process=process, doAntitheticVariate=True, stepsPerYear=nb_steps_a, requiredSamples=nb_paths, seed=seed) option.set_pricing_engine(engine) price_mc = option.net_present_value expected = 15.1796 tolerance = .05 self.assertAlmostEqual(price_fft, expected, delta=tolerance) self.assertAlmostEqual(price_mc, expected, delta=tolerance)
def test_black_calibration(self): # calibrate a Heston model to a constant volatility surface without # smile. expected result is a vanishing volatility of the volatility. # In addition theta and v0 should be equal to the constant variance todays_date = today() self.settings.evaluation_date = todays_date daycounter = Actual360() calendar = NullCalendar() risk_free_ts = flat_rate(0.04, daycounter) dividend_ts = flat_rate(0.50, daycounter) option_maturities = [ Period(1, Months), Period(2, Months), Period(3, Months), Period(6, Months), Period(9, Months), Period(1, Years), Period(2, Years) ] options = [] s0 = SimpleQuote(1.0) vol = SimpleQuote(0.1) volatility = vol.value for maturity in option_maturities: for moneyness in np.arange(-1.0, 2.0, 1.): tau = daycounter.year_fraction( risk_free_ts.reference_date, calendar.advance( risk_free_ts.reference_date, period=maturity) ) forward_price = s0.value * dividend_ts.discount(tau) / \ risk_free_ts.discount(tau) strike_price = forward_price * np.exp( -moneyness * volatility * np.sqrt(tau) ) options.append( HestonModelHelper( maturity, calendar, s0.value, strike_price, vol, risk_free_ts, dividend_ts ) ) for sigma in np.arange(0.1, 0.7, 0.2): v0 = 0.01 kappa = 0.2 theta = 0.02 rho = -0.75 process = HestonProcess( risk_free_ts, dividend_ts, s0, v0, kappa, theta, sigma, rho ) self.assertEqual(v0, process.v0) self.assertEqual(kappa, process.kappa) self.assertEqual(theta, process.theta) self.assertEqual(sigma, process.sigma) self.assertEqual(rho, process.rho) self.assertEqual(1.0, process.s0.value) model = HestonModel(process) engine = AnalyticHestonEngine(model, 96) for option in options: option.set_pricing_engine(engine) optimisation_method = LevenbergMarquardt(1e-8, 1e-8, 1e-8) end_criteria = EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8) model.calibrate(options, optimisation_method, end_criteria) tolerance = 3.0e-3 self.assertFalse(model.sigma > tolerance) self.assertAlmostEqual( model.kappa * model.theta, model.kappa * volatility ** 2, delta=tolerance ) self.assertAlmostEqual(model.v0, volatility ** 2, delta=tolerance)
def test_deposit_swap(self): settings = Settings() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date); depositData = [[ 1, Months, 4.581 ], [ 2, Months, 4.573 ], [ 3, Months, 4.557 ], [ 6, Months, 4.496 ], [ 9, Months, 4.490 ]] swapData = [[ 1, Years, 4.54 ], [ 5, Years, 4.99 ], [ 10, Years, 5.47 ], [ 20, Years, 5.89 ], [ 30, Years, 5.96 ]] rate_helpers = [] end_of_month = True for m, period, rate in depositData: tenor = Period(m, Months) helper = DepositRateHelper(rate/100, tenor, settlement_days, calendar, ModifiedFollowing, end_of_month, Actual360()) rate_helpers.append(helper) liborIndex = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360()) spread = SimpleQuote(0) fwdStart = Period(0, Days) for m, period, rate in swapData: rate = SimpleQuote(rate/100) helper = SwapRateHelper(rate, Period(m, Years), calendar, Annual, Unadjusted, Thirty360(), liborIndex, spread, fwdStart) rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 ts = term_structure_factory( 'discount', 'loglinear', settlement_date, rate_helpers, ts_day_counter, tolerance) # this is not a real test ... self.assertAlmostEquals(0.9103, ts.discount(calendar.advance(today(), 2, Years)),3) self.assertAlmostEquals(0.7836, ts.discount(calendar.advance(today(), 5, Years)),3) self.assertAlmostEquals(0.5827, ts.discount(calendar.advance(today(), 10, Years)),3) self.assertAlmostEquals(0.4223, ts.discount(calendar.advance(today(), 15, Years)),3)
def get_term_structure(df_libor, dtObs): settings = Settings() # Market information calendar = TARGET() # must be a business day eval_date = calendar.adjust(today()) settings.evaluation_date = eval_date settlement_days = 2 settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date); depositData =[[1, Months, 'Libor1M'], [3, Months, 'Libor3M'], [6, Months, 'Libor6M']] swapData = [[ 1, Years, 'Swap1Y'], [ 2, Years, 'Swap2Y'], [ 3, Years, 'Swap3Y'], [ 4, Years, 'Swap4Y'], [ 5, Years, 'Swap5Y'], [ 7, Years, 'Swap7Y'], [ 10, Years,'Swap10Y'], [ 30, Years,'Swap30Y']] rate_helpers = [] end_of_month = True for m, period, label in depositData: tenor = Period(m, Months) rate = df_libor.get_value(dtObs, label) helper = DepositRateHelper(float(rate/100), tenor, settlement_days, calendar, ModifiedFollowing, end_of_month, Actual360()) rate_helpers.append(helper) endOfMonth = True liborIndex = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, ModifiedFollowing, endOfMonth, Actual360()) spread = SimpleQuote(0) fwdStart = Period(0, Days) for m, period, label in swapData: rate = df_libor.get_value(dtObs, label) helper = SwapRateHelper(SimpleQuote(rate/100), Period(m, Years), calendar, Annual, Unadjusted, Thirty360(), liborIndex, spread, fwdStart) rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 ts = term_structure_factory( 'discount', 'loglinear', settlement_date, rate_helpers, ts_day_counter, tolerance) return ts
def test_zero_curve_on_swap_index(self): todays_date = today() calendar = UnitedStates() # INPUT dayCounter = Actual360() # INPUT currency = USDCurrency() # INPUT Settings.instance().evaluation_date = todays_date settlement_days = 2 settlement_date = calendar.advance( todays_date, period=Period(settlement_days, Days) ) liborRates = [ SimpleQuote(0.002763), SimpleQuote(0.004082), SimpleQuote(0.005601), SimpleQuote(0.006390), SimpleQuote(0.007125), SimpleQuote(0.007928), SimpleQuote(0.009446), SimpleQuote(0.01110)] liborRatesTenor = [Period(tenor, Months) for tenor in [1,2,3,4,5,6,9,12]] Libor_dayCounter = Actual360(); swapRates = [SimpleQuote(0.005681), SimpleQuote(0.006970), SimpleQuote(0.009310), SimpleQuote(0.012010), SimpleQuote(0.014628), SimpleQuote(0.016881), SimpleQuote(0.018745), SimpleQuote(0.020260), SimpleQuote(0.021545)] swapRatesTenor = [Period(i, Years) for i in range(2, 11)] # description of the fixed leg of the swap Swap_fixedLegTenor = Period(12, Months) # INPUT Swap_fixedLegConvention = ModifiedFollowing # INPUT Swap_fixedLegDayCounter = Actual360() # INPUT # description of the float leg of the swap Swap_iborIndex = Libor( "USDLibor", Period(3, Months), settlement_days, USDCurrency(), UnitedStates(), Actual360() ) SwapFamilyName = currency.name + "swapIndex" instruments = [] # ++++++++++++++++++++ Creation of the vector of RateHelper (need for the Yield Curve construction) # ++++++++++++++++++++ Libor LiborFamilyName = currency.name + "Libor" instruments = [] for rate, tenor in zip(liborRates, liborRatesTenor): # Index description ___ creation of a Libor index liborIndex = Libor( LiborFamilyName, tenor, settlement_days, currency, calendar, Libor_dayCounter ) # Initialize rate helper # the DepositRateHelper link the recording rate with the Libor # index instruments.append(DepositRateHelper(rate, index=liborIndex)) for tenor, rate in zip(swapRatesTenor, swapRates): # swap description ___ creation of a swap index. The floating leg is described in the index 'Swap_iborIndex' swapIndex = SwapIndex ( SwapFamilyName, tenor, settlement_days, currency, calendar, Swap_fixedLegTenor, Swap_fixedLegConvention, Swap_fixedLegDayCounter, Swap_iborIndex ) # Initialize rate helper __ the SwapRateHelper links the swap index width his rate instruments.append(SwapRateHelper.from_index(rate,swapIndex)) # ++++++++++++++++++ Now the creation of the yield curve tolerance = 1.0e-15 ts = PiecewiseYieldCurve.from_reference_date( BootstrapTrait.ZeroYield, Interpolator.Linear, settlement_date, instruments, dayCounter, tolerance ) self.assertEqual(settlement_date, ts.reference_date)
# The Heston Process # ------------------ # <codecell> def flat_rate(forward, daycounter): return FlatForward( forward=SimpleQuote(forward), settlement_days=0, calendar=NullCalendar(), daycounter=daycounter ) settings = Settings.instance() settlement_date = today() settings.evaluation_date = settlement_date daycounter = ActualActual() calendar = NullCalendar() interest_rate = .1 dividend_yield = .04 risk_free_ts = flat_rate(interest_rate, daycounter) dividend_ts = flat_rate(dividend_yield, daycounter) s0 = SimpleQuote(100.0) # Heston model
def test_zero_curve_on_swap_index(self): todays_date = today() calendar = UnitedStates() # INPUT dayCounter = Actual360() # INPUT currency = USDCurrency() # INPUT Settings.instance().evaluation_date = todays_date settlement_days = 2 settlement_date = calendar.advance( todays_date, period=Period(settlement_days, Days) ) liborRates = [ SimpleQuote(0.002763), SimpleQuote(0.004082), SimpleQuote(0.005601), SimpleQuote(0.006390), SimpleQuote(0.007125), SimpleQuote(0.007928), SimpleQuote(0.009446), SimpleQuote(0.01110)] liborRatesTenor = [Period(tenor, Months) for tenor in [1,2,3,4,5,6,9,12]] Libor_dayCounter = Actual360(); swapRates = [SimpleQuote(0.005681), SimpleQuote(0.006970), SimpleQuote(0.009310), SimpleQuote(0.012010), SimpleQuote(0.014628), SimpleQuote(0.016881), SimpleQuote(0.018745), SimpleQuote(0.020260), SimpleQuote(0.021545)] swapRatesTenor = [Period(i, Years) for i in range(2, 11)] # description of the fixed leg of the swap Swap_fixedLegTenor = Period(12, Months) # INPUT Swap_fixedLegConvention = ModifiedFollowing # INPUT Swap_fixedLegDayCounter = Actual360() # INPUT # description of the float leg of the swap Swap_iborIndex = Libor( "USDLibor", Period(3, Months), settlement_days, USDCurrency(), UnitedStates(), Actual360() ) SwapFamilyName = currency.name + "swapIndex" instruments = [] # ++++++++++++++++++++ Creation of the vector of RateHelper (need for the Yield Curve construction) # ++++++++++++++++++++ Libor LiborFamilyName = currency.name + "Libor" instruments = [] for rate, tenor in zip(liborRates, liborRatesTenor): # Index description ___ creation of a Libor index liborIndex = Libor( LiborFamilyName, tenor, settlement_days, currency, calendar, Libor_dayCounter ) # Initialize rate helper # the DepositRateHelper link the recording rate with the Libor # index instruments.append(DepositRateHelper(rate, index=liborIndex)) for tenor, rate in zip(swapRatesTenor, swapRates): # swap description ___ creation of a swap index. The floating leg is described in the index 'Swap_iborIndex' swapIndex = SwapIndex ( SwapFamilyName, tenor, settlement_days, currency, calendar, Swap_fixedLegTenor, Swap_fixedLegConvention, Swap_fixedLegDayCounter, Swap_iborIndex ) # Initialize rate helper __ the SwapRateHelper links the swap index width his rate instruments.append(SwapRateHelper.from_index(rate,swapIndex)) # ++++++++++++++++++ Now the creation of the yield curve tolerance = 1.0e-15 ts = PiecewiseYieldCurve( 'zero', 'linear', settlement_date, instruments, dayCounter, tolerance ) self.assertEqual(settlement_date, ts.reference_date)