33from typing import TYPE_CHECKING
44
55from rateslib import defaults
6+ from rateslib .curves ._parsers import _validate_obj_not_no_input
67from rateslib .dual import Variable , gradient
78from rateslib .dual .utils import _dual_float , _to_number
89from rateslib .enums .generics import NoInput , _drb
1516from rateslib .instruments .protocols .kwargs import _convert_to_schedule_kwargs , _KWArgs
1617from rateslib .instruments .protocols .pricing import (
1718 _Curves ,
18- _maybe_get_curve_or_dict_maybe_from_solver ,
19+ _maybe_get_curve_maybe_from_solver ,
1920 _Vol ,
2021)
2122from rateslib .legs import FixedLeg
2425if TYPE_CHECKING :
2526 from rateslib .typing import ( # pragma: no cover
2627 CalInput ,
27- CurveOption_ ,
28- Curves_ ,
28+ CurvesT_ ,
2929 DualTypes ,
3030 DualTypes_ ,
3131 FXForwards_ ,
3232 Number ,
33+ Sequence ,
3334 Solver_ ,
3435 VolT_ ,
3536 _BaseLeg ,
@@ -200,7 +201,7 @@ def leg1(self) -> FixedLeg:
200201 return self ._leg1
201202
202203 @property
203- def legs (self ) -> list [_BaseLeg ]:
204+ def legs (self ) -> Sequence [_BaseLeg ]:
204205 """A list of the *Legs* of the *Instrument*."""
205206 return self ._legs
206207
@@ -217,7 +218,7 @@ def __init__(
217218 convention : str_ = NoInput (0 ),
218219 settle : int_ = NoInput (0 ),
219220 calc_mode : BillCalcMode | str_ = NoInput (0 ),
220- curves : Curves_ = NoInput (0 ),
221+ curves : CurvesT_ = NoInput (0 ),
221222 spec : str_ = NoInput (0 ),
222223 metric : str = "price" ,
223224 ):
@@ -271,7 +272,7 @@ def __init__(
271272 def _parse_vol (self , vol : VolT_ ) -> _Vol :
272273 return _Vol ()
273274
274- def _parse_curves (self , curves : CurveOption_ ) -> _Curves :
275+ def _parse_curves (self , curves : CurvesT_ ) -> _Curves :
275276 """
276277 A Bill has one curve requirements: a disc_curve.
277278
@@ -298,23 +299,25 @@ def _parse_curves(self, curves: CurveOption_) -> _Curves:
298299 raise ValueError (
299300 f"{ type (self ).__name__ } requires only 1 curve types. Got { len (curves )} ."
300301 )
302+ elif isinstance (curves , _Curves ):
303+ return curves
301304 else : # `curves` is just a single input which is copied across all curves
302305 return _Curves (
303- disc_curve = curves ,
306+ disc_curve = curves , # type: ignore[arg-type]
304307 )
305308
306309 def rate (
307310 self ,
308311 * ,
309- curves : Curves_ = NoInput (0 ),
312+ curves : CurvesT_ = NoInput (0 ),
310313 solver : Solver_ = NoInput (0 ),
311314 fx : FXForwards_ = NoInput (0 ),
312315 vol : VolT_ = NoInput (0 ),
313316 base : str_ = NoInput (0 ),
314317 settlement : datetime_ = NoInput (0 ),
315318 forward : datetime_ = NoInput (0 ),
316319 metric : str_ = NoInput (0 ),
317- ) -> DualTypes_ :
320+ ) -> DualTypes :
318321 """
319322 Return various pricing metrics of the security calculated from
320323 :class:`~rateslib.curves.Curve` s.
@@ -345,17 +348,20 @@ def rate(
345348 -------
346349 float, Dual, Dual2
347350 """
348- disc_curve_ = _maybe_get_curve_or_dict_maybe_from_solver (
349- solver = solver ,
350- name = "disc_curve" ,
351- curves = self ._parse_curves (curves ),
352- curves_meta = self .kwargs .meta ["curves" ],
351+ disc_curve_ = _validate_obj_not_no_input (
352+ _maybe_get_curve_maybe_from_solver (
353+ solver = solver ,
354+ name = "disc_curve" ,
355+ curves = self ._parse_curves (curves ),
356+ curves_meta = self .kwargs .meta ["curves" ],
357+ ),
358+ "disc_curve" ,
353359 )
354360 settlement_ = self ._maybe_get_settlement (settlement = settlement , disc_curve = disc_curve_ )
355361
356362 # scale price to par 100 and make a fwd adjustment according to curve
357363 price = (
358- self .npv (curves = curves , solver = solver , fx = fx , base = base , local = False )
364+ self .npv (curves = curves , solver = solver , local = False ) # type: ignore[operator]
359365 * 100
360366 / (- self .leg1 .settlement_params .notional * disc_curve_ [settlement_ ])
361367 )
@@ -387,7 +393,7 @@ def simple_rate(self, price: DualTypes, settlement: datetime) -> DualTypes:
387393 """
388394 acc_frac = self .kwargs .meta ["calc_mode" ]._settle_accrual (self , settlement , 0 )
389395 dcf = (1 - acc_frac ) * self .leg1 ._regular_periods [0 ].period_params .dcf
390- return ((100 / price - 1 ) / dcf ) * 100
396+ return ((100 / price - 1 ) / dcf ) * 100 # type: ignore[no-any-return]
391397
392398 def discount_rate (self , price : DualTypes , settlement : datetime ) -> DualTypes :
393399 """
@@ -407,7 +413,7 @@ def discount_rate(self, price: DualTypes, settlement: datetime) -> DualTypes:
407413 acc_frac = self .kwargs .meta ["calc_mode" ]._settle_accrual (self , settlement , 0 )
408414 dcf = (1 - acc_frac ) * self .leg1 ._regular_periods [0 ].period_params .dcf
409415 rate = ((1 - price / 100 ) / dcf ) * 100
410- return rate
416+ return rate # type: ignore[no-any-return]
411417
412418 def price (
413419 self ,
@@ -444,14 +450,14 @@ def price(
444450 def _price_discount (self , rate : DualTypes , settlement : datetime ) -> DualTypes :
445451 acc_frac = self .kwargs .meta ["calc_mode" ]._settle_accrual (self , settlement , 0 )
446452 dcf = (1 - acc_frac ) * self .leg1 ._regular_periods [0 ].period_params .dcf
447- return 100 - rate * dcf
453+ return 100 - rate * dcf # type: ignore[no-any-return]
448454
449455 def _price_simple (self , rate : DualTypes , settlement : datetime ) -> DualTypes :
450456 acc_frac = self .kwargs .meta ["calc_mode" ]._settle_accrual (self , settlement , 0 )
451457 dcf = (1 - acc_frac ) * self .leg1 ._regular_periods [0 ].period_params .dcf
452- return 100 / (1 + rate * dcf / 100 )
458+ return 100 / (1 + rate * dcf / 100 ) # type: ignore[no-any-return]
453459
454- def ytm (
460+ def ytm ( # type: ignore[override]
455461 self ,
456462 price : DualTypes ,
457463 settlement : datetime ,
@@ -492,11 +498,11 @@ def ytm(
492498 while quasi_ustart > settlement :
493499 quasi_ustart = frequency .uprevious (quasi_ustart )
494500
495- equiv_bond = FixedRateBond (
501+ equiv_bond = FixedRateBond ( # type: ignore[abstract]
496502 effective = quasi_ustart ,
497503 termination = self .leg1 .schedule .utermination ,
498504 fixed_rate = 0.0 ,
499- ** calc_mode_ ._ytm_clone_kwargs ,
505+ ** calc_mode_ ._ytm_clone_kwargs , # type: ignore[arg-type]
500506 )
501507 return equiv_bond .ytm (price , settlement )
502508
@@ -527,9 +533,7 @@ def duration(self, ytm: DualTypes, settlement: datetime, metric: str = "risk") -
527533 # TODO: this is not AD safe: returns only float
528534 ytm_ : float = _dual_float (ytm )
529535 if metric == "duration" :
530- price_ : Dual | Dual2 = _to_number ( # type: ignore[assignment]
531- self .price (Variable (ytm_ , ["y" ]), settlement , dirty = True )
532- )
536+ price_ = _to_number (self .price (Variable (ytm_ , ["y" ]), settlement , dirty = True ))
533537 freq = _get_frequency (
534538 self .kwargs .meta ["frequency" ],
535539 self .leg1 .schedule .utermination .day ,
0 commit comments