Coverage for tests/test_bonds.py: 99%

70 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-05 14:27 +0000

1from unittest import main, TestCase 

2from rivapy.instruments import ZeroCouponBondSpecification, FixedRateBondSpecification, FloatingRateNoteSpecification, PlainVanillaCouponBondSpecification 

3from rivapy.tools.enums import RollConvention, SecuritizationLevel, DayCounterType, Currency 

4from rivapy.pricing import SimpleCashflowPricer 

5from rivapy.marketdata import DiscountCurveParametrized, ConstantRate 

6from datetime import date, datetime 

7 

8 

9class BondSpecificationTests(TestCase): 

10 

11 def test_bond_specification(self): 

12 # zero coupon bond 

13 zero_coupon_bond = ZeroCouponBondSpecification('US500769CH58', datetime(2007, 6, 29), datetime(2037, 6, 29), 'USD', 1000, 'KfW', 

14 SecuritizationLevel.SENIOR_UNSECURED) 

15 self.assertEqual(zero_coupon_bond.obj_id, 'US500769CH58') 

16 self.assertEqual(zero_coupon_bond.issue_date, datetime(2007, 6, 29)) 

17 self.assertEqual(zero_coupon_bond.maturity_date, datetime(2037, 6, 29)) 

18 self.assertEqual(zero_coupon_bond.currency, 'USD') 

19 self.assertEqual(zero_coupon_bond.notional, 1000) 

20 self.assertEqual(zero_coupon_bond.issuer, 'KfW') 

21 self.assertEqual(zero_coupon_bond.securitization_level, 'SENIOR_UNSECURED') 

22 # fixed rate bond 

23 fixed_rate_bond = FixedRateBondSpecification.from_master_data('DE000CZ40NT7', datetime(2019, 3, 11), datetime(2024, 9, 11), 0.0125, 

24 '1Y', True, True, RollConvention.FOLLOWING, 'DE', 'EUR', 

25 100000, 'Commerzbank', 

26 SecuritizationLevel.NON_PREFERRED_SENIOR) 

27 self.assertEqual(fixed_rate_bond.obj_id, 'DE000CZ40NT7') 

28 self.assertEqual(fixed_rate_bond.issue_date, datetime(2019, 3, 11)) 

29 self.assertEqual(fixed_rate_bond.maturity_date, datetime(2024, 9, 11)) 

30 self.assertEqual(fixed_rate_bond.coupon_payment_dates, [datetime(2019, 9, 11), datetime(2020, 9, 11), datetime(2021, 9, 13), 

31 datetime(2022, 9, 12), datetime(2023, 9, 11), 

32 datetime(2024, 9, 11)]) 

33 self.assertEqual(fixed_rate_bond.coupons, [0.0125, 0.0125, 0.0125, 0.0125, 0.0125, 0.0125]) 

34 self.assertEqual(fixed_rate_bond.currency, 'EUR') 

35 self.assertEqual(fixed_rate_bond.notional, 100000) 

36 self.assertEqual(fixed_rate_bond.issuer, 'Commerzbank') 

37 self.assertEqual(fixed_rate_bond.securitization_level, 'NON_PREFERRED_SENIOR') 

38 fixed_rate_bond = FixedRateBondSpecification('DE000CZ40NT7', datetime(2019, 3, 11), datetime(2024, 9, 11), 

39 fixed_rate_bond.coupon_payment_dates, fixed_rate_bond.coupons, 'EUR', 100000, 

40 'Commerzbank', SecuritizationLevel.NON_PREFERRED_SENIOR) 

41 self.assertEqual(fixed_rate_bond.obj_id, 'DE000CZ40NT7') 

42 self.assertEqual(fixed_rate_bond.issue_date, datetime(2019, 3, 11)) 

43 self.assertEqual(fixed_rate_bond.maturity_date, datetime(2024, 9, 11)) 

44 self.assertEqual(fixed_rate_bond.coupon_payment_dates, [datetime(2019, 9, 11), datetime(2020, 9, 11), datetime(2021, 9, 13), 

45 datetime(2022, 9, 12), datetime(2023, 9, 11), 

46 datetime(2024, 9, 11)]) 

47 self.assertEqual(fixed_rate_bond.coupons, [0.0125, 0.0125, 0.0125, 0.0125, 0.0125, 0.0125]) 

48 self.assertEqual(fixed_rate_bond.currency, 'EUR') 

49 self.assertEqual(fixed_rate_bond.notional, 100000) 

50 self.assertEqual(fixed_rate_bond.issuer, 'Commerzbank') 

51 self.assertEqual(fixed_rate_bond.securitization_level, 'NON_PREFERRED_SENIOR') 

52 

53 # floating rate bond 

54 floating_rate_note = FloatingRateNoteSpecification.from_master_data('DE000HLB3DU1', datetime(2016, 6, 23), datetime(2024, 6, 27), 

55 '3M', True, False, RollConvention.FOLLOWING, 'DE', 

56 DayCounterType.ThirtyU360, 0.0, 'EURIBOR_3M', 'EUR', 1000, 

57 'Helaba', SecuritizationLevel.NON_PREFERRED_SENIOR) 

58 self.assertEqual(floating_rate_note.obj_id, 'DE000HLB3DU1') 

59 self.assertEqual(floating_rate_note.issue_date, datetime(2016, 6, 23)) 

60 self.assertEqual(floating_rate_note.maturity_date, datetime(2024, 6, 27)) 

61 self.assertEqual(floating_rate_note.coupon_period_dates, [datetime(2016, 6, 23), datetime(2016, 9, 27), 

62 datetime(2016, 12, 27), datetime(2017, 3, 27), 

63 datetime(2017, 6, 27), datetime(2017, 9, 27), 

64 datetime(2017, 12, 27), datetime(2018, 3, 27), 

65 datetime(2018, 6, 27), datetime(2018, 9, 27), 

66 datetime(2018, 12, 27), datetime(2019, 3, 27), 

67 datetime(2019, 6, 27), datetime(2019, 9, 27), 

68 datetime(2019, 12, 27), datetime(2020, 3, 27), 

69 datetime(2020, 6, 29), datetime(2020, 9, 28), 

70 datetime(2020, 12, 28), datetime(2021, 3, 29), 

71 datetime(2021, 6, 28), datetime(2021, 9, 27), 

72 datetime(2021, 12, 27), datetime(2022, 3, 28), 

73 datetime(2022, 6, 27), datetime(2022, 9, 27), 

74 datetime(2022, 12, 27), datetime(2023, 3, 27), 

75 datetime(2023, 6, 27), datetime(2023, 9, 27), 

76 datetime(2023, 12, 27), datetime(2024, 3, 27), 

77 datetime(2024, 6, 27)]) 

78 self.assertEqual(floating_rate_note.daycount_convention, '30U360') 

79 self.assertEqual(floating_rate_note.spreads, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 

80 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 

81 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) 

82 self.assertEqual(floating_rate_note.reference_index, 'EURIBOR_3M') 

83 self.assertEqual(floating_rate_note.currency, 'EUR') 

84 self.assertEqual(floating_rate_note.notional, 1000) 

85 self.assertEqual(floating_rate_note.issuer, 'Helaba') 

86 self.assertEqual(floating_rate_note.securitization_level, 'NON_PREFERRED_SENIOR') 

87 floating_rate_note = FloatingRateNoteSpecification('DE000HLB3DU1', datetime(2016, 6, 23), datetime(2024, 6, 27), 

88 floating_rate_note.coupon_period_dates, DayCounterType.ThirtyU360, 

89 floating_rate_note.spreads, 'EURIBOR_3M', 'EUR', 1000, 'Helaba', 

90 SecuritizationLevel.NON_PREFERRED_SENIOR) 

91 self.assertEqual(floating_rate_note.obj_id, 'DE000HLB3DU1') 

92 self.assertEqual(floating_rate_note.issue_date, datetime(2016, 6, 23)) 

93 self.assertEqual(floating_rate_note.maturity_date, datetime(2024, 6, 27)) 

94 self.assertEqual(floating_rate_note.coupon_period_dates, [datetime(2016, 6, 23), datetime(2016, 9, 27), 

95 datetime(2016, 12, 27), datetime(2017, 3, 27), 

96 datetime(2017, 6, 27), datetime(2017, 9, 27), 

97 datetime(2017, 12, 27), datetime(2018, 3, 27), 

98 datetime(2018, 6, 27), datetime(2018, 9, 27), 

99 datetime(2018, 12, 27), datetime(2019, 3, 27), 

100 datetime(2019, 6, 27), datetime(2019, 9, 27), 

101 datetime(2019, 12, 27), datetime(2020, 3, 27), 

102 datetime(2020, 6, 29), datetime(2020, 9, 28), 

103 datetime(2020, 12, 28), datetime(2021, 3, 29), 

104 datetime(2021, 6, 28), datetime(2021, 9, 27), 

105 datetime(2021, 12, 27), datetime(2022, 3, 28), 

106 datetime(2022, 6, 27), datetime(2022, 9, 27), 

107 datetime(2022, 12, 27), datetime(2023, 3, 27), 

108 datetime(2023, 6, 27), datetime(2023, 9, 27), 

109 datetime(2023, 12, 27), datetime(2024, 3, 27), 

110 datetime(2024, 6, 27)]) 

111 self.assertEqual(floating_rate_note.daycount_convention, '30U360') 

112 self.assertEqual(floating_rate_note.spreads, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 

113 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 

114 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) 

115 self.assertEqual(floating_rate_note.reference_index, 'EURIBOR_3M') 

116 self.assertEqual(floating_rate_note.currency, 'EUR') 

117 self.assertEqual(floating_rate_note.notional, 1000) 

118 self.assertEqual(floating_rate_note.issuer, 'Helaba') 

119 self.assertEqual(floating_rate_note.securitization_level, 'NON_PREFERRED_SENIOR') 

120 

121 # fixed-to-floating rate note 

122 # if False: 

123 # # not correctly working 

124 # fixed_to_floating_rate_note = FixedToFloatingRateNote.from_master_data('XS1887493309', datetime(2018, 10, 4), 

125 # datetime(2022, 1, 20), datetime(2023, 1, 20), 

126 # 0.04247, '6M', '3M', True, True, True, 

127 # False, RollConvention.MODIFIED_FOLLOWING, 

128 # RollConvention.MODIFIED_FOLLOWING, 'DE', 

129 # 'DE', DayCounterType.ThirtyU360, 0.0115, 

130 # 'US_LIBOR_3M', 'USD', 1000000, 

131 # 'Standard Chartered PLC', 

132 # SecuritizationLevel.SENIOR_SECURED) 

133 # self.assertEqual(fixed_to_floating_rate_note.obj_id, 'XS1887493309') 

134 # # self.assertEqual(fixed_to_floating_rate_note.issue_date, datetime(2018, 10, 4)) 

135 # self.assertEqual(fixed_to_floating_rate_note.maturity_date, datetime(2023, 1, 20)) 

136 # self.assertEqual(fixed_to_floating_rate_note.coupon_payment_dates, [datetime(2019, 1, 21), datetime(2019, 7, 22), 

137 # datetime(2020, 1, 20), datetime(2020, 7, 20), 

138 # datetime(2021, 1, 20), datetime(2021, 7, 20), 

139 # datetime(2022, 1, 20)]) 

140 # self.assertEqual(fixed_to_floating_rate_note.coupons, [0.04247, 0.04247, 0.04247, 0.04247, 0.04247, 0.04247, 

141 # 0.04247]) 

142 # self.assertEqual(fixed_to_floating_rate_note.coupon_period_dates, [datetime(2022, 1, 20), datetime(2022, 4, 20), 

143 # datetime(2022, 7, 20), datetime(2022, 10, 20), 

144 # datetime(2023, 1, 20)]) 

145 # self.assertEqual(fixed_to_floating_rate_note.day_count_convention, '30U360') 

146 # self.assertEqual(fixed_to_floating_rate_note.spreads, [0.0115, 0.0115, 0.0115, 0.0115]) 

147 # self.assertEqual(fixed_to_floating_rate_note.currency, 'USD') 

148 # self.assertEqual(fixed_to_floating_rate_note.notional, 1000000) 

149 # self.assertEqual(fixed_to_floating_rate_note.issuer, 'Standard Chartered PLC') 

150 # self.assertEqual(fixed_to_floating_rate_note.securitization_level, 'SENIOR_SECURED') 

151 

152class BondPricingTests(TestCase): 

153 

154 def test_yield_bond(self): 

155 """Simple test for yield computation: Fixed rate used to compute pv which is then used to compute yield. 

156 """ 

157 ref_date = datetime(2023,5,1) 

158 bond_spec = PlainVanillaCouponBondSpecification('PV_BOND', 

159 issue_date = datetime(2023,1,1), 

160 maturity_date = datetime(2025,1,2), 

161 currency = Currency.EUR, notional=100.0, 

162 issuer='None', 

163 securitization_level=SecuritizationLevel.SUBORDINATED, 

164 coupon = 0.05, coupon_freq='1Y', 

165 accrual_start = datetime(2023,2,10)) 

166 dc = DiscountCurveParametrized('', ref_date, ConstantRate(0.05)) 

167 bond_price = SimpleCashflowPricer.pv_cashflows(ref_date, bond_spec, dc) 

168 bond_yield = SimpleCashflowPricer.compute_yield(target_dirty_price=bond_price, 

169 val_date = ref_date, 

170 specification=bond_spec) 

171 self.assertAlmostEqual(bond_yield,0.05, delta=1e-3) 

172if __name__ == '__main__': 

173 main()