Coverage for tests/test_marketdata.py: 80%

93 statements  

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

1import unittest 

2import numpy as np 

3import datetime as dt 

4 

5import rivapy 

6from rivapy.marketdata import VolatilityGridParametrization, VolatilityParametrizationSABR, VolatilitySurface 

7from rivapy.marketdata import ( 

8 DiscountCurve, 

9 EquityForwardCurve, 

10 enums, 

11 DiscountCurveComposition, 

12 DiscountCurveParametrized, 

13 ConstantRate, 

14 LinearRate, 

15) 

16from rivapy.tools import SimpleSchedule 

17from rivapy import enums 

18from rivapy import _pyvacon_available 

19 

20 

21class VolatilityGridParamTest(unittest.TestCase): 

22 def test_exceptions(self): 

23 expiries = np.linspace(1.0 / 365.0, 4.0, 10) 

24 strikes = np.linspace(0.4, 1.6, 100) 

25 # test for exception if number of strikes does not match number of cols 

26 vols = np.empty((expiries.shape[0], 1)) 

27 try: 

28 vol_grid_param = VolatilityGridParametrization(expiries, strikes, vols) 

29 self.assertFalse(False) 

30 except: 

31 self.assertFalse(True) 

32 

33 def test_calc_implied_vol(self): 

34 """Simple tests for class VolatilityGridParametrization""" 

35 if not _pyvacon_available: 

36 self.assertEqual(1, 1) 

37 return 

38 expiries = np.linspace(1.0 / 365.0, 4.0, 10) 

39 strikes = np.linspace(0.4, 1.6, 100) 

40 vols = 0.3 * np.ones((expiries.shape[0], strikes.shape[0])) 

41 vol_grid_param = VolatilityGridParametrization(expiries, strikes, vols) 

42 self.assertAlmostEqual(0.3, vol_grid_param.calc_implied_vol(1.0, 1.3), delta=1e-7) 

43 # now add to volatility surface 

44 refdate = dt.datetime(2021, 1, 1) 

45 dummy = DiscountCurve("", refdate=refdate, dates=[refdate, refdate + dt.timedelta(days=10 * 365)], df=[1.0, 1.0]) 

46 fwd = EquityForwardCurve(100.0, funding_curve=dummy, borrow_curve=dummy, div_table=None) 

47 vol_surface = VolatilitySurface("", refdate, fwd, enums.DayCounterType.Act365Fixed, vol_grid_param) 

48 if not _pyvacon_available: 

49 self.assertAlmostEqual(1, 1) 

50 return 

51 vol = vol_surface.calc_implied_vol(refdate + dt.timedelta(days=365), 100.0) 

52 self.assertAlmostEqual(vol, vol_grid_param.calc_implied_vol(1.0, 1.3), delta=1e-7) 

53 

54 

55class VolatilitySABRParamTest(unittest.TestCase): 

56 

57 def test_calc_implied_vol(self): 

58 # 1. Parametrization 

59 expiries = [1.0 / 12.0, 1.0, 2.0, 3.0] 

60 sabr_params = np.array( 

61 [ 

62 [0.1, 0.1, 0.9, -0.8], 

63 [0.3, 0.1, 0.1, 0.1], 

64 [ 

65 0.5, 

66 0.3, 

67 0.9, 

68 -0.75, 

69 ], 

70 [ 

71 0.5, 

72 0.3, 

73 0.9, 

74 -0.85, 

75 ], 

76 ] 

77 ) 

78 sabr_param = VolatilityParametrizationSABR(expiries, sabr_params) 

79 self.assertAlmostEqual(0.30118, sabr_param.calc_implied_vol(ttm=1.0, strike=1.0), delta=1e-7) 

80 

81 # 2. Vol Surface 

82 obj_id = "Test Surface" 

83 refdate = dt.datetime(2021, 1, 1) 

84 dc = DiscountCurve("", refdate=refdate, dates=[refdate, refdate + dt.timedelta(days=10 * 365)], df=[1.0, 1.0]) 

85 fc = EquityForwardCurve(100.0, funding_curve=dc, borrow_curve=dc, div_table=None) 

86 vol_surf = VolatilitySurface(obj_id, refdate, fc, enums.DayCounterType.Act365Fixed, sabr_param) 

87 if not _pyvacon_available: 

88 self.assertAlmostEqual(1, 1) 

89 return 

90 vol = vol_surf.calc_implied_vol(refdate + dt.timedelta(days=365), 100.0, refdate) 

91 self.assertAlmostEqual(vol, sabr_param.calc_implied_vol(ttm=1.0, strike=1.0), delta=1e-7) 

92 

93 

94class VolatilitySurfaceTest(unittest.TestCase): 

95 

96 def test_calc_implied_vol_single_expiry(self): 

97 self.assertAlmostEqual(0, 0) 

98 # Fix to make the the commented code below working 

99 return 

100 """Test if calc_implied_vol works for single expiry 

101 """ 

102 expiries = np.array([1]) 

103 strikes = np.linspace(0.4, 1.6, 100) 

104 vols = 0.3 * np.ones((expiries.shape[0], strikes.shape[0])) 

105 vol_grid_param = VolatilityGridParametrization(expiries, strikes, vols) 

106 self.assertAlmostEqual(0.3, vol_grid_param.calc_implied_vol(1.0, 1.3), delta=1e-7) 

107 refdate = dt.datetime(2021, 1, 1) 

108 dummy = DiscountCurve("", refdate=refdate, dates=[refdate, refdate + dt.timedelta(days=10 * 365)], df=[1.0, 1.0]) 

109 fwd = EquityForwardCurve(100.0, funding_curve=dummy, borrow_curve=dummy, div_table=None) 

110 vol_surface = VolatilitySurface("", refdate, fwd, enums.DayCounterType.Act365Fixed, vol_grid_param) 

111 vol = vol_surface.calc_implied_vol(refdate + dt.timedelta(days=365), 100.0) 

112 self.assertAlmostEqual(vol, vol_grid_param.calc_implied_vol(1.0, 1.3), delta=1e-7) 

113 

114 

115# class PowerPriceForwardCurveTest(unittest.TestCase): 

116# def test_simple_schedule(self): 

117# """Test value with SimpleSchedule""" 

118# simple_schedule = SimpleSchedule(dt.datetime(2022, 12, 1), dt.datetime(2023, 11, 1, 4, 0, 0), freq="1H") 

119# values = np.ones((len(simple_schedule.get_schedule()),)).cumsum() 

120# hpfc = PowerPriceForwardCurve(dt.datetime(2022, 12, 1), dt.datetime(2022, 12, 1), dt.datetime(2023, 11, 1, 4, 0, 0), freq="1H", values=values) 

121# simple_schedule = SimpleSchedule(dt.datetime(2022, 12, 1), dt.datetime(2022, 12, 1, 4, 0, 0), freq="1H") 

122# values = hpfc.value(dt.datetime(2022, 1, 1), simple_schedule) 

123# self.assertEqual(values.shape[0], 4) 

124# self.assertEqual(values[0], 1) 

125# self.assertEqual(values[-1], 4) 

126# # same with hours excluded 

127# simple_schedule = SimpleSchedule(dt.datetime(2022, 12, 1), dt.datetime(2022, 12, 1, 4, 0, 0), freq="1H", hours=[2]) 

128# values = hpfc.value(dt.datetime(2022, 1, 1), simple_schedule) 

129# self.assertEqual(values.shape[0], 1) 

130# self.assertEqual(values[0], 3) 

131 

132# def test_exceptions(self): 

133# """Test consistency checks in forward curve.""" 

134# simple_schedule = SimpleSchedule(dt.datetime(2022, 12, 1), dt.datetime(2023, 11, 1, 4, 0, 0), freq="1H") 

135# values = np.ones((len(simple_schedule.get_schedule()),)).cumsum() 

136# hpfc = PowerPriceForwardCurve(dt.datetime(2022, 12, 1), dt.datetime(2022, 12, 1), dt.datetime(2023, 11, 1, 4, 0, 0), freq="1H", values=values) 

137# # schedule starts before first date of forward curve 

138# simple_schedule = SimpleSchedule(dt.datetime(2022, 11, 30), dt.datetime(2022, 12, 1, 4, 0, 0), freq="1H") 

139# self.assertRaises(Exception, lambda: hpfc.value(dt.datetime(2022, 1, 1), simple_schedule)) 

140# # schedule ends after last date of forward curve 

141# simple_schedule = SimpleSchedule(dt.datetime(2022, 11, 30), dt.datetime(2023, 12, 1, 4, 0, 0), freq="1H") 

142# self.assertRaises(Exception, lambda: hpfc.value(dt.datetime(2022, 1, 1), simple_schedule)) 

143 

144 

145class DiscountCurveCompositionTest(unittest.TestCase): 

146 def test_curve_addition(self): 

147 """Simple test adding two curves testing""" 

148 ref_date = dt.datetime(2023, 1, 1) 

149 c1 = DiscountCurveParametrized("C1", ref_date, ConstantRate(0.01)) 

150 c2 = DiscountCurveParametrized("C2", ref_date, ConstantRate(0.025)) 

151 # add two constant curves 

152 c = c1 + c2 

153 d = ref_date + dt.timedelta(days=10 * 365) 

154 self.assertAlmostEqual(c1.value_rate(ref_date, d) + c2.value_rate(ref_date, d), c.value_rate(ref_date, d), places=6) 

155 self.assertAlmostEqual(c1.value(ref_date, d) * c2.value(ref_date, d), c.value(ref_date, d), places=6) 

156 # add one constant and one linear curve 

157 c2 = DiscountCurveParametrized("C2", ref_date, LinearRate(0.01, 0.05, max_maturity=10.0)) 

158 c = c1 + c2 

159 self.assertAlmostEqual(c1.value_rate(ref_date, d) + c2.value_rate(ref_date, d), c.value_rate(ref_date, d), places=6) 

160 self.assertAlmostEqual(c1.value(ref_date, d) * c2.value(ref_date, d), c.value(ref_date, d), places=6) 

161 # add a curve and a float 

162 c = 0.01 + c2 

163 self.assertAlmostEqual(c1.value_rate(ref_date, d) + c2.value_rate(ref_date, d), c.value_rate(ref_date, d), places=6) 

164 self.assertAlmostEqual(c1.value(ref_date, d) * c2.value(ref_date, d), c.value(ref_date, d), places=6) 

165 

166 def test_curve_multiplication(self): 

167 """Simple test multiplying two curves""" 

168 ref_date = dt.datetime(2023, 1, 1) 

169 c1 = DiscountCurveParametrized("C1", ref_date, ConstantRate(0.01)) 

170 c2 = DiscountCurveParametrized("C2", ref_date, ConstantRate(0.025)) 

171 # multiply two constant curves 

172 c = c1 * c2 

173 d = ref_date + dt.timedelta(days=10 * 365) 

174 self.assertAlmostEqual(c1.value_rate(ref_date, d) * c2.value_rate(ref_date, d), c.value_rate(ref_date, d), places=6) 

175 df = np.exp(-c1.value_rate(ref_date, d) * c2.value_rate(ref_date, d) * c1._dc.yf(ref_date, d)) 

176 self.assertAlmostEqual(df, c.value(ref_date, d), places=6) 

177 

178 # multiply one constant and one linear curve 

179 c2 = DiscountCurveParametrized("C2", ref_date, LinearRate(0.01, 0.05, max_maturity=10.0)) 

180 c = c1 * c2 

181 self.assertAlmostEqual(c1.value_rate(ref_date, d) * c2.value_rate(ref_date, d), c.value_rate(ref_date, d), places=6) 

182 df = np.exp(-c1.value_rate(ref_date, d) * c2.value_rate(ref_date, d) * c1._dc.yf(ref_date, d)) 

183 self.assertAlmostEqual(df, c.value(ref_date, d), places=6) 

184 # multiply a curve and a float 

185 c = 0.01 * c2 

186 self.assertAlmostEqual(0.01 * c2.value_rate(ref_date, d), c.value_rate(ref_date, d), places=6) 

187 df = np.exp(-0.01 * c2.value_rate(ref_date, d) * c1._dc.yf(ref_date, d)) 

188 self.assertAlmostEqual(df, c.value(ref_date, d), places=6) 

189 

190 

191if __name__ == "__main__": 

192 unittest.main()