def test_clean_price(self): notional = 1000000.0 fixed_rates = [0.1] fixed_day_count = Actual365Fixed() fixed_calendar = self.calendar fixed_index = self.ii contractObservationLag = Period(3, Months) observationInterpolation = InterpolationType.Flat settlement_days = 3 growth_only = True baseCPI = 206.1 fixed_schedule = Schedule.from_rule(Date(2, 10, 2007), Date(2, 10, 2052), Period(6, Months), fixed_calendar, Unadjusted, Rule.Backward) cpi_bond = CPIBond(settlement_days, notional, growth_only, baseCPI, contractObservationLag, fixed_index, observationInterpolation, fixed_schedule, fixed_rates, fixed_day_count, ModifiedFollowing) engine = DiscountingBondEngine(self.yts) cpi_bond.set_pricing_engine(engine) set_coupon_pricer(cpi_bond.cashflows, CPICouponPricer(self.yts)) storedPrice = 383.01816406 calculated = cpi_bond.clean_price self.assertAlmostEqual(storedPrice, calculated)
def test_normalize_period(self): period = Period(12, Months) period.normalize() self.assertEquals(1, period.length) self.assertEquals(Years, period.units)
def test_period_substraction(self): period1 = Period(11, Months) period2 = Period(EveryFourthMonth) period3 = period1 - period2 self.assertEquals(7, period3.length) self.assertEquals(Months, period3.units)
def test_normalize_period(self): period = Period(12, Months) period.normalize() self.assertEqual(1, period.length) self.assertEqual(Years, period.units)
def test_period_substraction(self): period1 = Period(11, Months) period2 = Period(EveryFourthMonth) period3 = period1 - period2 self.assertEqual(7, period3.length) self.assertEqual(Months, period3.units) with self.assertRaisesRegexp(RuntimeError, 'impossible addition'): period1 - Period('3W')
def test_creation_with_frequency(self): period = Period(Annual) self.assertEqual(1, period.length) self.assertEqual(Years, period.units) period = Period(Bimonthly) self.assertEqual(2, period.length) self.assertEqual(Months, period.units)
def test_multiplication(self): period = Period(Bimonthly) period2 = period * 10 self.assertEqual(20, period2.length) # invert operation period2 = 10 * period self.assertIsInstance(period2, Period) self.assertEqual(20, period2.length) self.assertEqual(3 * Months, Period(3, Months)) self.assertEqual(Days * 10, Period(10, Days))
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_inplace_addition(self): period = Period(Bimonthly) period2 = Period(2, Months) period += period2 self.assertEqual(4, period.length) self.assertEqual(Months, period.units) with self.assertRaises(ValueError): period3 = Period(2, Weeks) period += period3 # does not support different units
def test_inplace_substraction(self): period = Period(Semiannual) period2 = Period(3, Months) period -= period2 self.assertEqual(3, period.length) self.assertEqual(Months, period.units) with self.assertRaises(ValueError): period3 = Period(2, Weeks) period -= period3 # does not support different units
def test_weekendsonly_calendar(self): wocal = WeekendsOnly() first_date = Date(31, Dec, 2014) Jan_1_2015 = Date(1, Jan, 2015) Jan_5_2015 = Date(5, Jan, 2015) period_1_day = Period(1, Days) period_3_day = Period(3, Days) #do not skip holidays self.assertEqual(Jan_1_2015, wocal.advance(first_date, period=period_1_day, convention=Following)) #but skip weekend dates self.assertEqual(Jan_5_2015, wocal.advance(first_date, period=period_3_day, convention=Following))
def test_creation_with_time_and_units(self): period = Period(10, Months) self.assertEqual(10, period.length) self.assertEqual(Months, period.units) self.assertEqual(OtherFrequency, period.frequency)
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_german_calendar(self): frankfcal = Germany(Market.Eurex) first_date = Date(31, Oct, 2009) second_date = Date(1, Jan, 2010) Dec_30_2009 = Date(30, Dec, 2009) Jan_4_2010 = Date(4, Jan, 2010) self.assertEqual(Dec_30_2009, frankfcal.adjust(second_date, Preceding)) self.assertEqual(Jan_4_2010, frankfcal.adjust(second_date, ModifiedPreceding)) mat = Period(2, Months) self.assertEqual( Jan_4_2010, frankfcal.advance(first_date, period=mat, convention=Following, end_of_month=False)) self.assertEqual( Dec_30_2009, frankfcal.advance(first_date, period=mat, convention=ModifiedFollowing, end_of_month=False)) self.assertEqual( 41, frankfcal.business_days_between(first_date, second_date, False, False))
def test_parallel_analysis(self): index = USDLibor(Period(3, Months), self.ts) swap = MakeVanillaSwap(Period(10, Years), index)() old_values = [q.value for q in self.quotes] dv01, _ = parallel_analysis(self.quotes, [swap]) shift = 1e-4 for v, q in zip(old_values, self.quotes): q.value = v + shift pv_plus = swap.npv for v, q in zip(old_values, self.quotes): q.value = v - shift pv_minus = swap.npv self.assertAlmostEqual((pv_plus - pv_minus) * 0.5 / shift, dv01)
def test_inplace_division(self): period = Period(Semiannual) period /= 3 self.assertEqual(2, period.length) self.assertEqual(Months, period.units)
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 test_substracting_period_to_date(self): date1 = Date(1, May, 2011) period = Period(1, Months) date2 = date1 - period expected_date = Date(1, Apr, 2011) self.assertTrue(expected_date == date2) period = Period(Bimonthly) date2 = date1 - period expected_date = Date(1, Mar, 2011) self.assertTrue(expected_date == date2) period = Period(10, Days) date2 = date1 - period expected_date = Date(21, Apr, 2011) self.assertTrue(expected_date == date2)
def test_zero_index(self): aucpi = AUCPI(Monthly, True, True) self.assertEqual(aucpi.name, "Australia CPI") self.assertEqual(aucpi.frequency, Monthly) self.assertEqual(aucpi.availabilityLag, Period(2, Months))
def test_adding_period_to_date(self): date1 = Date(1, May, 2011) period = Period(1, Months) date2 = date1 + period expected_date = Date(1, Jun, 2011) self.assertTrue(expected_date == date2) period = Period(Bimonthly) date2 = date1 + period expected_date = Date(1, Jul, 2011) self.assertTrue(expected_date == date2) period = Period(10, Months) date2 = date1 + period expected_date = Date(1, Mar, 2012) self.assertTrue(expected_date == date2)
def test_at(self): expected_date = self.calendar.adjust(self.from_date, Following) self.assertTrue(expected_date == self.schedule.at(0)) next_date = self.calendar.adjust(self.from_date + Period(4, Weeks), Following) expected_date = Date(20, next_date.month, next_date.year) self.assertTrue(expected_date == self.schedule.at(1))
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_multiplication(self): period = Period(Bimonthly) period2 = period * 10 self.assertEquals(20, period2.length) # invert operation period2 = 10 * period self.assertIsInstance(period2, Period) self.assertEquals(20, period2.length)
def test_simple(self): periods = [3, 6, 12] expected_times = [0.25, 0.5, 1.0] first = Date(1, January, 2002) day_counter = SimpleDayCounter() for index, period in enumerate(periods): end = first + Period(period, Months) calculated = day_counter.year_fraction(first, end) self.assertAlmostEquals(expected_times[index], calculated)
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.from_date = Date(1, Jan, 2011) self.to_date = Date(31, Dec, 2011) self.tenor = Period(4, Weeks) self.calendar = UnitedKingdom() self.convention = Following self.termination_convention = Preceding self.rule = Twentieth self.schedule = Schedule(self.from_date, self.to_date, self.tenor, self.calendar, self.convention, self.termination_convention, self.rule)
def test_calendar_date_advance(self): ukcal = UnitedKingdom() bank_holiday_date = Date(3, May, 2010) #Early May Bank Holiday advanced_date = ukcal.advance(bank_holiday_date, step=6, units=Months) expected_date = Date(3, November, 2010) self.assertTrue(expected_date == advanced_date) period_10days = Period(10, Days) advanced_date = ukcal.advance(bank_holiday_date, period=period_10days) expected_date = Date(17, May, 2010) self.assertTrue(expected_date == advanced_date)
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 _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 test_schedule_from_dates(self): dates = [Date(3, Sep, 2011), Date(5, Nov, 2011), Date(15, Dec, 2011)] tenor = Period(1, Months) calendar = UnitedKingdom() convention = Following termination_convention = Following rule = Forward schedule = Schedule.from_dates(dates, calendar, convention, termination_convention, tenor, rule) expected_date = Date(3, Sep, 2011) self.assert_(expected_date == schedule.next_date(Date(3, Sep, 2011))) expected_date = Date(5, Nov, 2011) self.assert_(expected_date == schedule.next_date(Date(4, Sep, 2011))) expected_date = Date(15, Dec, 2011) self.assert_(expected_date == schedule.next_date(Date(6, Nov, 2011)))
def test_rich_cmp(self): # equality period1 = Period(Annual) period2 = Period(1, Years) self.assertTrue(period1 == period2) period1 = Period(12, Months) period2 = Period(1, Years) self.assertTrue(period1 == period2) # non equality period1 = Period(11, Months) period2 = Period(1, Years) period3 = Period(150, Weeks) period4 = Period(52, Weeks) self.assertTrue(period1 != period2) self.assertTrue(period1 < period2) self.assertTrue(period3 > period1) self.assertTrue(period3 >= period1) self.assertTrue(period4 <= period2)