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_relinkable_structures(self): discounting_term_structure = YieldTermStructure() settlement_days = 3 flat_term_structure = FlatForward(settlement_days=settlement_days, forward=0.044, calendar=NullCalendar(), daycounter=Actual360()) discounting_term_structure.link_to(flat_term_structure) evaluation_date = Settings().evaluation_date +100 self.assertEqual( flat_term_structure.discount(evaluation_date), discounting_term_structure.discount(evaluation_date) ) another_flat_term_structure = FlatForward(settlement_days=10, forward=0.067, calendar=NullCalendar(), daycounter=Actual365Fixed()) discounting_term_structure.link_to(another_flat_term_structure) self.assertEqual( another_flat_term_structure.discount(evaluation_date), discounting_term_structure.discount(evaluation_date) ) self.assertNotEqual( flat_term_structure.discount(evaluation_date), discounting_term_structure.discount(evaluation_date) )
def flat_rate(rate, dc=Actual365Fixed(), reference_date=None): if reference_date is None: return FlatForward(settlement_days=0, calendar=NullCalendar(), forward=rate, daycounter=dc) else: return FlatForward(reference_date, rate, dc)
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 _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 create_helper(): calendar = TARGET() todays_date = Date(15, May, 2007) todays_date = calendar.adjust(todays_date) Settings.instance().evaluation_date = todays_date flat_rate = SimpleQuote(0.01) ts_curve = FlatForward(todays_date, flat_rate, Actual365Fixed()) recovery_rate = 0.5 quoted_spreads = 0.0150 tenor = Period(5, Years) helper = SpreadCdsHelper(quoted_spreads, tenor, 0, calendar, Quarterly, Following, Rule.TwentiethIMM, Actual365Fixed(), recovery_rate, ts_curve, model=PricingModel.Midpoint) return todays_date, helper
def test_excel_example_with_zero_coupon_bond(self): todays_date = Date(25, August, 2011) settlement_days = 3 face_amount = 100 calendar = TARGET() maturity_date = Date(26, February, 2024) bond = ZeroCouponBond(settlement_days, calendar, face_amount, maturity_date, Following, 100.0, todays_date) discounting_term_structure = YieldTermStructure(relinkable=True) flat_term_structure = FlatForward(settlement_days=1, forward=0.044, calendar=NullCalendar(), daycounter=Actual365Fixed(), compounding=Continuous, frequency=Annual) discounting_term_structure.link_to(flat_term_structure) engine = DiscountingBondEngine(discounting_term_structure) bond.set_pricing_engine(engine) self.assertEquals(calendar.advance(todays_date, 3, Days), bond.settlement_date()) self.assertEquals(0., bond.accrued_amount(bond.settlement_date())) self.assertAlmostEquals(57.6915, bond.clean_price, 4)
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_reference_evaluation_data_changed(self): """Testing term structure against evaluation date change... """ quote = SimpleQuote() term_structure = FlatForward(settlement_days=self.settlement_days, forward=quote, calendar=NullCalendar(), daycounter=Actual360()) quote.value = 0.03 expected = [] for days in [10, 30, 60, 120, 360, 720]: expected.append( term_structure.discount(self.adjusted_today + days) ) Settings().evaluation_date = self.adjusted_today + 30 calculated = [] for days in [10, 30, 60, 120, 360, 720]: calculated.append( term_structure.discount(self.adjusted_today+ 30 + days) ) for i, val in enumerate(expected): self.assertAlmostEqual(val, calculated[i])
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.assertEquals(t.length, 6) self.assertEquals(t.units, 2) self.assertEquals('USD Libor6M Actual/360', index.name)
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_creation(self): settlement_date = Date(1, January, 2014) term_structure = YieldTermStructure() term_structure.link_to( FlatForward(settlement_date, 0.05, Actual365Fixed())) index = USDLibor(Period(3, Months), term_structure) self.assertEqual(index.name, 'USDLibor3M Actual/360')
def test_creation(self): settlement_date = Date(1, January, 2014) term_structure = YieldTermStructure(relinkable=True) term_structure.link_to( FlatForward(settlement_date, 0.05, Actual365Fixed())) # Makes sure the constructor does not segfault anymore ;-) index = Euribor6M(term_structure) self.assertEquals(index.name, 'Euribor6M Actual/360')
def flat_rate(forward, daycounter): """ Create a flat yield curve, with rate defined according to the specified day-count convention. Used mostly for unit tests and simple illustrations. """ return FlatForward(forward=SimpleQuote(forward), settlement_days=0, calendar=NullCalendar(), daycounter=daycounter)
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_excel_example_with_fixed_rate_bond(self): '''Port the QuantLib Excel adding bond example to Python. ''' todays_date = Date(25, August, 2011) 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, Backward) issue_date = effective_date bond = FixedRateBond(settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], ActualActual(ISMA), Following, redemption, issue_date) discounting_term_structure = YieldTermStructure() flat_term_structure = FlatForward(settlement_days=1, forward=0.044, calendar=NullCalendar(), daycounter=Actual365Fixed(), compounding=Continuous, frequency=Annual) discounting_term_structure.link_to(flat_term_structure) engine = DiscountingBondEngine(discounting_term_structure) bond.set_pricing_engine(engine) self.assertEqual(Date(10, Jul, 2016), termination_date) self.assertEqual(calendar.advance(todays_date, 3, Days), bond.settlement_date()) self.assertEqual(Date(11, Jul, 2016), bond.maturity_date) self.assertAlmostEqual(0.6849, bond.accrued_amount(bond.settlement_date()), 4) self.assertAlmostEqual(102.1154, bond.clean_price, 4)
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_matrix = SwaptionVolatilityMatrix(calendar, Following, atm_option_tenors, atm_swap_tenors, M, Actual365Fixed()) term_structure = FlatForward(forward=0.05, settlement_days=2, calendar=calendar, daycounter=Actual365Fixed()) self.swap_index_base = EuriborSwapIsdaFixA(Period(2, Years), term_structure) self.short_swap_index_base = EuriborSwapIsdaFixA(Period(1, Years), term_structure) self.vega_weighted_smile_fit = False class Cube: def __init__(self): self.option_tenors = [Period(1, Years), Period(10, Years), Period(30, Years)] self.swap_tenors = [Period(2, Years), Period(10, Years), Period(30, Years)] self.strike_spreads = [-0.02, -0.005, 0, 0.005, 0.02] self.vol_spreads = np.array([[0.0599, 0.0049, 0.0000, -0.0001, 0.0127], [0.0729, 0.0086, 0.0000, -0.0024, 0.0098], [0.0738, 0.0102, 0.0000, -0.0039, 0.0065], [0.0465, 0.0063, 0.0000, -0.0032, -0.0010], [0.0558, 0.0084, 0.0000, -0.0050, -0.0057], [0.0576, 0.0083, 0.0000, -0.0043, -0.0014], [0.0437, 0.0059, 0.0000, -0.0030, -0.0006], [0.0533, 0.0078, 0.0000, -0.0045, -0.0046], [0.0545, 0.0079, 0.0000, -0.0042, -0.0020]]) self.vol_spreads_handle = [] for vs in self.vol_spreads: self.vol_spreads_handle.append([SimpleQuote(v) for v in vs]) self.cube = Cube()
class IndexManagerTestCase(unittest.TestCase): settlement_date = Date(1, January, 2014) term_structure = YieldTermStructure() term_structure.link_to(FlatForward(settlement_date, 0.05, Actual365Fixed())) index = USDLibor(Period(3, Months), term_structure) index.add_fixing(Date(5, 2, 2018), 1.79345) index.add_fixing(Date(2, 2, 2018), 1.78902) def test_index_manager_methods(self): self.assertIn(self.index.name.upper(), IndexManager.histories()) ts = IndexManager.get_history(self.index.name.upper()) self.assertEqual(ts[Date(5, 2, 2018)], 1.79345) self.assertEqual(ts[Date(2, 2, 2018)], 1.78902) IndexManager.clear_histories() self.assertFalse(IndexManager.get_history(self.index.name.upper()))
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_create_swap_index(self): term_structure = YieldTermStructure() term_structure.link_to( FlatForward(forward=0.05, daycounter=Actual365Fixed(), settlement_days=2, calendar=UnitedStates())) ibor_index = USDLibor(Period(3, Months), term_structure) index = SwapIndex('UsdLiborSwapIsdaFixAm', Period(10, Years), 2, USDCurrency(), UnitedStates(GovernmentBond), Period(6, Months), ModifiedFollowing, Thirty360(), ibor_index) index2 = UsdLiborSwapIsdaFixAm(Period(10, Years), term_structure) for attr in [ 'name', 'family_name', 'fixing_calendar', 'tenor', 'day_counter', 'currency' ]: self.assertEqual(getattr(index, attr), getattr(index2, attr))
def setUp(self): self.ref_date = Date(23, 2, 2018) Settings().evaluation_date = self.ref_date self.yts = FlatForward(self.ref_date, 0.02, Actual365Fixed()) self.swLn = ConstantSwaptionVolatility.from_reference_date( self.ref_date, TARGET(), Following, 0.2, Actual365Fixed(), VolatilityType.ShiftedLognormal, 0.) self.swSLn = ConstantSwaptionVolatility.from_reference_date( self.ref_date, TARGET(), Following, 0.1, Actual365Fixed(), VolatilityType.ShiftedLognormal, 0.01) self.swN = ConstantSwaptionVolatility.from_reference_date( self.ref_date, TARGET(), Following, 0.075, Actual365Fixed(), VolatilityType.Normal, 0.01) reversion = SimpleQuote(0.01) self.cms_pricer_ln = LinearTsrPricer(self.swLn, reversion, self.yts) self.cms_pricer_sln = LinearTsrPricer(self.swSLn, reversion, self.yts) self.cms_pricer_n = LinearTsrPricer(self.swN, reversion, self.yts) self.correlation = SimpleQuote(0.6) self.cms_spread_pricer_ln = LognormalCmsSpreadPricer(self.cms_pricer_ln, self.correlation, self.yts, 32) self.cms_spread_pricer_sln = LognormalCmsSpreadPricer(self.cms_pricer_sln, self.correlation, self.yts, 32) self.cms_spread_pricer_n = LognormalCmsSpreadPricer(self.cms_pricer_n, self.correlation, self.yts, 32)
def _bndprice(bond_yield, coupon_rate, pricing_date, maturity_date, period, basis, compounding_frequency): """ Clean price and accrued interest of a bond """ _period = str_to_frequency(period) evaluation_date = pydate_to_qldate(pricing_date) settings = Settings() settings.evaluation_date = evaluation_date calendar = TARGET() termination_date = pydate_to_qldate(maturity_date) # effective date must be before settlement date, but do not # care about exact issuance date of bond effective_date = Date(termination_date.day, termination_date.month, evaluation_date.year) effective_date = calendar.advance(effective_date, -1, Years, convention=Unadjusted) settlement_date = calendar.advance(evaluation_date, 2, Days, convention=ModifiedFollowing) face_amount = 100.0 redemption = 100.0 fixed_bond_schedule = Schedule(effective_date, termination_date, Period(_period), calendar, ModifiedFollowing, ModifiedFollowing, Backward) issue_date = effective_date cnt = DayCounter.from_name(basis) settlement_days = 2 bond = FixedRateBond(settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], cnt, Following, redemption, issue_date) discounting_term_structure = YieldTermStructure(relinkable=True) cnt_yield = DayCounter.from_name('Actual/Actual (Historical)') flat_term_structure = FlatForward(settlement_days=2, forward=bond_yield, calendar=NullCalendar(), daycounter=cnt_yield, compounding=Compounded, frequency=_period) discounting_term_structure.link_to(flat_term_structure) engine = DiscountingBondEngine(discounting_term_structure) bond.set_pricing_engine(engine) price = bond.clean_price ac = bond.accrued_amount(pydate_to_qldate(settlement_date)) return (price, ac)
settlement_days = 3 face_amount = 100.0 coupon_rate = 0.05 redemption = 100.0 fixed_bond_schedule = Schedule(effective_date, termination_date, Period(Annual), calendar, ModifiedFollowing, ModifiedFollowing, Backward) issue_date = effective_date bond = FixedRateBond(settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], ActualActual(ISMA), Following, redemption, issue_date) discounting_term_structure = YieldTermStructure(relinkable=True) flat_term_structure = FlatForward(settlement_days=1, forward=0.044, calendar=NullCalendar(), daycounter=Actual365Fixed(), compounding=Continuous, frequency=Annual) discounting_term_structure.link_to(flat_term_structure) pricing_engine = DiscountingBondEngine(discounting_term_structure) bond.set_pricing_engine(pricing_engine) print('Settlement date: ', bond.settlement_date()) print('Maturity date:', bond.maturity_date) print('Accrued amount: ', bond.accrued_amount(bond.settlement_date())) print('Clean price:', bond.clean_price)
def test_swap_QL(self): """ Test that a swap with fixed coupon = fair rate has an NPV=0 Create from QL objects """ nominal = 100.0 fixedConvention = Unadjusted floatingConvention = ModifiedFollowing fixedFrequency = Annual floatingFrequency = Semiannual fixedDayCount = Thirty360() floatDayCount = Thirty360() calendar = TARGET() settlement_days = 2 eval_date = Date(2, January, 2014) settings = Settings() settings.evaluation_date = eval_date settlement_date = calendar.advance(eval_date, settlement_days, Days) # must be a business day settlement_date = calendar.adjust(settlement_date) termStructure = YieldTermStructure(relinkable=True) termStructure.link_to( FlatForward(settlement_date, 0.05, Actual365Fixed())) index = Libor('USD Libor', Period(6, Months), settlement_days, USDCurrency(), calendar, Actual360(), termStructure) length = 5 fixedRate = .05 floatingSpread = 0.0 maturity = calendar.advance(settlement_date, length, Years, convention=floatingConvention) fixedSchedule = Schedule(settlement_date, maturity, Period(fixedFrequency), calendar, fixedConvention, fixedConvention, Rule.Forward, False) floatSchedule = Schedule(settlement_date, maturity, Period(floatingFrequency), calendar, floatingConvention, floatingConvention, Rule.Forward, False) engine = DiscountingSwapEngine(termStructure, False, settlement_date, settlement_date) for swap_type in [Payer, Receiver]: swap = VanillaSwap(swap_type, nominal, fixedSchedule, fixedRate, fixedDayCount, floatSchedule, index, floatingSpread, floatDayCount, fixedConvention) swap.set_pricing_engine(engine) fixed_leg = swap.fixed_leg floating_leg = swap.floating_leg f = swap.fair_rate print('fair rate: %f' % f) p = swap.net_present_value print('NPV: %f' % p) swap = VanillaSwap(swap_type, nominal, fixedSchedule, f, fixedDayCount, floatSchedule, index, floatingSpread, floatDayCount, fixedConvention) swap.set_pricing_engine(engine) p = swap.net_present_value print('NPV: %f' % p) self.assertAlmostEqual(p, 0)
def test_display(self): settings = Settings() # Date setup calendar = TARGET() # Settlement date settlement_date = calendar.adjust(Date(28, January, 2011)) # Evaluation date fixing_days = 1 settlement_days = 1 todays_date = calendar.advance( settlement_date, -fixing_days, Days ) settings.evaluation_date = todays_date # Bound attributes face_amount = 100.0 redemption = 100.0 issue_date = Date(27, January, 2011) maturity_date = Date(31, August, 2020) coupon_rate = 0.03625 bond_yield = 0.034921 flat_discounting_term_structure = YieldTermStructure() flat_term_structure = FlatForward( reference_date = settlement_date, forward = bond_yield, daycounter = Actual365Fixed(), #actual_actual.ActualActual(actual_actual.Bond), compounding = Compounded, frequency = Semiannual) # have a look at the FixedRateBondHelper to simplify this # construction flat_discounting_term_structure.link_to(flat_term_structure) #Rate fixed_bond_schedule = Schedule( issue_date, maturity_date, Period(Semiannual), UnitedStates(market=GOVERNMENTBOND), Unadjusted, Unadjusted, Backward, False); bond = FixedRateBond( settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], ActualActual(Bond), Unadjusted, redemption, issue_date ) d=bf.startDate(bond) zspd=bf.zSpread(bond, 100.0, flat_term_structure, Actual365Fixed(), Compounded, Semiannual, settlement_date, 1e-6, 100, 0.5) #Also need a test case for a PiecewiseTermStructure... 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(SimpleQuote(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(), YieldTermStructure(relinkable=False)) spread = SimpleQuote(0) fwdStart = Period(0, Days) for m, period, rate in swapData: helper = SwapRateHelper.from_tenor( 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 = PiecewiseYieldCurve.from_reference_date( BootstrapTrait.Discount, Interpolator.LogLinear, settlement_date, rate_helpers, ts_day_counter, tolerance) pyc_zspd=bf.zSpread(bond, 102.0, ts, ActualActual(ISDA), Compounded, Semiannual, Date(1, April, 2015), 1e-6, 100, 0.5) pyc_zspd_disco=bf.zSpread(bond, 95.0, ts, ActualActual(ISDA), Compounded, Semiannual, settlement_date, 1e-6, 100, 0.5) yld = bf.yld(bond, 102.0, ActualActual(ISDA), Compounded, Semiannual, settlement_date, 1e-6, 100, 0.5) dur = bf.duration(bond, yld, ActualActual(ISDA), Compounded, Semiannual, 2, settlement_date) yld_disco = bf.yld(bond, 95.0, ActualActual(ISDA), Compounded, Semiannual, settlement_date, 1e-6, 100, 0.5) dur_disco = bf.duration(bond, yld_disco, ActualActual(ISDA), Compounded, Semiannual, 2, settlement_date) self.assertEqual(round(zspd, 6), 0.001281) self.assertEqual(round(pyc_zspd, 4), -0.0264) self.assertEqual(round(pyc_zspd_disco, 4), -0.0114) self.assertEqual(round(yld, 4), 0.0338) self.assertEqual(round(yld_disco, 4), 0.0426) self.assertEqual(round(dur, 4), 8.0655) self.assertEqual(round(dur_disco, 4), 7.9702)
def test_pricing_bond(self): '''Inspired by the C++ code from http://quantcorner.wordpress.com/.''' settings = Settings() # Date setup calendar = TARGET() # Settlement date settlement_date = calendar.adjust(Date(28, January, 2011)) # Evaluation date fixing_days = 1 settlement_days = 1 todays_date = calendar.advance(settlement_date, -fixing_days, Days) settings.evaluation_date = todays_date # Bound attributes face_amount = 100.0 redemption = 100.0 issue_date = Date(27, January, 2011) maturity_date = Date(31, August, 2020) coupon_rate = 0.03625 bond_yield = 0.034921 discounting_term_structure = YieldTermStructure(relinkable=True) flat_term_structure = FlatForward( reference_date=settlement_date, forward=bond_yield, daycounter=Actual365Fixed( ), #actual_actual.ActualActual(actual_actual.Bond), compounding=Compounded, frequency=Semiannual) # have a look at the FixedRateBondHelper to simplify this # construction discounting_term_structure.link_to(flat_term_structure) #Rate fixed_bond_schedule = Schedule(issue_date, maturity_date, Period(Semiannual), UnitedStates(market=GOVERNMENTBOND), Unadjusted, Unadjusted, Backward, False) bond = FixedRateBond(settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], ActualActual(Bond), Unadjusted, redemption, issue_date) bond.set_pricing_engine(discounting_term_structure) # tests self.assertTrue(Date(27, January, 2011), bond.issue_date) self.assertTrue(Date(31, August, 2020), bond.maturity_date) self.assertTrue(settings.evaluation_date, bond.valuation_date) # the following assertion fails but must be verified self.assertAlmostEqual(101.1, bond.clean_price, 1) self.assertAlmostEqual(101.1, bond.net_present_value, 1) self.assertAlmostEqual(101.1, bond.dirty_price) self.assertAlmostEqual(0.009851, bond.accrued_amount()) print(settings.evaluation_date) print('Principal: {}'.format(face_amount)) print('Issuing date: {} '.format(bond.issue_date)) print('Maturity: {}'.format(bond.maturity_date)) print('Coupon rate: {:.4%}'.format(coupon_rate)) print('Yield: {:.4%}'.format(bond_yield)) print('Net present value: {:.4f}'.format(bond.net_present_value)) print('Clean price: {:.4f}'.format(bond.clean_price)) print('Dirty price: {:.4f}'.format(bond.dirty_price)) print('Accrued coupon: {:.6f}'.format(bond.accrued_amount())) print('Accrued coupon: {:.6f}'.format( bond.accrued_amount(Date(1, March, 2011))))
def test_excel_example_with_floating_rate_bond(self): todays_date = Date(25, August, 2011) 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_date = calendar.adjust(Date(28, January, 2011)) settlement_days = 3 #1 face_amount = 13749769.27 #2 coupon_rate = 0.05 redemption = 100.0 float_bond_schedule = Schedule(effective_date, termination_date, Period(Annual), calendar, ModifiedFollowing, ModifiedFollowing, Backward) #3 flat_discounting_term_structure = YieldTermStructure(relinkable=True) forecastTermStructure = YieldTermStructure(relinkable=True) dc = Actual360() ibor_index = Euribor6M(forecastTermStructure) #5 fixing_days = 2 #6 gearings = [1, 0.0] #7 spreads = [1, 0.05] #8 caps = [] #9 floors = [] #10 pmt_conv = ModifiedFollowing #11 issue_date = effective_date float_bond = FloatingRateBond(settlement_days, face_amount, float_bond_schedule, ibor_index, dc, fixing_days, gearings, spreads, caps, floors, pmt_conv, redemption, issue_date) flat_term_structure = FlatForward(settlement_days=1, forward=0.055, calendar=NullCalendar(), daycounter=Actual365Fixed(), compounding=Continuous, frequency=Annual) flat_discounting_term_structure.link_to(flat_term_structure) forecastTermStructure.link_to(flat_term_structure) engine = DiscountingBondEngine(flat_discounting_term_structure) float_bond.set_pricing_engine(engine) cons_option_vol = ConstantOptionletVolatility(settlement_days, UnitedStates(SETTLEMENT), pmt_conv, 0.95, Actual365Fixed()) coupon_pricer = BlackIborCouponPricer(cons_option_vol) set_coupon_pricer(float_bond, coupon_pricer) self.assertEquals(Date(10, Jul, 2016), termination_date) self.assertEquals(calendar.advance(todays_date, 3, Days), float_bond.settlement_date()) self.assertEquals(Date(11, Jul, 2016), float_bond.maturity_date) self.assertAlmostEqual( 0.6944, float_bond.accrued_amount(float_bond.settlement_date()), 4) self.assertAlmostEqual(98.2485, float_bond.dirty_price, 4) self.assertAlmostEqual(13500805.2469, float_bond.npv, 4)