Skip to content

Commit 8ec7de0

Browse files
authored
DOC: updates for components (#152) (#1075)
1 parent 23c3bb6 commit 8ec7de0

File tree

7 files changed

+356
-104
lines changed

7 files changed

+356
-104
lines changed

python/rateslib/instruments/components/irs.py

Lines changed: 225 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,45 +33,224 @@
3333
float_,
3434
int_,
3535
str_,
36+
_BaseLeg,
3637
)
3738

3839

3940
class IRS(_BaseInstrument):
41+
"""
42+
Create an *interest rate swap (IRS)* composing a :class:`~rateslib.legs.components.FixedLeg`
43+
and a :class:`~rateslib.legs.components.FloatLeg`.
44+
45+
.. role:: red
46+
47+
.. role:: green
48+
49+
Parameters
50+
----------
51+
.
52+
53+
.. note::
54+
55+
The following define generalised **scheduling** parameters.
56+
57+
effective : datetime, :red:`required`
58+
The unadjusted effective date. If given as adjusted, unadjusted alternatives may be
59+
inferred.
60+
termination : datetime, str, :red:`required`
61+
The unadjusted termination date. If given as adjusted, unadjusted alternatives may be
62+
inferred. If given as string tenor will be calculated from ``effective``.
63+
frequency : Frequency, str, :red:`required`
64+
The frequency of the schedule.
65+
If given as string will derive a :class:`~rateslib.scheduling.Frequency` aligning with:
66+
monthly ("M"), quarterly ("Q"), semi-annually ("S"), annually("A") or zero-coupon ("Z"), or
67+
a set number of calendar or business days ("_D", "_B"), weeks ("_W"), months ("_M") or
68+
years ("_Y").
69+
Where required, the :class:`~rateslib.scheduling.RollDay` is derived as per ``roll``
70+
and business day calendar as per ``calendar``.
71+
stub : StubInference, str in {"ShortFront", "LongFront", "ShortBack", "LongBack"}, :green:`optional`
72+
The stub type used if stub inference is required. If given as string will derive a
73+
:class:`~rateslib.scheduling.StubInference`.
74+
front_stub : datetime, :green:`optional`
75+
The unadjusted date for the start stub period. If given as adjusted, unadjusted
76+
alternatives may be inferred.
77+
back_stub : datetime, :green:`optional`
78+
The unadjusted date for the back stub period. If given as adjusted, unadjusted
79+
alternatives may be inferred.
80+
See notes for combining ``stub``, ``front_stub`` and ``back_stub``
81+
and any automatic stub inference.
82+
roll : RollDay, int in [1, 31], str in {"eom", "imm", "som"}, :green:`optional`
83+
The roll day of the schedule. If not given or not available in ``frequency`` will be
84+
inferred for monthly frequency variants.
85+
eom : bool, :green:`optional`
86+
Use an end of month preference rather than regular rolls for ``roll`` inference. Set by
87+
default. Not required if ``roll`` is defined.
88+
modifier : Adjuster, str in {"NONE", "F", "MF", "P", "MP"}, :green:`optional`
89+
The :class:`~rateslib.scheduling.Adjuster` used for adjusting unadjusted schedule dates
90+
into adjusted dates. If given as string must define simple date rolling rules.
91+
calendar : calendar, str, :green:`optional`
92+
The business day calendar object to use. If string will call
93+
:meth:`~rateslib.scheduling.get_calendar`.
94+
payment_lag: Adjuster, int, :green:`optional`
95+
The :class:`~rateslib.scheduling.Adjuster` to use to map adjusted schedule dates into
96+
a payment date. If given as integer will define the number of business days to
97+
lag payments by.
98+
payment_lag_exchange: Adjuster, int, :green:`optional`
99+
The :class:`~rateslib.scheduling.Adjuster` to use to map adjusted schedule dates into
100+
additional payment date. If given as integer will define the number of business days to
101+
lag payments by.
102+
ex_div: Adjuster, int, :green:`optional`
103+
The :class:`~rateslib.scheduling.Adjuster` to use to map adjusted schedule dates into
104+
additional dates, which may be used, for example by fixings schedules. If given as integer
105+
will define the number of business days to lag dates by.
106+
convention: str, :green:`optional (set by 'defaults')`
107+
The day count convention applied to calculations of period accrual dates.
108+
See :meth:`~rateslib.scheduling.dcf`.
109+
leg2_effective : datetime, :green:`optional (inherited from leg1)`
110+
leg2_termination : datetime, str, :green:`optional (inherited from leg1)`
111+
leg2_frequency : Frequency, str, :green:`optional (inherited from leg1)`
112+
leg2_stub : StubInference, str, :green:`optional (inherited from leg1)`
113+
leg2_front_stub : datetime, :green:`optional (inherited from leg1)`
114+
leg2_back_stub : datetime, :green:`optional (inherited from leg1)`
115+
leg2_roll : RollDay, int, str, :green:`optional (inherited from leg1)`
116+
leg2_eom : bool, :green:`optional (inherited from leg1)`
117+
leg2_modifier : Adjuster, str, :green:`optional (inherited from leg1)`
118+
leg2_calendar : calendar, str, :green:`optional (inherited from leg1)`
119+
leg2_payment_lag: Adjuster, int, :green:`optional (inherited from leg1)`
120+
leg2_payment_lag_exchange: Adjuster, int, :green:`optional (inherited from leg1)`
121+
leg2_ex_div: Adjuster, int, :green:`optional (inherited from leg1)`
122+
leg2_convention: str, :green:`optional (inherited from leg1)`
123+
124+
.. note::
125+
126+
The following define generalised **settlement** parameters.
127+
128+
currency : str, :green:`optional (set by 'defaults')`
129+
The local settlement currency of the *Instrument* (3-digit code).
130+
notional : float, Dual, Dual2, Variable, :green:`optional (set by 'defaults')`
131+
The initial leg notional, defined in units of *reference currency*.
132+
amortization: float, Dual, Dual2, Variable, str, Amortization, :green:`optional (set as zero)`
133+
Set a non-constant notional per *Period*. If a scalar value, adjusts the ``notional`` of
134+
each successive period by that same value. Should have
135+
sign equal to that of notional if the notional is to reduce towards zero.
136+
leg2_notional : float, Dual, Dual2, Variable, :green:`optional (negatively inherited from leg1)`
137+
leg2_amortization : float, Dual, Dual2, Variable, str, Amortization, :green:`optional (negatively inherited from leg1)`
138+
139+
.. note::
140+
141+
The following are **rate parameters**.
142+
143+
fixed_rate : float or None
144+
The fixed rate applied to the :class:`~rateslib.legs.FixedLeg`. If `None`
145+
will be set to mid-market when curves are provided.
146+
leg2_fixing_method: FloatFixingMethod, str, :green:`optional (set by 'defaults')`
147+
The :class:`~rateslib.enums.parameters.FloatFixingMethod` describing the determination
148+
of the floating rate for each period.
149+
leg2_method_param: int, :green:`optional (set by 'defaults')`
150+
A specific parameter that is used by the specific ``fixing_method``.
151+
leg2_fixing_frequency: Frequency, str, :green:`optional (set by 'frequency' or '1B')`
152+
The :class:`~rateslib.scheduling.Frequency` as a component of the
153+
:class:`~rateslib.data.fixings.FloatRateIndex`. If not given is assumed to match the
154+
frequency of the schedule for an IBOR type ``fixing_method`` or '1B' if RFR type.
155+
leg2_fixing_series: FloatRateSeries, str, :green:`optional (implied by other parameters)`
156+
The :class:`~rateslib.data.fixings.FloatRateSeries` as a component of the
157+
:class:`~rateslib.data.fixings.FloatRateIndex`. If not given inherits attributes given
158+
such as the ``calendar``, ``convention``, ``method_param`` etc.
159+
leg2_float_spread: float, Dual, Dual2, Variable, :green:`optional (set as 0.0)`
160+
The amount (in bps) added to the rate in each period rate determination.
161+
leg2_spread_compound_method: SpreadCompoundMethod, str, :green:`optional (set by 'defaults')`
162+
The :class:`~rateslib.enums.parameters.SpreadCompoundMethod` used in the calculation
163+
of the period rate when combining a ``float_spread``. Used **only** with RFR type
164+
``fixing_method``.
165+
leg2_rate_fixings: float, Dual, Dual2, Variable, Series, str, :green:`optional`
166+
See XXX (working with fixings).
167+
The value of the rate fixing. If a scalar, is used directly. If a string identifier, links
168+
to the central ``fixings`` object and data loader.
169+
170+
.. note::
171+
172+
The following are **meta parameters**.
173+
174+
curves : XXX
175+
Pricing objects passed directly to the *Instrument's* methods' ``curves`` argument.
176+
spec: str, :green:`optional`
177+
A collective group of parameters. See
178+
:ref:`default argument specifications <defaults-arg-input>`.
179+
180+
Notes
181+
------
182+
The various different ``leg2_fixing_methods``, which describe how an
183+
individual *FloatPeriod* calculates its *rate*, are
184+
fully documented in the notes for the :class:`~rateslib.periods.FloatPeriod`.
185+
These configurations provide the mechanics to differentiate between IBOR swaps, and
186+
OISs with different mechanisms such as *payment delay*, *observation shift*,
187+
*lockout*, and/or *averaging*.
188+
Similarly some information is provided in that same link regarding
189+
``leg2_fixings``, but a cookbook article is also produced for
190+
:ref:`working with fixings <cook-fixings-doc>`.
191+
192+
Examples
193+
--------
194+
Construct a curve to price the example.
195+
196+
"""
197+
40198
_rate_scalar = 1.0
41199

42200
@property
43201
def fixed_rate(self) -> DualTypes_:
202+
"""The fixed rate parameter of the composited
203+
:class:`~rateslib.legs.components.FixedLeg`."""
44204
return self.leg1.fixed_rate
45205

46206
@fixed_rate.setter
47207
def fixed_rate(self, value: DualTypes_) -> None:
48208
self.kwargs.leg1["fixed_rate"] = value
49209
self.leg1.fixed_rate = value
50210

51-
@property
52-
def float_spread(self) -> NoReturn:
53-
raise AttributeError(f"Attribute not available on {type(self).__name__}")
211+
# @property
212+
# def float_spread(self) -> NoReturn:
213+
# """The float spread parameter of the composited
214+
# :class:`~rateslib.legs.components.FloatLeg`."""
215+
# raise AttributeError(f"Attribute not available on {type(self).__name__}")
54216

55-
@property
56-
def leg2_fixed_rate(self) -> NoReturn:
57-
raise AttributeError(f"Attribute not available on {type(self).__name__}")
217+
# @property
218+
# def leg2_fixed_rate(self) -> NoReturn:
219+
# raise AttributeError(f"Attribute not available on {type(self).__name__}")
58220

59221
@property
60222
def leg2_float_spread(self) -> DualTypes_:
223+
"""The float spread parameter of the composited
224+
:class:`~rateslib.legs.components.FloatLeg`."""
61225
return self.leg2.float_spread
62226

63227
@leg2_float_spread.setter
64228
def leg2_float_spread(self, value: DualTypes) -> None:
65229
self.kwargs.leg2["float_spread"] = value
66230
self.leg2.float_spread = value
67231

232+
@property
233+
def leg1(self) -> FixedLeg:
234+
"""The :class:`~rateslib.legs.components.FixedLeg` of the *Instrument*."""
235+
return self._leg1
236+
237+
@property
238+
def leg2(self) -> FloatLeg:
239+
"""The :class:`~rateslib.legs.components.FloatLeg` of the *Instrument*."""
240+
return self._leg2
241+
242+
@property
243+
def legs(self) -> list[_BaseLeg]:
244+
"""A list of the *Legs* of the *Instrument*."""
245+
return self._legs
246+
68247
def __init__(
69248
self,
249+
# scheduling
70250
effective: datetime_ = NoInput(0),
71251
termination: datetime | str_ = NoInput(0),
72252
frequency: Frequency | str_ = NoInput(0),
73253
*,
74-
fixed_rate: DualTypes_ = NoInput(0),
75254
stub: str_ = NoInput(0),
76255
front_stub: datetime_ = NoInput(0),
77256
back_stub: datetime_ = NoInput(0),
@@ -82,15 +261,7 @@ def __init__(
82261
payment_lag: int_ = NoInput(0),
83262
payment_lag_exchange: int_ = NoInput(0),
84263
ex_div: int_ = NoInput(0),
85-
notional: float_ = NoInput(0),
86-
currency: str_ = NoInput(0),
87-
amortization: float_ = NoInput(0),
88264
convention: str_ = NoInput(0),
89-
leg2_float_spread: DualTypes_ = NoInput(0),
90-
leg2_spread_compound_method: str_ = NoInput(0),
91-
leg2_rate_fixings: FixingsRates_ = NoInput(0), # type: ignore[type-var]
92-
leg2_fixing_method: str_ = NoInput(0),
93-
leg2_method_param: int_ = NoInput(0),
94265
leg2_effective: datetime_ = NoInput(1),
95266
leg2_termination: datetime | str_ = NoInput(1),
96267
leg2_frequency: Frequency | str_ = NoInput(1),
@@ -103,53 +274,69 @@ def __init__(
103274
leg2_calendar: CalInput = NoInput(1),
104275
leg2_payment_lag: int_ = NoInput(1),
105276
leg2_payment_lag_exchange: int_ = NoInput(1),
277+
leg2_ex_div: int_ = NoInput(1),
278+
leg2_convention: str_ = NoInput(1),
279+
# settlement parameters
280+
currency: str_ = NoInput(0),
281+
notional: float_ = NoInput(0),
282+
amortization: float_ = NoInput(0),
106283
leg2_notional: float_ = NoInput(-1),
107284
leg2_amortization: float_ = NoInput(-1),
108-
leg2_convention: str_ = NoInput(1),
109-
leg2_ex_div: int_ = NoInput(1),
285+
# rate parameters
286+
fixed_rate: DualTypes_ = NoInput(0),
287+
leg2_float_spread: DualTypes_ = NoInput(0),
288+
leg2_spread_compound_method: str_ = NoInput(0),
289+
leg2_rate_fixings: FixingsRates_ = NoInput(0), # type: ignore[type-var]
290+
leg2_fixing_method: str_ = NoInput(0),
291+
leg2_method_param: int_ = NoInput(0),
292+
# meta parameters
110293
curves: Curves_ = NoInput(0),
111294
spec: str_ = NoInput(0),
112295
) -> None:
113296
user_args = dict(
297+
# scheduling
114298
effective=effective,
299+
leg2_effective=leg2_effective,
115300
termination=termination,
301+
leg2_termination=leg2_termination,
116302
frequency=frequency,
117-
fixed_rate=fixed_rate,
303+
leg2_frequency=leg2_frequency,
118304
stub=stub,
305+
leg2_stub=leg2_stub,
119306
front_stub=front_stub,
307+
leg2_front_stub=leg2_front_stub,
120308
back_stub=back_stub,
309+
leg2_back_stub=leg2_back_stub,
121310
roll=roll,
311+
leg2_roll=leg2_roll,
122312
eom=eom,
313+
leg2_eom=leg2_eom,
123314
modifier=modifier,
315+
leg2_modifier=leg2_modifier,
124316
calendar=calendar,
317+
leg2_calendar=leg2_calendar,
125318
payment_lag=payment_lag,
319+
leg2_payment_lag=leg2_payment_lag,
126320
payment_lag_exchange=payment_lag_exchange,
321+
leg2_payment_lag_exchange=leg2_payment_lag_exchange,
127322
ex_div=ex_div,
128-
notional=notional,
323+
leg2_ex_div=leg2_ex_div,
324+
convention=convention,
325+
leg2_convention=leg2_convention,
326+
# settlement
129327
currency=currency,
328+
notional=notional,
329+
leg2_notional=leg2_notional,
130330
amortization=amortization,
131-
convention=convention,
331+
leg2_amortization=leg2_amortization,
332+
# rate
333+
fixed_rate=fixed_rate,
132334
leg2_float_spread=leg2_float_spread,
133335
leg2_spread_compound_method=leg2_spread_compound_method,
134336
leg2_rate_fixings=leg2_rate_fixings,
135337
leg2_fixing_method=leg2_fixing_method,
136338
leg2_method_param=leg2_method_param,
137-
leg2_effective=leg2_effective,
138-
leg2_termination=leg2_termination,
139-
leg2_frequency=leg2_frequency,
140-
leg2_stub=leg2_stub,
141-
leg2_front_stub=leg2_front_stub,
142-
leg2_back_stub=leg2_back_stub,
143-
leg2_roll=leg2_roll,
144-
leg2_eom=leg2_eom,
145-
leg2_modifier=leg2_modifier,
146-
leg2_calendar=leg2_calendar,
147-
leg2_payment_lag=leg2_payment_lag,
148-
leg2_payment_lag_exchange=leg2_payment_lag_exchange,
149-
leg2_ex_div=leg2_ex_div,
150-
leg2_notional=leg2_notional,
151-
leg2_amortization=leg2_amortization,
152-
leg2_convention=leg2_convention,
339+
# meta
153340
curves=self._parse_curves(curves),
154341
)
155342
instrument_args = dict( # these are hard coded arguments specific to this instrument
@@ -172,8 +359,8 @@ def __init__(
172359
meta_args=["curves"],
173360
)
174361

175-
self.leg1 = FixedLeg(**_convert_to_schedule_kwargs(self.kwargs.leg1, 1))
176-
self.leg2 = FloatLeg(**_convert_to_schedule_kwargs(self.kwargs.leg2, 1))
362+
self._leg1 = FixedLeg(**_convert_to_schedule_kwargs(self.kwargs.leg1, 1))
363+
self._leg2 = FloatLeg(**_convert_to_schedule_kwargs(self.kwargs.leg2, 1))
177364
self._legs = [self.leg1, self.leg2]
178365

179366
def rate(

python/rateslib/instruments/components/protocols/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from rateslib.instruments.components.protocols.npv import _WithNPV
1010
from rateslib.instruments.components.protocols.rate import _WithRate
1111
from rateslib.instruments.components.protocols.sensitivities import _WithSensitivities
12+
from rateslib.instruments.components.protocols.kwargs import _KWArgs
1213

1314
if TYPE_CHECKING:
1415
pass
@@ -28,6 +29,7 @@ class _BaseInstrument(
2829

2930

3031
__all__ = [
32+
"_KWArgs",
3133
"_WithNPV",
3234
"_WithRate",
3335
"_WithCashflows",

python/rateslib/instruments/components/protocols/analytic_delta.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,8 @@ class _WithAnalyticDelta(_WithPricingObjs, Protocol):
2929
Protocol to determine the *analytic rate delta* of a particular *Leg* of an *Instrument*.
3030
"""
3131

32-
_legs: list[_BaseLeg]
3332
_kwargs: _KWArgs
3433

35-
@property
36-
def legs(self) -> list[_BaseLeg]:
37-
return self._legs
38-
3934
@property
4035
def kwargs(self) -> _KWArgs:
4136
return self._kwargs
@@ -98,6 +93,8 @@ def analytic_delta(
9893
for this conversion although best practice does not recommend it due to possible
9994
settlement date conflicts.
10095
"""
96+
assert hasattr(self, "legs")
97+
10198
_curves: _Curves = self._parse_curves(curves)
10299
_curves_meta: _Curves = self.kwargs.meta["curves"]
103100

python/rateslib/instruments/components/protocols/npv.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class _WithNPV(_WithPricingObjs, Protocol):
3333

3434
@property
3535
def kwargs(self) -> _KWArgs:
36+
"""The :class:`~rateslib.instruments.components.protocols._KWArgs` container for
37+
the *Instrument*."""
3638
return self._kwargs
3739

3840
def __repr__(self) -> str:

0 commit comments

Comments
 (0)