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.assertEqual( calendar.advance(todays_date, 3, Days), bond.settlement_date() ) self.assertEqual(0., bond.accrued_amount(bond.settlement_date())) self.assertAlmostEqual(57.6915, bond.clean_price, 4)
def test_christmas_is_holiday(self): calendar = TARGET() date = Date(24, 12, 2011) self.assertTrue(calendar.is_holiday(date))
def test_christmas_is_holiday(self): calendar = TARGET() date = Date(24,12, 2011) self.assertTrue(calendar.is_holiday(date))
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.assertEqual(calendar.advance(todays_date, 3, Days), bond.settlement_date()) self.assertEqual(0., bond.accrued_amount(bond.settlement_date())) self.assertAlmostEqual(57.6915, bond.clean_price, 4)
class FlatForwardTestCase(unittest.TestCase): def setUp(self): self.calendar = TARGET() self.settlement_days = 2 self.adjusted_today = self.calendar.adjust(today()) Settings().evaluation_date = self.adjusted_today self.settlement_date = self.calendar.advance(today(), self.settlement_days, Days) 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 zbt_libor_yield(instruments, yields, pricing_date, basis='Actual/Actual (Bond)', compounding_freq='Continuous', maturity_dates=None): """ Bootstrap a zero-coupon curve from libor rates and swap yields Args: instruments: list of instruments, of the form Libor?M for Libor rates and Swap?Y for swap rates yields: market rates pricing_date: the date where market data is observed. Settlement is by default 2 days after pricing_date Optional: compounding_frequency: ... of zero-coupon rates. By default: 'Continuous' Returns: zero_rate: zero-coupon rate maturity_date: ... of corresponding rate """ calendar = TARGET() settings = Settings() # must be a business day eval_date = calendar.adjust(pydate_to_qldate(pricing_date)) settings.evaluation_date = eval_date rates = dict(zip(instruments, yields)) ts = make_term_structure(rates, pricing_date) cnt = DayCounter.from_name(basis) if maturity_dates is None: # schedule of maturity dates from settlement date to last date on # the term structure s = Schedule(effective_date=ts.reference_date, termination_date=ts.max_date, tenor=Period(1, Months), calendar=TARGET()) maturity_dates = [qldate_to_pydate(dt) for dt in s.dates()] cp_freq = Compounding[compounding_freq] zc = [ ts.zero_rate(pydate_to_qldate(dt), day_counter=cnt, compounding=cp_freq).rate for dt in maturity_dates ] return (maturity_dates, zc)
def setUp(self): self.calendar = TARGET() self.settlement_days = 2 self.adjusted_today = self.calendar.adjust(today()) Settings().evaluation_date = self.adjusted_today self.settlement_date = self.calendar.advance( today(), self.settlement_days, Days )
def _cfamounts(coupon_rate, pricing_date, maturity_date, period, basis): """ cash flow schedule """ _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) 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) res = zip(*bond.cashflows) return(res)
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( 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) 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 zbt_libor_yield(instruments, yields, pricing_date, basis='Actual/Actual (Bond)', compounding_freq='Continuous', maturity_dates=None): """ Bootstrap a zero-coupon curve from libor rates and swap yields Args: insruments: list of instruments, of the form Libor?M for Libor rates and Swap?Y for swap rates yields: market rates pricing_date: the date where market data is observed. Settlement is by default 2 days after pricing_date Optional: compounding_frequency: ... of zero-coupon rates. By default: 'Continuous' Returns: zero_rate: zero-coupon rate maturity_date: ... of corresponding rate """ calendar = TARGET() settings = Settings() # must be a business day eval_date = calendar.adjust(pydate_to_qldate(pricing_date)) settings.evaluation_date = eval_date rates = dict(zip(instruments, yields)) ts = make_term_structure(rates, pricing_date) cnt = DayCounter.from_name(basis) if maturity_dates is None: # schedule of maturity dates from settlement date to last date on # the term structure s = Schedule(effective_date=ts.reference_date, termination_date=ts.max_date, tenor=Period(1, Months), calendar=TARGET()) maturity_dates = [qldate_to_pydate(dt) for dt in s.dates()] cp_freq = compounding_from_name(compounding_freq) zc = [ts.zero_rate(date=pydate_to_qldate(dt), day_counter=cnt, compounding=cp_freq).rate for dt in maturity_dates] return (maturity_dates, zc)
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): self.calendar = TARGET() self.settlement_days = 1 settlement_date = self.calendar.adjust(Date(28, January, 2011)) todays_date = self.calendar.advance( settlement_date, -self.settlement_days, Days ) Settings().evaluation_date = todays_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 ]] self.rate_helpers = [] end_of_month = True for m, period, rate in depositData: tenor = Period(m, Months) helper = DepositRateHelper(SimpleQuote(rate / 100), tenor, self.settlement_days, self.calendar, ModifiedFollowing, end_of_month, Actual360()) self.rate_helpers.append(helper) liborIndex = USDLibor(Period(6, Months)) for m, period, rate in swapData: sq_rate = SimpleQuote(rate/100) helper = SwapRateHelper.from_tenor( sq_rate, Period(m, Years), self.calendar, Annual, Unadjusted, Thirty360(), liborIndex ) self.rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 self.ts = PiecewiseYieldCurve( BootstrapTrait.Discount, Interpolator.LogLinear, self.settlement_days, self.calendar, self.rate_helpers, ts_day_counter, tolerance)
def setUp(self): self.calendar = TARGET() self.settlement_days = 2 self.adjusted_today = self.calendar.adjust(today()) Settings().evaluation_date = self.adjusted_today self.settlement_date = self.calendar.advance(today(), self.settlement_days, Days)
def test_iteration_on_date_list(self): date_iterator = TARGET().holiday_list(Date(1, Jan, 2000), Date(1, Jan, 2001)) holidays = [ Date(21, Apr, 2000), Date(24, Apr, 2000), Date(1, May, 2000), Date(25, Dec, 2000), Date(26, Dec, 2000), Date(1, Jan, 2001) ] for date in date_iterator: self.assertIn(date, holidays)
def test_calendar_creation(self): calendar = TARGET() self.assertEqual('TARGET', calendar.name) ukcalendar = UnitedKingdom() self.assertEqual('UK settlement', ukcalendar.name) lse_cal = UnitedKingdom(market=EXCHANGE) self.assertEqual('London stock exchange', lse_cal.name) null_calendar = NullCalendar() self.assertEqual('Null', null_calendar.name)
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 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])
class FlatForwardTestCase(unittest.TestCase): def setUp(self): self.calendar = TARGET() self.settlement_days = 2 self.adjusted_today = self.calendar.adjust(today()) Settings().evaluation_date = self.adjusted_today self.settlement_date = self.calendar.advance( today(), self.settlement_days, Days ) 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_bucketanalysis_bond(self): settings = Settings() calendar = TARGET() settlement_date = calendar.adjust(Date(28, January, 2011)) simple_quotes = [] fixing_days = 1 settlement_days = 1 todays_date = calendar.advance( settlement_date, -fixing_days, Days ) settings.evaluation_date = todays_date face_amount = 100.0 redemption = 100.0 issue_date = Date(27, January, 2011) maturity_date = Date(1, January, 2021) coupon_rate = 0.055 bond_yield = 0.034921 flat_discounting_term_structure = YieldTermStructure(relinkable=True) flat_term_structure = FlatForward( reference_date = settlement_date, forward = bond_yield, daycounter = Actual365Fixed(), compounding = Compounded, frequency = Semiannual) flat_discounting_term_structure.link_to(flat_term_structure) 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 ) zspd=bf.zSpread(bond, 100.0, flat_term_structure, Actual365Fixed(), Compounded, Semiannual, settlement_date, 1e-6, 100, 0.5) 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) sq_rate = SimpleQuote(rate/100) helper = DepositRateHelper(sq_rate, tenor, settlement_days, calendar, ModifiedFollowing, end_of_month, Actual360()) simple_quotes.append(sq_rate) 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: sq_rate = SimpleQuote(rate/100) helper = SwapRateHelper.from_tenor( sq_rate, Period(m, Years), calendar, Annual, Unadjusted, Thirty360(), liborIndex, spread, fwdStart ) simple_quotes.append(sq_rate) rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve( 'discount', 'loglinear', settlement_date, rate_helpers, ts_day_counter, tolerance) discounting_term_structure = YieldTermStructure(relinkable=True) discounting_term_structure.link_to(ts) pricing_engine = DiscountingBondEngine(discounting_term_structure) bond.set_pricing_engine(pricing_engine) self.assertAlmostEqual(bond.npv, 100.83702940160767) ba = bucket_analysis([simple_quotes], [bond], [1], 0.0001, 1) self.assertTrue(2, ba) self.assertTrue(type(tuple), ba) self.assertEqual(len(simple_quotes), len(ba[0][0])) self.assertEqual(0, ba[0][0][8])
from quantlib.time.calendars.null_calendar import NullCalendar from quantlib.time.calendars.weekends_only import WeekendsOnly import quantlib.time.calendars.germany as ger import quantlib.time.calendars.united_states as us import quantlib.time.calendars.united_kingdom as uk import quantlib.time.calendars.japan as jp import quantlib.time.calendars.switzerland as sw import quantlib.time.calendars.canada as ca from quantlib.time.calendars.target import TARGET from quantlib.util.object_registry import ObjectRegistry #ISO-3166 country codes (http://en.wikipedia.org/wiki/ISO_3166-1) ISO_3166_CALENDARS = { 'TARGET': TARGET(), 'NULL': NullCalendar(), 'WO': WeekendsOnly(), 'DEU': ger.Germany(), 'EUREX': ger.Germany(ger.EUREX), 'FSE': ger.Germany(ger.FRANKFURT_STOCK_EXCHANGE), 'EUWAX': ger.Germany(ger.EUWAX), 'XETRA': ger.Germany(ger.XETRA), 'GBR': uk.UnitedKingdom(), 'LSE': uk.UnitedKingdom(uk.EXCHANGE), 'LME': uk.UnitedKingdom(uk.METALS), 'USA': us.UnitedStates(), 'USA-GVT-BONDS': us.UnitedStates(us.GOVERNMENTBOND), 'NYSE': us.UnitedStates(us.NYSE), 'NERC': us.UnitedStates(us.NERC), 'JPN': jp.Japan(), 'CHE': sw.Switzerland(), 'CAN': ca.Canada(),
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.from_rule( 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.from_rule(effective_date, termination_date, Period(Annual), calendar, ModifiedFollowing, ModifiedFollowing, Backward) #3 flat_discounting_term_structure = YieldTermStructure() forecastTermStructure = YieldTermStructure() 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, True, 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.assertEqual(Date(10, Jul, 2016), termination_date) self.assertEqual(calendar.advance(todays_date, 3, Days), float_bond.settlement_date()) self.assertEqual(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)
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)
def test_bucketanalysis_bond(self): settings = Settings() calendar = TARGET() settlement_date = calendar.adjust(Date(28, January, 2011)) simple_quotes = [] fixing_days = 1 settlement_days = 1 todays_date = calendar.advance(settlement_date, -fixing_days, Days) settings.evaluation_date = todays_date face_amount = 100.0 redemption = 100.0 issue_date = Date(27, January, 2011) maturity_date = Date(1, January, 2021) coupon_rate = 0.055 bond_yield = 0.034921 flat_discounting_term_structure = YieldTermStructure() flat_term_structure = FlatForward(reference_date=settlement_date, forward=bond_yield, daycounter=Actual365Fixed(), compounding=Compounded, frequency=Semiannual) flat_discounting_term_structure.link_to(flat_term_structure) fixed_bond_schedule = Schedule.from_rule( 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) zspd = bf.zSpread(bond, 100.0, flat_term_structure, Actual365Fixed(), Compounded, Semiannual, settlement_date, 1e-6, 100, 0.5) 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) sq_rate = SimpleQuote(rate / 100) helper = DepositRateHelper(sq_rate, tenor, settlement_days, calendar, ModifiedFollowing, end_of_month, Actual360()) simple_quotes.append(sq_rate) 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: sq_rate = SimpleQuote(rate / 100) helper = SwapRateHelper.from_tenor(sq_rate, Period(m, Years), calendar, Annual, Unadjusted, Thirty360(), liborIndex, spread, fwdStart) simple_quotes.append(sq_rate) 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) discounting_term_structure = YieldTermStructure() discounting_term_structure.link_to(ts) pricing_engine = DiscountingBondEngine(discounting_term_structure) bond.set_pricing_engine(pricing_engine) self.assertAlmostEqual(bond.npv, 100.83702940160767) ba = bucket_analysis([simple_quotes], [bond], [1], 0.0001, 1) self.assertTrue(2, ba) self.assertTrue(type(tuple), ba) self.assertEqual(len(simple_quotes), len(ba[0][0])) self.assertEqual(0, ba[0][0][8])
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)
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.assertEqual(Date(10, Jul, 2016), termination_date) self.assertEqual( calendar.advance(todays_date, 3, Days), float_bond.settlement_date() ) self.assertEqual(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)
class SensitivityTestCase(unittest.TestCase): def setUp(self): self.calendar = TARGET() self.settlement_days = 1 settlement_date = self.calendar.adjust(Date(28, January, 2011)) todays_date = self.calendar.advance( settlement_date, -self.settlement_days, Days ) Settings().evaluation_date = todays_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 ]] self.rate_helpers = [] end_of_month = True for m, period, rate in depositData: tenor = Period(m, Months) helper = DepositRateHelper(SimpleQuote(rate / 100), tenor, self.settlement_days, self.calendar, ModifiedFollowing, end_of_month, Actual360()) self.rate_helpers.append(helper) liborIndex = USDLibor(Period(6, Months)) for m, period, rate in swapData: sq_rate = SimpleQuote(rate/100) helper = SwapRateHelper.from_tenor( sq_rate, Period(m, Years), self.calendar, Annual, Unadjusted, Thirty360(), liborIndex ) self.rate_helpers.append(helper) ts_day_counter = ActualActual(ISDA) tolerance = 1.0e-15 self.ts = PiecewiseYieldCurve( BootstrapTrait.Discount, Interpolator.LogLinear, self.settlement_days, self.calendar, self.rate_helpers, ts_day_counter, tolerance) def test_bucketanalysis_bond(self): face_amount = 100.0 redemption = 100.0 issue_date = Date(27, January, 2011) maturity_date = Date(1, January, 2021) coupon_rate = 0.055 fixed_bond_schedule = Schedule.from_rule( issue_date, maturity_date, Period(Semiannual), UnitedStates(market=GovernmentBond), Unadjusted, Unadjusted, Backward, False) bond = FixedRateBond( self.settlement_days, face_amount, fixed_bond_schedule, [coupon_rate], ActualActual(Bond), Unadjusted, redemption, issue_date ) pricing_engine = DiscountingBondEngine(self.ts) bond.set_pricing_engine(pricing_engine) self.assertAlmostEqual(bond.npv, 100.82127876105724) quotes = [rh.quote for rh in self.rate_helpers] delta, gamma = bucket_analysis(quotes, [bond]) self.assertEqual(len(quotes), len(delta)) old_values = [q.value for q in quotes] delta_manual = [] gamma_manual = [] pv = bond.npv shift = 1e-4 for v, q in zip(old_values, quotes): q.value = v + shift pv_plus = bond.npv q.value = v - shift pv_minus = bond.npv delta_manual.append((pv_plus - pv_minus) * 0.5 / shift) gamma_manual.append((pv_plus - 2 * pv + pv_minus) / shift ** 2) q.value = v assert_allclose(delta, delta_manual) assert_allclose(gamma, gamma_manual, atol=1e-4) 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 test_parallel_analysis(self): index = USDLibor(Period(3, Months), self.ts) swap = MakeVanillaSwap(Period(10, Years), index)() quotes = [rh.quote for rh in self.rate_helpers] old_values = [q.value for q in quotes] dv01, _ = parallel_analysis(quotes, [swap]) shift = 1e-4 for v, q in zip(old_values, quotes): q.value = v + shift pv_plus = swap.npv for v, q in zip(old_values, quotes): q.value = v - shift pv_minus = swap.npv self.assertAlmostEqual((pv_plus - pv_minus) * 0.5 / shift, dv01)