Skip to content

Commit bbf5e8d

Browse files
committed
Use swap.Type to determine which indicators to output.
1 parent 07c7560 commit bbf5e8d

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

financepy/products/rates/ibor_swap.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,44 @@ def payer_side_macaulay_duration(self, value_dt, discount_curve, payment_periods
417417
mac_duration = 1 - (md1 - md2 / md3)
418418
return mac_duration
419419

420+
421+
def macaulay_duration(self, value_dt, discount_curve, swap_type, payment_periods: float):
422+
"""Calculation of the Payer's Macaulay Duration in an Interest Rate Swap
423+
Based on Bond Math: The Theory Behind the Formulas, Second Edition by
424+
Donald J. Smith
425+
"""
426+
# Get coupon frequency
427+
coupon_frequency = self.fixed_leg.freq_type.value
428+
429+
# Get swap rate
430+
swap_rate_val = self.swap_rate(value_dt,discount_curve)
431+
432+
y = swap_rate_val / coupon_frequency
433+
# payment_periods is the number of periods to maturity as of the beginning of the period;
434+
# for instance, If the start date of the interest rate swap is 2024-01-01,
435+
# the end date is 2025-12-31, the valuation date is 2024-03-31,
436+
# and the frequency type is QUARTERLY,
437+
# then the number of payment periods is 8; it is independent of the valuation date.
438+
N = payment_periods
439+
c = swap_rate_val / coupon_frequency
440+
md1 = (1 + y) / y
441+
md2 = 1 + y + (N * (c - y))
442+
md3 = c * ((1 + y) ** N - 1) + y
443+
444+
"""
445+
The party who pays the fixed rate(ie,SwapTypes.PAY) is known as the payer
446+
and the party who receives the fixed rate is known as the receiver.
447+
The fixed‐rate payer and floating‐rate receiver,
448+
sometimes is said to be the “buyer” of the swap, or is “long” the swap.
449+
"""
450+
if swap_type == SwapTypes.PAY:
451+
mac_duration = 1 - (md1 - md2 / md3)
452+
453+
elif swap_type == SwapTypes.RECEIVE:
454+
mac_duration = (1 - (md1 - md2 / md3))*(-1)
455+
456+
return mac_duration
457+
420458
###########################################################################
421459

422460
def receiver_side_macaulay_duration(self, value_dt, discount_curve,payment_periods: float):
@@ -440,6 +478,27 @@ def payer_side_modified_duration(self, value_dt, discount_curve,payment_periods:
440478

441479
return self.payer_side_macaulay_duration(value_dt, discount_curve,payment_periods)/(1+swap_rate_val/coupon_frequency)
442480

481+
def modified_duration(self, value_dt, discount_curve, swap_type, payment_periods: float):
482+
"""Computation of the Modified Duration for the Fixed-Rate
483+
Payer's Perspective in Interest Rate Swap
484+
"""
485+
# Get coupon frequency
486+
coupon_frequency = self.fixed_leg.freq_type.value
487+
488+
# Get swap rate
489+
swap_rate_val = self.swap_rate(value_dt, discount_curve)
490+
491+
if swap_type == SwapTypes.PAY:
492+
modified_duration = (self.macaulay_duration(value_dt, discount_curve, swap_type, payment_periods) /
493+
(1 + swap_rate_val / coupon_frequency))
494+
495+
elif swap_type == SwapTypes.RECEIVE:
496+
modified_duration = (self.macaulay_duration(value_dt, discount_curve, swap_type, payment_periods) /
497+
(1 + swap_rate_val / coupon_frequency))
498+
499+
return modified_duration
500+
501+
443502
###########################################################################
444503

445504
def receiver_side_modified_duration(self, value_dt, discount_curve,payment_periods: float):
@@ -472,6 +531,25 @@ def receiver_side_profits(self,
472531
"""
473532
return self.payer_side_profits(value_dt, discount_curve,payment_periods,swap_rate_changes)*(-1)
474533

534+
535+
def change_in_market_value(self,
536+
value_dt, discount_curve, swap_type, payment_periods: float,
537+
swap_rate_changes: float):
538+
"""Computation of the Profits for the Fixed-Rate Payer's Perspective in Interest Rate Swap
539+
"""
540+
# Get coupon frequency
541+
coupon_frequency = self.fixed_leg.freq_type.value
542+
543+
annualized_modi_dur = self.modified_duration(value_dt, discount_curve,swap_type,payment_periods)/coupon_frequency
544+
545+
if swap_type == SwapTypes.PAY:
546+
delta_mv=(-1)*(annualized_modi_dur*self.fixed_leg.notional*swap_rate_changes)
547+
548+
elif swap_type == SwapTypes.RECEIVE:
549+
delta_mv=(annualized_modi_dur*self.fixed_leg.notional*swap_rate_changes)
550+
551+
return delta_mv
552+
475553
###########################################################################
476554

477555
def payer_side_BPV(self, value_dt, discount_curve,payment_periods: float,):
@@ -499,6 +577,27 @@ def receiver_side_BPV(self, value_dt, discount_curve,payment_periods: float,):
499577

500578
###########################################################################
501579

580+
def basis_point_value (self,value_dt, discount_curve,swap_type, payment_periods: float):
581+
"""
582+
calculate the basis‐point‐value (BPV) for the payer_side of the swap,
583+
which is swap's modified duration times the notional principal,
584+
times one basis point (0.0001)
585+
"""
586+
bp=0.0001
587+
# Get coupon frequency
588+
coupon_frequency = self.fixed_leg.freq_type.value
589+
modi_dur = self.modified_duration(value_dt, discount_curve, swap_type, payment_periods)
590+
annualized_modi_dur= modi_dur/coupon_frequency
591+
592+
if swap_type == SwapTypes.PAY:
593+
BPV=annualized_modi_dur*self.fixed_leg.notional*bp
594+
595+
elif swap_type == SwapTypes.RECEIVE:
596+
BPV=annualized_modi_dur*self.fixed_leg.notional*bp*(-1)
597+
598+
return BPV
599+
600+
502601
def __repr__(self):
503602

504603
s = label_to_string("OBJECT TYPE", type(self).__name__)

0 commit comments

Comments
 (0)