Skip to content

Commit 9275b93

Browse files
committed
add BPV for payer and receiver
1 parent b6dd01e commit 9275b93

File tree

2 files changed

+90
-108
lines changed

2 files changed

+90
-108
lines changed

financepy/products/rates/ibor_swap.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,42 @@ def payer_side_profits(self,
458458
"""
459459
# Get coupon frequency
460460
coupon_frequency = self.fixed_leg.freq_type.value
461+
461462
annualized_modi_dur = self.payer_side_modified_duration(value_dt, discount_curve,payment_periods)/coupon_frequency
462463
return (-1)*(annualized_modi_dur*self.fixed_leg.notional*swap_rate_changes)
463464

465+
###########################################################################
466+
467+
def receiver_side_profits(self,
468+
value_dt,
469+
discount_curve,payment_periods: float,
470+
swap_rate_changes: float):
471+
"""Computation of the Profits for the Fixed-Rate Receiver's Perspective in Interest Rate Swap
472+
"""
473+
return self.payer_side_profits(value_dt, discount_curve,payment_periods,swap_rate_changes)*(-1)
474+
475+
###########################################################################
476+
477+
def payer_side_BPV(self, value_dt, discount_curve,payment_periods: float,):
478+
"""
479+
calculate the basis‐point‐value (BPV) for the payer_side of the swap,
480+
which is swap's modified duration times the notional principal,
481+
times one basis point (0.0001)
482+
"""
483+
bp=0.0001
484+
return self.payer_side_modified_duration(value_dt, discount_curve,payment_periods)*self.fixed_leg.notional*bp
485+
486+
###########################################################################
487+
488+
def receiver_side_BPV(self, value_dt, discount_curve,payment_periods: float,):
489+
"""
490+
calculate the basis‐point‐value (BPV) for receiver_side of the swap,
491+
which is swap's modified duration times the notional principal,
492+
times one basis point (0.0001)
493+
"""
494+
return self.payer_side_BPV(value_dt, discount_curve,payment_periods)*(-1)
495+
496+
###########################################################################
464497

465498
def __repr__(self):
466499

notebooks/products/rates/FINIBORSWAP_ReplicationgBONDMATHDurationExample3M.ipynb

Lines changed: 57 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"metadata": {
77
"collapsed": true,
88
"ExecuteTime": {
9-
"end_time": "2025-05-23T02:25:34.603675Z",
10-
"start_time": "2025-05-23T02:25:34.599467Z"
9+
"end_time": "2025-05-23T02:31:22.631355Z",
10+
"start_time": "2025-05-23T02:31:22.625849Z"
1111
}
1212
},
1313
"source": [
@@ -17,13 +17,13 @@
1717
"import datetime as dt"
1818
],
1919
"outputs": [],
20-
"execution_count": 16
20+
"execution_count": 2
2121
},
2222
{
2323
"metadata": {
2424
"ExecuteTime": {
25-
"end_time": "2025-05-23T02:25:34.630084Z",
26-
"start_time": "2025-05-23T02:25:34.621619Z"
25+
"end_time": "2025-05-23T02:31:22.679560Z",
26+
"start_time": "2025-05-23T02:31:22.657680Z"
2727
}
2828
},
2929
"cell_type": "code",
@@ -63,13 +63,13 @@
6363
],
6464
"id": "1ebf43316efee835",
6565
"outputs": [],
66-
"execution_count": 17
66+
"execution_count": 3
6767
},
6868
{
6969
"metadata": {
7070
"ExecuteTime": {
71-
"end_time": "2025-05-23T02:25:34.640874Z",
72-
"start_time": "2025-05-23T02:25:34.636086Z"
71+
"end_time": "2025-05-23T02:31:22.694667Z",
72+
"start_time": "2025-05-23T02:31:22.687165Z"
7373
}
7474
},
7575
"cell_type": "code",
@@ -89,18 +89,18 @@
8989
"31-MAR-2024"
9090
]
9191
},
92-
"execution_count": 18,
92+
"execution_count": 4,
9393
"metadata": {},
9494
"output_type": "execute_result"
9595
}
9696
],
97-
"execution_count": 18
97+
"execution_count": 4
9898
},
9999
{
100100
"metadata": {
101101
"ExecuteTime": {
102-
"end_time": "2025-05-23T02:25:34.675868Z",
103-
"start_time": "2025-05-23T02:25:34.663679Z"
102+
"end_time": "2025-05-23T02:31:22.727011Z",
103+
"start_time": "2025-05-23T02:31:22.719602Z"
104104
}
105105
},
106106
"cell_type": "code",
@@ -123,13 +123,13 @@
123123
],
124124
"id": "290b7a06932da41d",
125125
"outputs": [],
126-
"execution_count": 19
126+
"execution_count": 5
127127
},
128128
{
129129
"metadata": {
130130
"ExecuteTime": {
131-
"end_time": "2025-05-23T02:25:34.693421Z",
132-
"start_time": "2025-05-23T02:25:34.686347Z"
131+
"end_time": "2025-05-23T02:31:22.746919Z",
132+
"start_time": "2025-05-23T02:31:22.739589Z"
133133
}
134134
},
135135
"cell_type": "code",
@@ -142,68 +142,18 @@
142142
"0.030065619962567392"
143143
]
144144
},
145-
"execution_count": 20,
145+
"execution_count": 6,
146146
"metadata": {},
147147
"output_type": "execute_result"
148148
}
149149
],
150-
"execution_count": 20
150+
"execution_count": 6
151151
},
152152
{
153153
"metadata": {
154154
"ExecuteTime": {
155-
"end_time": "2025-05-23T02:25:34.722494Z",
156-
"start_time": "2025-05-23T02:25:34.715862Z"
157-
}
158-
},
159-
"cell_type": "code",
160-
"source": [
161-
"# def payer_side_macaulay_duration(value_dt, discount_curve):\n",
162-
"# \"\"\"Calculation of the Payer's Macaulay Duration in an Interest Rate Swap\n",
163-
"# Based on Bond Math: The Theory Behind the Formulas, Second Edition by\n",
164-
"# Donald J. Smith\n",
165-
"# \"\"\"\n",
166-
"# # Number of fixed leg payments\n",
167-
"# payment_period = len(swap.fixed_leg.payments)\n",
168-
"#\n",
169-
"# # Get coupon frequency\n",
170-
"# coupon_frequency = self.fixed_leg.freq_type.value\n",
171-
"#\n",
172-
"# # Get swap rate\n",
173-
"# swap_rate_val = self.swap_rate(value_dt, discount_curve)\n",
174-
"#\n",
175-
"# y = swap_rate_val / coupon_frequency\n",
176-
"# N = payment_period\n",
177-
"# c = swap_rate_val / coupon_frequency\n",
178-
"# md1 = (1 + y) / y\n",
179-
"# md2 = 1 + y + (N * (c - y))\n",
180-
"# md3 = c * ((1 + y) ** N - 1) + y\n",
181-
"# mac_duration = 1 - (md1 - md2 / md3)\n",
182-
"# return mac_duration\n",
183-
"\n",
184-
"\n",
185-
"payment_period = len(swap.fixed_leg.payments) + 1\n",
186-
"coupon_frequency = swap.fixed_leg.freq_type.value\n",
187-
"swap_rate_val = swap.swap_rate(value_dt, zero_curve)\n",
188-
"y = swap_rate_val / coupon_frequency\n",
189-
"N = payment_period\n",
190-
"c = swap_rate_val / coupon_frequency\n",
191-
"md1 = (1 + y) / y\n",
192-
"md2 = 1 + y + (N * (c - y))\n",
193-
"md3 = c * ((1 + y) ** N - 1) + y\n",
194-
"mac_duration = 1 - (md1 - md2 / md3)\n",
195-
"\n",
196-
"delta_mv=-(-mac_duration/4*notional*(-0.004))"
197-
],
198-
"id": "65a401442f9bf084",
199-
"outputs": [],
200-
"execution_count": 21
201-
},
202-
{
203-
"metadata": {
204-
"ExecuteTime": {
205-
"end_time": "2025-05-23T02:25:34.740382Z",
206-
"start_time": "2025-05-23T02:25:34.734050Z"
155+
"end_time": "2025-05-23T02:31:22.765913Z",
156+
"start_time": "2025-05-23T02:31:22.759349Z"
207157
}
208158
},
209159
"cell_type": "code",
@@ -216,18 +166,18 @@
216166
"-404094.769553849"
217167
]
218168
},
219-
"execution_count": 22,
169+
"execution_count": 7,
220170
"metadata": {},
221171
"output_type": "execute_result"
222172
}
223173
],
224-
"execution_count": 22
174+
"execution_count": 7
225175
},
226176
{
227177
"metadata": {
228178
"ExecuteTime": {
229-
"end_time": "2025-05-23T02:25:34.769581Z",
230-
"start_time": "2025-05-23T02:25:34.763504Z"
179+
"end_time": "2025-05-23T02:31:22.784960Z",
180+
"start_time": "2025-05-23T02:31:22.779808Z"
231181
}
232182
},
233183
"cell_type": "code",
@@ -240,18 +190,18 @@
240190
"-6.794198629548404"
241191
]
242192
},
243-
"execution_count": 23,
193+
"execution_count": 8,
244194
"metadata": {},
245195
"output_type": "execute_result"
246196
}
247197
],
248-
"execution_count": 23
198+
"execution_count": 8
249199
},
250200
{
251201
"metadata": {
252202
"ExecuteTime": {
253-
"end_time": "2025-05-23T02:25:34.803424Z",
254-
"start_time": "2025-05-23T02:25:34.798626Z"
203+
"end_time": "2025-05-23T02:31:22.817161Z",
204+
"start_time": "2025-05-23T02:31:22.812093Z"
255205
}
256206
},
257207
"cell_type": "code",
@@ -264,18 +214,18 @@
264214
"6.794198629548404"
265215
]
266216
},
267-
"execution_count": 24,
217+
"execution_count": 9,
268218
"metadata": {},
269219
"output_type": "execute_result"
270220
}
271221
],
272-
"execution_count": 24
222+
"execution_count": 9
273223
},
274224
{
275225
"metadata": {
276226
"ExecuteTime": {
277-
"end_time": "2025-05-23T02:25:34.836332Z",
278-
"start_time": "2025-05-23T02:25:34.831799Z"
227+
"end_time": "2025-05-23T02:31:22.858301Z",
228+
"start_time": "2025-05-23T02:31:22.853154Z"
279229
}
280230
},
281231
"cell_type": "code",
@@ -288,18 +238,18 @@
288238
"-6.743511664816526"
289239
]
290240
},
291-
"execution_count": 25,
241+
"execution_count": 10,
292242
"metadata": {},
293243
"output_type": "execute_result"
294244
}
295245
],
296-
"execution_count": 25
246+
"execution_count": 10
297247
},
298248
{
299249
"metadata": {
300250
"ExecuteTime": {
301-
"end_time": "2025-05-23T02:25:34.864470Z",
302-
"start_time": "2025-05-23T02:25:34.860289Z"
251+
"end_time": "2025-05-23T02:31:22.894478Z",
252+
"start_time": "2025-05-23T02:31:22.889858Z"
303253
}
304254
},
305255
"cell_type": "code",
@@ -312,18 +262,18 @@
312262
"6.743511664816526"
313263
]
314264
},
315-
"execution_count": 26,
265+
"execution_count": 11,
316266
"metadata": {},
317267
"output_type": "execute_result"
318268
}
319269
],
320-
"execution_count": 26
270+
"execution_count": 11
321271
},
322272
{
323273
"metadata": {
324274
"ExecuteTime": {
325-
"end_time": "2025-05-23T02:25:34.895364Z",
326-
"start_time": "2025-05-23T02:25:34.888381Z"
275+
"end_time": "2025-05-23T02:31:22.942622Z",
276+
"start_time": "2025-05-23T02:31:22.937046Z"
327277
}
328278
},
329279
"cell_type": "code",
@@ -373,13 +323,13 @@
373323
]
374324
}
375325
],
376-
"execution_count": 27
326+
"execution_count": 12
377327
},
378328
{
379329
"metadata": {
380330
"ExecuteTime": {
381-
"end_time": "2025-05-23T02:25:34.923991Z",
382-
"start_time": "2025-05-23T02:25:34.918594Z"
331+
"end_time": "2025-05-23T02:31:22.977499Z",
332+
"start_time": "2025-05-23T02:31:22.971711Z"
383333
}
384334
},
385335
"cell_type": "code",
@@ -411,13 +361,13 @@
411361
]
412362
}
413363
],
414-
"execution_count": 28
364+
"execution_count": 13
415365
},
416366
{
417367
"metadata": {
418368
"ExecuteTime": {
419-
"end_time": "2025-05-23T02:25:35.017712Z",
420-
"start_time": "2025-05-23T02:25:35.013394Z"
369+
"end_time": "2025-05-23T02:31:23.015658Z",
370+
"start_time": "2025-05-23T02:31:23.010172Z"
421371
}
422372
},
423373
"cell_type": "code",
@@ -449,32 +399,31 @@
449399
]
450400
}
451401
],
452-
"execution_count": 29
402+
"execution_count": 14
453403
},
454404
{
455405
"metadata": {
456406
"ExecuteTime": {
457-
"end_time": "2025-05-23T02:25:35.127867Z",
458-
"start_time": "2025-05-23T02:25:35.115423Z"
407+
"end_time": "2025-05-23T02:31:23.043840Z",
408+
"start_time": "2025-05-23T02:31:23.039172Z"
459409
}
460410
},
461411
"cell_type": "code",
462412
"source": "swap.payer_side_profits(value_dt, zero_curve,8,-0.004)",
463413
"id": "5ef5f29ad5dfad00",
464414
"outputs": [
465415
{
466-
"ename": "AttributeError",
467-
"evalue": "'IborSwap' object has no attribute 'payer_side_profits'",
468-
"output_type": "error",
469-
"traceback": [
470-
"\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
471-
"\u001B[1;31mAttributeError\u001B[0m Traceback (most recent call last)",
472-
"Cell \u001B[1;32mIn[30], line 1\u001B[0m\n\u001B[1;32m----> 1\u001B[0m \u001B[43mswap\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mpayer_side_profits\u001B[49m(value_dt, zero_curve,\u001B[38;5;241m8\u001B[39m,\u001B[38;5;241m-\u001B[39m\u001B[38;5;241m0.004\u001B[39m)\n",
473-
"\u001B[1;31mAttributeError\u001B[0m: 'IborSwap' object has no attribute 'payer_side_profits'"
474-
]
416+
"data": {
417+
"text/plain": [
418+
"-404610.6998889916"
419+
]
420+
},
421+
"execution_count": 15,
422+
"metadata": {},
423+
"output_type": "execute_result"
475424
}
476425
],
477-
"execution_count": 30
426+
"execution_count": 15
478427
}
479428
],
480429
"metadata": {

0 commit comments

Comments
 (0)