diff --git a/financepy/products/rates/ibor_swap.py b/financepy/products/rates/ibor_swap.py
index 596d1978..efc770ba 100644
--- a/financepy/products/rates/ibor_swap.py
+++ b/financepy/products/rates/ibor_swap.py
@@ -392,6 +392,96 @@ def print_payments(self):
###########################################################################
+ def macaulay_duration(self, value_dt, discount_curve, swap_type, payment_periods: float):
+ """Calculation of the Macaulay Duration in an Interest Rate Swap
+ Based on Bond Math: The Theory Behind the Formulas, Second Edition by
+ Donald J. Smith
+ """
+ # Get coupon frequency
+ coupon_frequency = self.fixed_leg.freq_type.value
+
+ # Get swap rate
+ swap_rate_val = self.swap_rate(value_dt, discount_curve)
+
+ y = swap_rate_val / coupon_frequency
+ # payment_periods is the number of periods to maturity as of the beginning of the period;
+ # for instance, If the start date of the interest rate swap is 2024-01-01,
+ # the end date is 2025-12-31, the valuation date is 2024-03-31,
+ # and the frequency type is QUARTERLY,
+ # then the number of payment periods is 8; it is independent of the valuation date.
+ N = payment_periods
+ c = swap_rate_val / coupon_frequency
+ md1 = (1 + y) / y
+ md2 = 1 + y + (N * (c - y))
+ md3 = c * ((1 + y) ** N - 1) + y
+
+ """
+ The party who pays the fixed rate(ie,SwapTypes.PAY) is known as the payer
+ and the party who receives the fixed rate is known as the receiver.
+ The fixed‐rate payer and floating‐rate receiver,
+ sometimes is said to be the “buyer” of the swap, or is “long” the swap.
+ """
+ if swap_type == SwapTypes.PAY:
+ mac_duration = 1 - (md1 - md2 / md3)
+
+ elif swap_type == SwapTypes.RECEIVE:
+ mac_duration = (1 - (md1 - md2 / md3)) * (-1)
+
+ return mac_duration
+
+ ###########################################################################
+
+ def modified_duration(self, value_dt, discount_curve, swap_type, payment_periods: float):
+ """Computation of the Modified Duration for the Fixed-Rate
+ Payer's Perspective in Interest Rate Swap
+ """
+ # Get coupon frequency
+ coupon_frequency = self.fixed_leg.freq_type.value
+
+ # Get swap rate
+ swap_rate_val = self.swap_rate(value_dt, discount_curve)
+
+ modified_duration = (self.macaulay_duration(value_dt, discount_curve, swap_type, payment_periods) /
+ (1 + swap_rate_val / coupon_frequency))
+
+ return modified_duration
+
+ ###########################################################################
+
+ def change_in_market_value(self,
+ value_dt, discount_curve, swap_type, payment_periods: float,
+ swap_rate_changes: float):
+ """Computation of the Profits for the Fixed-Rate Payer's Perspective in Interest Rate Swap
+ """
+ # Get coupon frequency
+ coupon_frequency = self.fixed_leg.freq_type.value
+
+ annualized_modi_dur = self.modified_duration(value_dt, discount_curve, swap_type,
+ payment_periods) / coupon_frequency
+
+ delta_mv = (-1) * (annualized_modi_dur * self.fixed_leg.notional * swap_rate_changes)
+
+ return delta_mv
+
+ ###########################################################################
+
+ def basis_point_value(self, value_dt, discount_curve, swap_type, payment_periods: float):
+ """
+ calculate the basis‐point‐value (BPV) of the swap,
+ which is swap's modified duration times the notional principal,
+ times one basis point (0.0001)
+ """
+ bp = 0.0001
+ # Get coupon frequency
+ coupon_frequency = self.fixed_leg.freq_type.value
+ modi_dur = self.modified_duration(value_dt, discount_curve, swap_type, payment_periods)
+ annualized_modi_dur = modi_dur / coupon_frequency
+ BPV = annualized_modi_dur * self.fixed_leg.notional * bp
+
+ return BPV
+
+ ###########################################################################
+
def __repr__(self):
s = label_to_string("OBJECT TYPE", type(self).__name__)
diff --git a/notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample.ipynb b/notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample.ipynb
new file mode 100644
index 00000000..34c69cf8
--- /dev/null
+++ b/notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample.ipynb
@@ -0,0 +1,648 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "id": "initial_id",
+ "metadata": {
+ "collapsed": true,
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.795273Z",
+ "start_time": "2025-05-26T05:31:31.791904Z"
+ }
+ },
+ "source": [
+ "from financepy.utils import *\n",
+ "from financepy.products.rates import *\n",
+ "from financepy.market.curves import *\n",
+ "import datetime as dt\n",
+ "import numpy as np"
+ ],
+ "outputs": [],
+ "execution_count": 15
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.835720Z",
+ "start_time": "2025-05-26T05:31:31.831900Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "# Calculating the macaulay_duration, modified_duration, basis‐point‐value and change_in_value_of_IRS\n",
+ "# in an Interest Rate Swap\n",
+ "# Based on Bond Math: The Theory Behind the Formulas, Second Edition by Donald J. Smith\n"
+ ],
+ "id": "1771696c9beba73c",
+ "outputs": [],
+ "execution_count": 16
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "# 1.Interest rate swaps at the beginning",
+ "id": "c710af2d079e815d"
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "## Define the swap",
+ "id": "e606fc8bae71cc9e"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.847045Z",
+ "start_time": "2025-05-26T05:31:31.842610Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "swap_cal_type = CalendarTypes.TARGET\n",
+ "bd_type = BusDayAdjustTypes.FOLLOWING\n",
+ "dg_type = DateGenRuleTypes.BACKWARD\n",
+ "\n",
+ "fixed_cpn = 0.034\n",
+ "fixed_freq_type = FrequencyTypes.QUARTERLY\n",
+ "fixed_dc_type = DayCountTypes.THIRTY_360_BOND\n",
+ "\n",
+ "float_spread = 0.0\n",
+ "float_freq_type = FrequencyTypes.QUARTERLY\n",
+ "float_dc_type = DayCountTypes.THIRTY_360_BOND\n",
+ "\n",
+ "swap_type = SwapTypes.PAY\n",
+ "notional = 60000000\n",
+ "\n",
+ "start_dt = Date(1, 1, 2024)\n",
+ "maturity_dt = start_dt.add_tenor('2Y')\n",
+ "\n",
+ "swap = IborSwap(start_dt,\n",
+ " maturity_dt,\n",
+ " swap_type,\n",
+ " fixed_cpn,\n",
+ " fixed_freq_type,\n",
+ " fixed_dc_type,\n",
+ " notional,\n",
+ " float_spread,\n",
+ " float_freq_type,\n",
+ " float_dc_type,\n",
+ " swap_cal_type,\n",
+ " bd_type,\n",
+ " dg_type)\n"
+ ],
+ "id": "1ebf43316efee835",
+ "outputs": [],
+ "execution_count": 17
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.862908Z",
+ "start_time": "2025-05-26T05:31:31.858964Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "value_date = dt.datetime(2023, 12, 31)\n",
+ "value_dt = from_datetime(value_date)\n",
+ "settle_dt = value_dt.add_weekdays(0)\n"
+ ],
+ "id": "8e46f142f3cba5d7",
+ "outputs": [],
+ "execution_count": 18
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "## Define the yield curve",
+ "id": "9e298d9eeefb972a"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.880211Z",
+ "start_time": "2025-05-26T05:31:31.875398Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "yield_curve = [i / 100 for i in [0.5, 1.0407, 1.5829, 2.1271, 2.4506, 2.7756, 3.1025, 3.4316]]\n",
+ "zero_dts = value_dt.add_years([0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0])\n",
+ "\n",
+ "zero_curve = DiscountCurveZeros(value_dt=value_dt,\n",
+ " zero_dts=zero_dts,\n",
+ " zero_rates=yield_curve,\n",
+ " freq_type=FrequencyTypes.QUARTERLY,\n",
+ " dc_type=DayCountTypes.THIRTY_360_BOND,\n",
+ " interp_type=InterpTypes.FINCUBIC_ZERO_RATES\n",
+ " )"
+ ],
+ "id": "290b7a06932da41d",
+ "outputs": [],
+ "execution_count": 19
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "## Calculate the swap rate and sensitivity indicators",
+ "id": "de6b6c0c33f6f4a6"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.898089Z",
+ "start_time": "2025-05-26T05:31:31.892320Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "swap_rate = swap.swap_rate(value_dt, zero_curve)\n",
+ "swap_rate"
+ ],
+ "id": "7bb1613d5e865838",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.03404344249149676"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 20
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "",
+ "id": "6ead1b5ec3065f1e"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.945567Z",
+ "start_time": "2025-05-26T05:31:31.941273Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.value(settle_dt, zero_curve)",
+ "id": "e2fabe76f4bbdf2d",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "5070.7014320408925"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 21
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:31.990346Z",
+ "start_time": "2025-05-26T05:31:31.986969Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "payment_periods = 8\n",
+ "id": "3f988f26e6662203",
+ "outputs": [],
+ "execution_count": 22
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:32.021487Z",
+ "start_time": "2025-05-26T05:31:32.014011Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "index = ['swap_rate',\n",
+ " 'payer_macaulay_duration',\n",
+ " 'payer_modified_duration',\n",
+ " 'payer_BPV',\n",
+ " 'change_in_value_of_payer',\n",
+ " 'receiver_macaulay_duration',\n",
+ " 'receiver_modified_duration',\n",
+ " 'receiver_BPV',\n",
+ " 'change_in_value_of_receiver', ]\n",
+ "\n",
+ "data_financepy = [swap_rate,\n",
+ " np.nan, np.nan, np.nan, np.nan,\n",
+ " np.nan, np.nan, np.nan, np.nan]\n",
+ "\n",
+ "data_bondmath = [0.034,\n",
+ " np.nan, np.nan, np.nan, np.nan,\n",
+ " np.nan, np.nan, np.nan, np.nan, ]\n",
+ "data = {\n",
+ " 'financepy': data_financepy,\n",
+ " 'Bond Math by Donald J. Smith': data_bondmath\n",
+ "}\n",
+ "\n",
+ "df = pd.DataFrame(data, index=index)\n",
+ "df"
+ ],
+ "id": "952ec880bd1140f2",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " financepy Bond Math by Donald J. Smith\n",
+ "swap_rate 0.034043 0.034\n",
+ "payer_macaulay_duration NaN NaN\n",
+ "payer_modified_duration NaN NaN\n",
+ "payer_BPV NaN NaN\n",
+ "change_in_value_of_payer NaN NaN\n",
+ "receiver_macaulay_duration NaN NaN\n",
+ "receiver_modified_duration NaN NaN\n",
+ "receiver_BPV NaN NaN\n",
+ "change_in_value_of_receiver NaN NaN"
+ ],
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " financepy | \n",
+ " Bond Math by Donald J. Smith | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " swap_rate | \n",
+ " 0.034043 | \n",
+ " 0.034 | \n",
+ "
\n",
+ " \n",
+ " payer_macaulay_duration | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " payer_modified_duration | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " payer_BPV | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " change_in_value_of_payer | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " receiver_macaulay_duration | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " receiver_modified_duration | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " receiver_BPV | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " change_in_value_of_receiver | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 23
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "",
+ "id": "61aa4eb194b3d1d0"
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "# 2.Calculation of indicators after 3 months",
+ "id": "39513cfdc5d7ef1"
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "## update the swap",
+ "id": "91abc51ca7618b13"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:32.072889Z",
+ "start_time": "2025-05-26T05:31:32.068405Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "fixed_cpn_3m = 0.034\n",
+ "start_dt_3m = Date(1, 4, 2024)\n",
+ "maturity_dt_3m = start_dt_3m.add_years(1.75)\n",
+ "\n",
+ "swap_3m = IborSwap(start_dt_3m,\n",
+ " maturity_dt_3m,\n",
+ " swap_type,\n",
+ " fixed_cpn_3m,\n",
+ " fixed_freq_type,\n",
+ " fixed_dc_type,\n",
+ " notional,\n",
+ " float_spread,\n",
+ " float_freq_type,\n",
+ " float_dc_type,\n",
+ " swap_cal_type,\n",
+ " bd_type,\n",
+ " dg_type)\n",
+ "\n"
+ ],
+ "id": "5892081fb637c810",
+ "outputs": [],
+ "execution_count": 24
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:32.129906Z",
+ "start_time": "2025-05-26T05:31:32.125936Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "value_date_3m = dt.datetime(2024, 3, 31)\n",
+ "value_dt_3m = from_datetime(value_date_3m)\n",
+ "\n",
+ "settle_dt_3m = value_dt_3m.add_weekdays(0)\n",
+ "settle_dt_3m"
+ ],
+ "id": "9093bbf0197b619b",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "31-MAR-2024"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 25
+ },
+ {
+ "metadata": {},
+ "cell_type": "markdown",
+ "source": "## update the yield curve",
+ "id": "28ea6f9df37837d0"
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:32.243507Z",
+ "start_time": "2025-05-26T05:31:32.239142Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "yield_curve_3m = [i / 100 for i in [0.75, 1.1853, 1.6822, 2.1474, 2.4371, 2.7390, 3.0198]]\n",
+ "zero_dts_3m = value_dt_3m.add_years([0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75])\n",
+ "\n",
+ "zero_curve_3m = DiscountCurveZeros(value_dt_3m,\n",
+ " zero_dts=zero_dts_3m,\n",
+ " zero_rates=yield_curve_3m,\n",
+ " freq_type=FrequencyTypes.QUARTERLY,\n",
+ " dc_type=DayCountTypes.THIRTY_360_BOND,\n",
+ " interp_type=InterpTypes.FINCUBIC_ZERO_RATES\n",
+ " )\n",
+ "\n"
+ ],
+ "id": "8acc84107dae665e",
+ "outputs": [],
+ "execution_count": 26
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:32.335358Z",
+ "start_time": "2025-05-26T05:31:32.329091Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap_3m.value(value_dt_3m, zero_curve_3m)",
+ "id": "3aa3b8731a5cc344",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-404094.769553849"
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 27
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-26T05:31:32.392498Z",
+ "start_time": "2025-05-26T05:31:32.379861Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "# a -40 basis point change in the swap fi xed rate\n",
+ "swap_rate_changes = -0.004\n",
+ "\n",
+ "data_financepy_3m = [swap_3m.swap_rate(value_dt_3m, zero_curve_3m),\n",
+ " swap_3m.macaulay_duration(value_dt_3m, zero_curve_3m, swap_type, payment_periods),\n",
+ " swap_3m.modified_duration(value_dt_3m, zero_curve_3m, swap_type, payment_periods),\n",
+ " swap_3m.basis_point_value(value_dt_3m, zero_curve_3m, swap_type, payment_periods),\n",
+ " swap_3m.change_in_market_value(value_dt_3m, zero_curve_3m, swap_type, payment_periods,\n",
+ " swap_rate_changes),\n",
+ " swap_3m.macaulay_duration(value_dt_3m, zero_curve_3m, SwapTypes.RECEIVE, payment_periods),\n",
+ " swap_3m.modified_duration(value_dt_3m, zero_curve_3m, SwapTypes.RECEIVE, payment_periods),\n",
+ " swap_3m.basis_point_value(value_dt_3m, zero_curve_3m, SwapTypes.RECEIVE, payment_periods),\n",
+ " swap_3m.change_in_market_value(value_dt_3m, zero_curve_3m, SwapTypes.RECEIVE,\n",
+ " payment_periods, swap_rate_changes)\n",
+ " ]\n",
+ "\n",
+ "data_bondmath_3m = [0.030,\n",
+ " -6.769,\n",
+ " -6.7186,\n",
+ " -10077.9,\n",
+ " -403116,\n",
+ " 6.769,\n",
+ " 6.7186,\n",
+ " 10077.9,\n",
+ " 403116]\n",
+ "\n",
+ "data_3m = {\n",
+ " 'financepy': data_financepy_3m,\n",
+ " 'Bond Math by Donald J. Smith': data_bondmath_3m\n",
+ "}\n",
+ "\n",
+ "df3m = pd.DataFrame(data_3m, index=index)\n",
+ "df3m"
+ ],
+ "id": "9e64b678f01aa539",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " financepy Bond Math by Donald J. Smith\n",
+ "swap_rate 0.030066 0.0300\n",
+ "payer_macaulay_duration -6.794199 -6.7690\n",
+ "payer_modified_duration -6.743512 -6.7186\n",
+ "payer_BPV -10115.267497 -10077.9000\n",
+ "change_in_value_of_payer -404610.699889 -403116.0000\n",
+ "receiver_macaulay_duration 6.794199 6.7690\n",
+ "receiver_modified_duration 6.743512 6.7186\n",
+ "receiver_BPV 10115.267497 10077.9000\n",
+ "change_in_value_of_receiver 404610.699889 403116.0000"
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " financepy | \n",
+ " Bond Math by Donald J. Smith | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " swap_rate | \n",
+ " 0.030066 | \n",
+ " 0.0300 | \n",
+ "
\n",
+ " \n",
+ " payer_macaulay_duration | \n",
+ " -6.794199 | \n",
+ " -6.7690 | \n",
+ "
\n",
+ " \n",
+ " payer_modified_duration | \n",
+ " -6.743512 | \n",
+ " -6.7186 | \n",
+ "
\n",
+ " \n",
+ " payer_BPV | \n",
+ " -10115.267497 | \n",
+ " -10077.9000 | \n",
+ "
\n",
+ " \n",
+ " change_in_value_of_payer | \n",
+ " -404610.699889 | \n",
+ " -403116.0000 | \n",
+ "
\n",
+ " \n",
+ " receiver_macaulay_duration | \n",
+ " 6.794199 | \n",
+ " 6.7690 | \n",
+ "
\n",
+ " \n",
+ " receiver_modified_duration | \n",
+ " 6.743512 | \n",
+ " 6.7186 | \n",
+ "
\n",
+ " \n",
+ " receiver_BPV | \n",
+ " 10115.267497 | \n",
+ " 10077.9000 | \n",
+ "
\n",
+ " \n",
+ " change_in_value_of_receiver | \n",
+ " 404610.699889 | \n",
+ " 403116.0000 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ]
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 28
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 2
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython2",
+ "version": "2.7.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample3M.ipynb b/notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample3M.ipynb
new file mode 100644
index 00000000..5c6d719b
--- /dev/null
+++ b/notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample3M.ipynb
@@ -0,0 +1,403 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "id": "initial_id",
+ "metadata": {
+ "collapsed": true,
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.198988Z",
+ "start_time": "2025-05-23T03:11:30.509140Z"
+ }
+ },
+ "source": [
+ "from financepy.utils import *\n",
+ "from financepy.products.rates import *\n",
+ "from financepy.market.curves import *\n",
+ "import datetime as dt\n"
+ ],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "####################################################################\n",
+ "# FINANCEPY BETA Version 0.370 - This build: 28 Oct 2024 at 20:29 #\n",
+ "# This software is distributed FREE AND WITHOUT ANY WARRANTY #\n",
+ "# Report bugs as issues at https://github.com/domokane/FinancePy #\n",
+ "####################################################################\n",
+ "\n"
+ ]
+ }
+ ],
+ "execution_count": 1
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.234873Z",
+ "start_time": "2025-05-23T03:11:32.208415Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "swap_cal_type = CalendarTypes.TARGET\n",
+ "bd_type = BusDayAdjustTypes.FOLLOWING\n",
+ "dg_type = DateGenRuleTypes.BACKWARD\n",
+ "\n",
+ "\n",
+ "fixed_cpn = 0.034\n",
+ "fixed_freq_type = FrequencyTypes.QUARTERLY\n",
+ "fixed_dc_type = DayCountTypes.THIRTY_360_BOND\n",
+ "\n",
+ "float_spread = 0.0\n",
+ "float_freq_type = FrequencyTypes.QUARTERLY\n",
+ "float_dc_type = DayCountTypes.THIRTY_360_BOND\n",
+ "\n",
+ "swap_type = SwapTypes.PAY\n",
+ "notional = 60000000\n",
+ "\n",
+ "start_dt = Date(1, 4, 2024)\n",
+ "maturity_dt = start_dt.add_years(1.75)\n",
+ "\n",
+ "swap = IborSwap(start_dt,\n",
+ " maturity_dt,\n",
+ " swap_type,\n",
+ " fixed_cpn,\n",
+ " fixed_freq_type,\n",
+ " fixed_dc_type,\n",
+ " notional,\n",
+ " float_spread,\n",
+ " float_freq_type,\n",
+ " float_dc_type,\n",
+ " swap_cal_type,\n",
+ " bd_type,\n",
+ " dg_type)\n"
+ ],
+ "id": "1ebf43316efee835",
+ "outputs": [],
+ "execution_count": 2
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.413949Z",
+ "start_time": "2025-05-23T03:11:32.408884Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "value_date= dt.datetime(2024,3,31)\n",
+ "value_dt = from_datetime(value_date)\n",
+ "\n",
+ "settle_dt = value_dt.add_weekdays(0)\n",
+ "# settle_dt=value_dt\n",
+ "settle_dt"
+ ],
+ "id": "8e46f142f3cba5d7",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "31-MAR-2024"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 3
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.447267Z",
+ "start_time": "2025-05-23T03:11:32.442210Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "\n",
+ "yield_curve=[i/100 for i in [0.75,1.1853,1.6822,2.1474,2.4371,2.7390,3.0198]]\n",
+ "zero_dts=value_dt.add_years([0.25,0.5,0.75,1.0,1.25,1.5,1.75])\n",
+ "\n",
+ "zero_curve = DiscountCurveZeros(value_dt=value_dt,\n",
+ " zero_dts=zero_dts,\n",
+ " zero_rates=yield_curve,\n",
+ " freq_type=FrequencyTypes.QUARTERLY,\n",
+ " dc_type=DayCountTypes.THIRTY_360_BOND,\n",
+ " interp_type=InterpTypes.FINCUBIC_ZERO_RATES\n",
+ " )"
+ ],
+ "id": "290b7a06932da41d",
+ "outputs": [],
+ "execution_count": 4
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.461542Z",
+ "start_time": "2025-05-23T03:11:32.456727Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.swap_rate(value_dt, zero_curve)",
+ "id": "7bb1613d5e865838",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.030065619962567392"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 5
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.501044Z",
+ "start_time": "2025-05-23T03:11:32.497430Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.value(settle_dt, zero_curve)",
+ "id": "e2fabe76f4bbdf2d",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-404094.769553849"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 6
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.548673Z",
+ "start_time": "2025-05-23T03:11:32.543824Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.payer_side_macaulay_duration(value_dt,zero_curve,8)",
+ "id": "3f988f26e6662203",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-6.794198629548404"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 7
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.591829Z",
+ "start_time": "2025-05-23T03:11:32.587918Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.receiver_side_macaulay_duration(value_dt, zero_curve,8)",
+ "id": "96d568f7a71861fe",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "6.794198629548404"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 8
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.651777Z",
+ "start_time": "2025-05-23T03:11:32.646875Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.payer_side_modified_duration(value_dt, zero_curve,8)",
+ "id": "ec2187c7336c1bc3",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-6.743511664816526"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 9
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.715295Z",
+ "start_time": "2025-05-23T03:11:32.711182Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.receiver_side_modified_duration(value_dt, zero_curve,8)",
+ "id": "2c1b845afaf5e18f",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "6.743511664816526"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 10
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.914101Z",
+ "start_time": "2025-05-23T03:11:32.909828Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "payment_periods=8\n",
+ "swap_rate_changes=-0.004\n",
+ "swap.payer_side_profits(value_dt, zero_curve,payment_periods,swap_rate_changes)"
+ ],
+ "id": "5ef5f29ad5dfad00",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-404610.6998889916"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 14
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:32.963176Z",
+ "start_time": "2025-05-23T03:11:32.958757Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.receiver_side_profits(value_dt, zero_curve,payment_periods,swap_rate_changes)",
+ "id": "11109a6f2da7b7dc",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "404610.6998889916"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 15
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:33.018125Z",
+ "start_time": "2025-05-23T03:11:33.013277Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.payer_side_BPV(value_dt, zero_curve,payment_periods)",
+ "id": "a4c532a9a90b445c",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-10115.26749722479"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 16
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-05-23T03:11:33.062580Z",
+ "start_time": "2025-05-23T03:11:33.058102Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "swap.receiver_side_BPV(value_dt, zero_curve,payment_periods)",
+ "id": "8f8630e90883e3b5",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10115.26749722479"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 17
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 2
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython2",
+ "version": "2.7.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}