Coverage for rivapy / pricing / pricing_request.py: 40%

302 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-27 14:36 +0000

1# -*- coding: utf-8 -*- 

2 

3 

4from datetime import date, datetime 

5from typing import List as _List, Union as _Union 

6from rivapy.tools.interfaces import FactoryObject 

7from rivapy.tools.datetools import _date_to_datetime as datetime_to_date, _datetime_to_date_list as datetime_to_date_list 

8 

9 

10class PricingRequestBase(FactoryObject): 

11 

12 _keys = ["theo_val", "paths_udl", "cf_expected", "cf_paths"] 

13 

14 def __init__(self, **kwargs): 

15 # validate the given keys 

16 for key in kwargs.keys(): 

17 if key not in PricingRequestBase._keys: 

18 raise ValueError("Unknown key '{}'".format(key)) 

19 # set the attributes 

20 setattr(self, key, kwargs[key]) 

21 

22 def _to_dict(self) -> dict: 

23 return self.__dict__ 

24 

25 

26class DepositPricingRequest(PricingRequestBase): 

27 

28 def __init__(self, theo_val: bool, cf_paths: bool = False, cf_expected: bool = False): 

29 """Configuration of set of information to be calculated for the Deposit's price. 

30 Restrict the general PricingRequest to the sub-set relevant for the pricing of deposits. 

31 """ 

32 

33 super().__init__(theo_val=theo_val, cf_paths=cf_paths, cf_expected=cf_expected) 

34 

35 

36class GreenPPAPricingRequest(PricingRequestBase): 

37 def __init__(self, theo_val: bool = False, cf_paths: bool = False, cf_expected: bool = False): 

38 """PricingRequest for Green PPA pricing. 

39 

40 Args: 

41 price (bool): If True, the :term:`Theoretical Value` is calculated. 

42 cf_expected (bool, optional): If True, the paths of the simulated :term:`Cash flow` is returned. Defaults to False. 

43 """ 

44 super().__init__(theo_val=theo_val, cf_expected=cf_expected, cf_paths=cf_paths) 

45 

46 

47class PricingRequest: 

48 # def __init__(self, calc_delta_gamma: bool = False, calc_cross_gamma: bool = True, calc_clean_price: bool = False, 

49 # calc_rho: bool = False, rho_scale: float = 0.0001, calc_vega: bool = False, vega_scale: float = 0.01, 

50 # calc_cross_volga: bool = False, calc_vanna: bool = False, calc_theta: bool = False, 

51 # theta_scale: float = 1.0, calc_spline: bool = False, calc_grid_sizes: bool = False, 

52 # calc_implied_volatility: bool = False, management_delta_limit: float = 0.01, 

53 # calc_pricing_data: bool = False, calc_expected_cashflows: bool = False, 

54 # calc_simulation_data: bool = False, calc_additional_information: bool = False, 

55 # calc_z_spread: bool = False, calc_yield_to_maturity: bool = False, calc_convexity: bool = False, 

56 # max_expected_cashflow_date: _Union[date, datetime] = None, 

57 # cashflow_times: _List[_Union[date, datetime]] = None, calc_macaulay_duration: bool = False): 

58 # """ 

59 # Defines the set of information, e.g. sensitivities, cashflow information, etc., to be calculated together with 

60 # the instrument's price in the context of pricing. For some sensitivities the shift parameter for calculating 

61 # the difference quotient (rather than the sensitivity in closed formula) is also stored in the pricing request 

62 # object. 

63 # 

64 # Args: TODO: Read carefully and double-check if these guessed descriptions are valid! 

65 # calc_delta_gamma (bool, optional): Flag determining if the change of the instrument's price associated with 

66 # small changes of the underlying's price shall be calculated to first (and 

67 # second) order within the pricing routine. Defaults to False. 

68 # TODO: also second order? delta_scale=? 

69 # calc_cross_gamma (bool, optional): Flag determining if the change of the instrument's price associated with 

70 # small changes of two underlyings' prices (both at fist order) shall be 

71 # calculated within the pricing routine. Defaults to True. 

72 # TODO: why defaults to True? 

73 # calc_clean_price (bool, optional): Flag determining if the instrument's clean price shall be calculated 

74 # additional to its dirty price within the pricing routine. 

75 # Defaults to False. 

76 # calc_rho (bool, optional): Flag determining if the change of the instrument's price associated with small 

77 # changes of the zero rate curve shall be calculated to first order within the 

78 # pricing routine. Defaults to False. 

79 # rho_scale (float, optional): Size of zero rate shift in the calculation of the change of the instrument's 

80 # price associated with zero rate curve shifts as difference quotient. 

81 # Defaults to 0.0001 (= 1 basis point). 

82 # calc_vega (bool, optional): Flag determining if the change of the instrument's price associated with small 

83 # changes of the implied volatility surface shall be calculated to first order 

84 # within the pricing routine. Defaults to False. 

85 # vega_scale (float, optional): Size of implied volatility shift in the calculation of the change of the 

86 # instrument's price associated with implied volatility surface shifts as 

87 # difference quotient. Defaults to 0.01. 

88 # calc_cross_volga (bool, optional): Flag determining if the change of the instrument's price associated with 

89 # small changes of two implied volatility surfaces (both at first order) 

90 # shall be calculated within the pricing routine. Defaults to True. 

91 # TODO: why defaults to True? 

92 # calc_vanna (bool, optional): Flag determining if the change of the instrument's price associated with small 

93 # changes of the underlying's price and the implied volatility surface (both at 

94 # first order) shall be calculated within the pricing routine. Defaults to False. 

95 # TODO: why defaults to False in contrast to cross Gamma/Volga? 

96 # calc_theta (bool, optional): Flag determining if the change of the instrument's price associated with small 

97 # changes of the instrument's maturity shall be calculated to first order within 

98 # the pricing routine. Defaults to False. 

99 # theta_scale (float, optional): Size of maturity shift in the calculation of the change of the instrument's 

100 # price associated with maturity shifts as difference quotient. Defaults to 1.0 

101 # calc_spline (bool, optional): 

102 # calc_grid_sizes (bool, optional): 

103 # calc_implied_volatility (bool, optional): 

104 # management_delta_limit (float, optional): 

105 # calc_pricing_data (bool, optional): 

106 # calc_expected_cashflows (bool, optional): 

107 # calc_simulation_data (bool, optional): 

108 # calc_additional_information (bool, optional): 

109 # calc_z_spread (bool, optional): Flag determining if the instrument's z-spread shall be calculated within the 

110 # pricing routine. Defaults to False. 

111 # calc_yield_to_maturity (bool, optional): Flag determining if the instrument's yield-to-maturity shall be 

112 # calculated within the pricing routine. Defaults to False. 

113 # calc_convexity (bool, optional): Flag determining if the change of the instrument's price associated with 

114 # small changes of the zero rate curve shall be calculated to second order 

115 # within the pricing routine. Defaults to False. 

116 # max_expected_cashflow_date (_Union[date, datetime], optional): 

117 # cashflow_times (_List[_Union[date, datetime]], optional): 

118 # calc_macaulay_duration (bool, optional): Flag determining if the instrument's Macaulay duration shall be 

119 # calculated within the pricing routine. Defaults to False. 

120 # """ 

121 def __init__( 

122 self, 

123 calc_delta_gamma: bool = None, 

124 calc_cross_gamma: bool = None, 

125 calc_clean_price: bool = None, 

126 calc_rho: bool = None, 

127 rho_scale: float = None, 

128 calc_vega: bool = None, 

129 vega_scale: float = None, 

130 calc_cross_volga: bool = None, 

131 calc_vanna: bool = None, 

132 calc_theta: bool = None, 

133 theta_scale: float = None, 

134 calc_spline: bool = None, 

135 calc_grid_sizes: bool = None, 

136 calc_implied_volatility: bool = None, 

137 management_delta_limit: float = None, 

138 calc_pricing_data: bool = None, 

139 calc_expected_cashflows: bool = None, 

140 calc_simulation_data: bool = None, 

141 calc_additional_information: bool = None, 

142 calc_z_spread: bool = None, 

143 calc_yield_to_maturity: bool = None, 

144 calc_convexity: bool = None, 

145 max_expected_cashflow_date: _Union[date, datetime] = None, 

146 cashflow_times: _List[_Union[date, datetime]] = None, 

147 calc_macaulay_duration: bool = None, 

148 ): 

149 """ 

150 Defines the set of information, e.g. sensitivities, cashflow information, etc., to be calculated together with 

151 the instrument's price in the context of pricing. For some sensitivities the shift parameter for calculating 

152 the difference quotient (rather than the sensitivity in closed formula) is also stored in the pricing request 

153 object. 

154 

155 Args: TODO: Read carefully and double-check if these guessed descriptions are valid! 

156 calc_delta_gamma (bool, optional): Flag determining if the change of the instrument's price associated with 

157 small changes of the underlying's price shall be calculated to first (and 

158 second) order within the pricing routine. Defaults to None. 

159 TODO: also second order? delta_scale=? 

160 calc_cross_gamma (bool, optional): Flag determining if the change of the instrument's price associated with 

161 small changes of two underlyings' prices (both at fist order) shall be 

162 calculated within the pricing routine. Defaults to None. 

163 calc_clean_price (bool, optional): Flag determining if the instrument's clean price shall be calculated 

164 additional to its dirty price within the pricing routine. 

165 Defaults to None. 

166 calc_rho (bool, optional): Flag determining if the change of the instrument's price associated with small 

167 changes of the zero rate curve shall be calculated to first order within the 

168 pricing routine. Defaults to None. 

169 rho_scale (float, optional): Size of zero rate shift in the calculation of the change of the instrument's 

170 price associated with zero rate curve shifts as difference quotient. 

171 Defaults to None. 

172 calc_vega (bool, optional): Flag determining if the change of the instrument's price associated with small 

173 changes of the implied volatility surface shall be calculated to first order 

174 within the pricing routine. Defaults to None. 

175 vega_scale (float, optional): Size of implied volatility shift in the calculation of the change of the 

176 instrument's price associated with implied volatility surface shifts as 

177 difference quotient. Defaults to None. 

178 calc_cross_volga (bool, optional): Flag determining if the change of the instrument's price associated with 

179 small changes of two implied volatility surfaces (both at first order) 

180 shall be calculated within the pricing routine. Defaults to None. 

181 calc_vanna (bool, optional): Flag determining if the change of the instrument's price associated with small 

182 changes of the underlying's price and the implied volatility surface (both at 

183 first order) shall be calculated within the pricing routine. Defaults to None. 

184 calc_theta (bool, optional): Flag determining if the change of the instrument's price associated with small 

185 changes of the instrument's maturity shall be calculated to first order within 

186 the pricing routine. Defaults to None. 

187 theta_scale (float, optional): Size of maturity shift in the calculation of the change of the instrument's 

188 price associated with maturity shifts as difference quotient. 

189 Defaults to None 

190 calc_spline (bool, optional): 

191 calc_grid_sizes (bool, optional): 

192 calc_implied_volatility (bool, optional): 

193 management_delta_limit (float, optional): 

194 calc_pricing_data (bool, optional): 

195 calc_expected_cashflows (bool, optional): 

196 calc_simulation_data (bool, optional): 

197 calc_additional_information (bool, optional): 

198 calc_z_spread (bool, optional): Flag determining if the instrument's z-spread shall be calculated within the 

199 pricing routine. Defaults to None. 

200 calc_yield_to_maturity (bool, optional): Flag determining if the instrument's yield-to-maturity shall be 

201 calculated within the pricing routine. Defaults to None. 

202 calc_convexity (bool, optional): Flag determining if the change of the instrument's price associated with 

203 small changes of the zero rate curve shall be calculated to second order 

204 within the pricing routine. Defaults to None. 

205 max_expected_cashflow_date (_Union[date, datetime], optional): 

206 cashflow_times (_List[_Union[date, datetime]], optional): 

207 calc_macaulay_duration (bool, optional): Flag determining if the instrument's Macaulay duration shall be 

208 calculated within the pricing routine. Defaults to None. 

209 """ 

210 self._calc_delta_gamma = calc_delta_gamma 

211 self._calc_cross_gamma = calc_cross_gamma 

212 self._calc_clean_price = calc_clean_price 

213 self._calc_rho = calc_rho 

214 self._rho_scale = rho_scale 

215 self._calc_vega = calc_vega 

216 self._vega_scale = vega_scale 

217 self._calc_cross_volga = calc_cross_volga 

218 self._calc_vanna = calc_vanna 

219 self._calc_theta = calc_theta 

220 self._theta_scale = theta_scale 

221 self._calc_spline = calc_spline 

222 self._calc_grid_sizes = calc_grid_sizes 

223 self._calc_implied_volatility = calc_implied_volatility 

224 self._management_delta_limit = management_delta_limit 

225 self._calc_pricing_data = calc_pricing_data 

226 self._calc_expected_cashflows = calc_expected_cashflows 

227 self._calc_simulation_data = calc_simulation_data 

228 self._calc_additional_information = calc_additional_information 

229 self._calc_z_spread = calc_z_spread 

230 self._calc_yield_to_maturity = calc_yield_to_maturity 

231 self._calc_convexity = calc_convexity 

232 self._max_expected_cashflow_date = max_expected_cashflow_date 

233 self._cashflow_times = cashflow_times 

234 self._calc_macaulay_duration = calc_macaulay_duration 

235 

236 @property 

237 def _calc_delta_gamma(self): 

238 return self.__calc_delta_gamma 

239 

240 @_calc_delta_gamma.setter 

241 def _calc_delta_gamma(self, calc_delta_gamma: bool): 

242 if calc_delta_gamma is not None: 

243 if isinstance(calc_delta_gamma, bool): 

244 self.__calc_delta_gamma = calc_delta_gamma 

245 else: 

246 raise TypeError("'" + str(calc_delta_gamma) + "' must be of type bool!") 

247 

248 @property 

249 def _calc_cross_gamma(self): 

250 return self.__calc_cross_gamma 

251 

252 @_calc_cross_gamma.setter 

253 def _calc_cross_gamma(self, calc_cross_gamma: bool): 

254 if calc_cross_gamma is not None: 

255 if isinstance(calc_cross_gamma, bool): 

256 self.__calc_cross_gamma = calc_cross_gamma 

257 if self._calc_cross_gamma: 

258 self.calc_delta_gamma = True 

259 else: 

260 raise TypeError("'" + str(calc_cross_gamma) + "' must be of type bool!") 

261 

262 @property 

263 def _calc_clean_price(self): 

264 return self.__calc_clean_price 

265 

266 @_calc_clean_price.setter 

267 def _calc_clean_price(self, calc_clean_price: bool): 

268 if calc_clean_price is not None: 

269 if isinstance(calc_clean_price, bool): 

270 self.__calc_clean_price = calc_clean_price 

271 else: 

272 raise TypeError("'" + str(calc_clean_price) + "' must be of type bool!") 

273 

274 @property 

275 def _calc_rho(self): 

276 return self.__calc_rho 

277 

278 @_calc_rho.setter 

279 def _calc_rho(self, calc_rho: bool): 

280 if calc_rho is not None: 

281 if isinstance(calc_rho, bool): 

282 self.__calc_rho = calc_rho 

283 if self._calc_rho & ~hasattr(self, "rho_scale"): 

284 self.rho_scale = 0.0001 

285 else: 

286 raise TypeError("'" + str(calc_rho) + "' must be of type bool!") 

287 

288 @property 

289 def _rho_scale(self): 

290 return self.__rho_scale 

291 

292 @_rho_scale.setter 

293 def _rho_scale(self, rho_scale: float): 

294 if rho_scale is not None: 

295 if isinstance(rho_scale, (int, float)): 

296 self.__rho_scale = float(rho_scale) 

297 self.calc_rho = True 

298 else: 

299 raise TypeError("'" + str(rho_scale) + "' must be a number (int or float)!") 

300 

301 @property 

302 def _calc_vega(self): 

303 return self.__calc_vega 

304 

305 @_calc_vega.setter 

306 def _calc_vega(self, calc_vega: bool): 

307 if calc_vega is not None: 

308 if isinstance(calc_vega, bool): 

309 self.__calc_vega = calc_vega 

310 if self._calc_vega & ~hasattr(self, "vega_scale"): 

311 self.vega_scale = 0.01 

312 else: 

313 raise TypeError("'" + str(calc_vega) + "' must be of type bool!") 

314 

315 @property 

316 def _vega_scale(self): 

317 return self.__vega_scale 

318 

319 @_vega_scale.setter 

320 def _vega_scale(self, vega_scale: float): 

321 if vega_scale is not None: 

322 if isinstance(vega_scale, (int, float)): 

323 self.__vega_scale = float(vega_scale) 

324 self.calc_vega = True 

325 else: 

326 raise TypeError("'" + str(vega_scale) + "' must be a number (int or float)!") 

327 

328 @property 

329 def _calc_cross_volga(self): 

330 return self.__calc_cross_volga 

331 

332 @_calc_cross_volga.setter 

333 def _calc_cross_volga(self, calc_cross_volga: bool): 

334 if calc_cross_volga is not None: 

335 if isinstance(calc_cross_volga, bool): 

336 self.__calc_cross_volga = calc_cross_volga 

337 if self._calc_cross_volga: 

338 self.calc_vega = True 

339 if not hasattr(self, "vega_scale"): 

340 self.vega_scale = 0.01 

341 else: 

342 raise TypeError("'" + str(calc_cross_volga) + "' must be of type bool!") 

343 

344 @property 

345 def _calc_vanna(self): 

346 return self.__calc_vanna 

347 

348 @_calc_vanna.setter 

349 def _calc_vanna(self, calc_vanna: bool): 

350 if calc_vanna is not None: 

351 if isinstance(calc_vanna, bool): 

352 self.__calc_vanna = calc_vanna 

353 if self._calc_vanna: 

354 self.calc_vega = True 

355 if not hasattr(self, "vega_scale"): 

356 self.vega_scale = 0.01 

357 else: 

358 raise TypeError("'" + str(calc_vanna) + "' must be of type bool!") 

359 

360 @property 

361 def _calc_theta(self): 

362 return self.__calc_theta 

363 

364 @_calc_theta.setter 

365 def _calc_theta(self, calc_theta: bool): 

366 if calc_theta is not None: 

367 if isinstance(calc_theta, bool): 

368 self.__calc_theta = calc_theta 

369 if self._calc_theta & ~hasattr(self, "theta_scale"): 

370 self.theta_scale = 1.0 

371 else: 

372 raise TypeError("'" + str(calc_theta) + "' must be of type bool!") 

373 

374 @property 

375 def _theta_scale(self): 

376 return self.__theta_scale 

377 

378 @_theta_scale.setter 

379 def _theta_scale(self, theta_scale: float): 

380 if theta_scale is not None: 

381 if isinstance(theta_scale, (int, float)): 

382 self.__theta_scale = float(theta_scale) 

383 self.calc_theta = True 

384 else: 

385 raise TypeError("'" + str(theta_scale) + "' must be a number (int or float)!") 

386 

387 @property 

388 def _calc_spline(self): 

389 return self.__calc_spline 

390 

391 @_calc_spline.setter 

392 def _calc_spline(self, calc_spline: bool): 

393 if calc_spline is not None: 

394 if isinstance(calc_spline, bool): 

395 self.__calc_spline = calc_spline 

396 else: 

397 raise TypeError("'" + str(calc_spline) + "' must be of type bool!") 

398 

399 @property 

400 def _calc_grid_sizes(self): 

401 return self.__calc_grid_sizes 

402 

403 @_calc_grid_sizes.setter 

404 def _calc_grid_sizes(self, calc_grid_sizes: bool): 

405 if calc_grid_sizes is not None: 

406 if isinstance(calc_grid_sizes, bool): 

407 self.__calc_grid_sizes = calc_grid_sizes 

408 else: 

409 raise TypeError("'" + str(calc_grid_sizes) + "' must be of type bool!") 

410 

411 @property 

412 def _calc_implied_volatility(self): 

413 return self.__calc_implied_volatility 

414 

415 @_calc_implied_volatility.setter 

416 def _calc_implied_volatility(self, calc_implied_volatility: bool): 

417 if calc_implied_volatility is not None: 

418 if isinstance(calc_implied_volatility, bool): 

419 self.__calc_implied_volatility = calc_implied_volatility 

420 else: 

421 raise TypeError("'" + str(calc_implied_volatility) + "' must be of type bool!") 

422 

423 @property 

424 def _management_delta_limit(self): 

425 return self.__management_delta_limit 

426 

427 @_management_delta_limit.setter 

428 def _management_delta_limit(self, management_delta_limit: float): 

429 self.__management_delta_limit = management_delta_limit 

430 

431 @property 

432 def _calc_pricing_data(self): 

433 return self.__calc_pricing_data 

434 

435 @_calc_pricing_data.setter 

436 def _calc_pricing_data(self, calc_pricing_data: bool): 

437 if calc_pricing_data is not None: 

438 if isinstance(calc_pricing_data, bool): 

439 self.__calc_pricing_data = calc_pricing_data 

440 else: 

441 raise TypeError("'" + str(calc_pricing_data) + "' must be of type bool!") 

442 

443 @property 

444 def _calc_expected_cashflows(self): 

445 return self.__calc_expected_cashflows 

446 

447 @_calc_expected_cashflows.setter 

448 def _calc_expected_cashflows(self, calc_expected_cashflows: bool): 

449 if calc_expected_cashflows is not None: 

450 if isinstance(calc_expected_cashflows, bool): 

451 self.__calc_expected_cashflows = calc_expected_cashflows 

452 else: 

453 raise TypeError("'" + str(calc_expected_cashflows) + "' must be of type bool!") 

454 

455 @property 

456 def _calc_simulation_data(self): 

457 return self.__calc_simulation_data 

458 

459 @_calc_simulation_data.setter 

460 def _calc_simulation_data(self, calc_simulation_data: bool): 

461 if calc_simulation_data is not None: 

462 if isinstance(calc_simulation_data, bool): 

463 self.__calc_simulation_data = calc_simulation_data 

464 else: 

465 raise TypeError("'" + str(calc_simulation_data) + "' must be of type bool!") 

466 

467 @property 

468 def _calc_additional_information(self): 

469 return self.__calc_additional_information 

470 

471 @_calc_additional_information.setter 

472 def _calc_additional_information(self, calc_additional_information: bool): 

473 if calc_additional_information is not None: 

474 if isinstance(calc_additional_information, bool): 

475 self.__calc_additional_information = calc_additional_information 

476 else: 

477 raise TypeError("'" + str(calc_additional_information) + "' must be of type bool!") 

478 

479 @property 

480 def _calc_z_spread(self): 

481 return self.__calc_z_spread 

482 

483 @_calc_z_spread.setter 

484 def _calc_z_spread(self, calc_z_spread: bool): 

485 if calc_z_spread is not None: 

486 if isinstance(calc_z_spread, bool): 

487 self.__calc_z_spread = calc_z_spread 

488 else: 

489 raise TypeError("'" + str(calc_z_spread) + "' must be of type bool!") 

490 

491 @property 

492 def _calc_yield_to_maturity(self): 

493 return self.__calc_yield_to_maturity 

494 

495 @_calc_yield_to_maturity.setter 

496 def _calc_yield_to_maturity(self, calc_yield_to_maturity: bool): 

497 if calc_yield_to_maturity is not None: 

498 if isinstance(calc_yield_to_maturity, bool): 

499 self.__calc_yield_to_maturity = calc_yield_to_maturity 

500 else: 

501 raise TypeError("'" + str(calc_yield_to_maturity) + "' must be of type bool!") 

502 

503 @property 

504 def _calc_convexity(self): 

505 return self.__calc_convexity 

506 

507 @_calc_convexity.setter 

508 def _calc_convexity(self, calc_convexity: bool): 

509 if calc_convexity is not None: 

510 if isinstance(calc_convexity, bool): 

511 self.__calc_convexity = calc_convexity 

512 if self._calc_convexity: 

513 self.calc_rho = True 

514 if not hasattr(self, "rho_scale"): 

515 self.rho_scale = 0.0001 

516 else: 

517 raise TypeError("'" + str(calc_convexity) + "' must be of type bool!") 

518 

519 @property 

520 def _max_expected_cashflow_date(self): 

521 return self.__max_expected_cashflow_date 

522 

523 @_max_expected_cashflow_date.setter 

524 def _max_expected_cashflow_date(self, max_expected_cashflow_date: _Union[date, datetime]): 

525 if max_expected_cashflow_date is not None: 

526 if isinstance(max_expected_cashflow_date, datetime) | isinstance(max_expected_cashflow_date, date): 

527 self.__max_expected_cashflow_date = datetime_to_date(max_expected_cashflow_date) 

528 else: 

529 raise TypeError("'" + str(max_expected_cashflow_date) + "' must be of type datetime or date!") 

530 

531 @property 

532 def _cashflow_times(self): 

533 return self.__cashflow_times 

534 

535 @_cashflow_times.setter 

536 def _cashflow_times(self, cashflow_times: _List[_Union[date, datetime]]): 

537 if cashflow_times is not None: 

538 if isinstance(cashflow_times, list) & (isinstance(cashflow_times[0], datetime) | isinstance(cashflow_times[0], date)): 

539 self.__cashflow_times = datetime_to_date_list(cashflow_times) 

540 else: 

541 raise TypeError("'" + str(cashflow_times) + "' must be of type list of datetime or date!") 

542 

543 @property 

544 def _calc_macaulay_duration(self): 

545 return self.__calc_macaulay_duration 

546 

547 @_calc_macaulay_duration.setter 

548 def _calc_macaulay_duration(self, calc_macaulay_duration: bool): 

549 if calc_macaulay_duration is not None: 

550 if isinstance(calc_macaulay_duration, bool): 

551 self.__calc_macaulay_duration = calc_macaulay_duration 

552 else: 

553 raise TypeError("'" + str(calc_macaulay_duration) + "' must be of type bool!") 

554 

555 

556class BondPricingRequest(PricingRequest): 

557 def __init__( 

558 self, 

559 calc_clean_price: bool = False, 

560 calc_rho: bool = False, 

561 rho_scale: float = None, 

562 calc_theta: bool = False, 

563 theta_scale: float = None, 

564 calc_yield_to_maturity: bool = False, 

565 calc_convexity: bool = False, 

566 calc_macaulay_duration: bool = False, 

567 calc_z_spread: bool = False, 

568 ): 

569 """ 

570 Configuration of set of information to be calculated together with the bond's dirty price. In restricts the 

571 general PricingRequest to the sub-set relevant for the pricing of bonds. 

572 """ 

573 PricingRequest.__init__( 

574 self, 

575 calc_clean_price=calc_clean_price, 

576 calc_rho=calc_rho, 

577 rho_scale=rho_scale, 

578 calc_theta=calc_theta, 

579 theta_scale=theta_scale, 

580 calc_yield_to_maturity=calc_yield_to_maturity, 

581 calc_convexity=calc_convexity, 

582 calc_macaulay_duration=calc_macaulay_duration, 

583 calc_z_spread=calc_z_spread, 

584 ) 

585 

586 

587class ForwardRateAgreementPricingRequest(PricingRequest): 

588 

589 def __init__(self): 

590 """Configuration of set of information to be calculated for the Forward Rate Agreement's price. 

591 Restrict the general PricingRequest to the sub-set relevant for the pricing of FRAs. 

592 """ 

593 

594 # super.__init__(self) 

595 pass 

596 

597 

598class InterestRateSwapPricingRequest(PricingRequest): 

599 

600 def __init__(self): 

601 """Configuration of set of information to be calculated for the Swap's price. 

602 Restrict the general PricingRequest to the sub-set relevant for the pricing of swaps. 

603 """ 

604 

605 # super.__init__(self) 

606 pass 

607 

608 

609if __name__ == "__main__": 

610 bond_pricing_request = BondPricingRequest()