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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
financepyBond Math by Donald J. Smith
swap_rate0.0340430.034
payer_macaulay_durationNaNNaN
payer_modified_durationNaNNaN
payer_BPVNaNNaN
change_in_value_of_payerNaNNaN
receiver_macaulay_durationNaNNaN
receiver_modified_durationNaNNaN
receiver_BPVNaNNaN
change_in_value_of_receiverNaNNaN
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
financepyBond Math by Donald J. Smith
swap_rate0.0300660.0300
payer_macaulay_duration-6.794199-6.7690
payer_modified_duration-6.743512-6.7186
payer_BPV-10115.267497-10077.9000
change_in_value_of_payer-404610.699889-403116.0000
receiver_macaulay_duration6.7941996.7690
receiver_modified_duration6.7435126.7186
receiver_BPV10115.26749710077.9000
change_in_value_of_receiver404610.699889403116.0000
\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 +}