Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems accurately plotting curves with long tenors #246

Open
henrikparssinen opened this issue Jul 1, 2024 · 1 comment
Open

Problems accurately plotting curves with long tenors #246

henrikparssinen opened this issue Jul 1, 2024 · 1 comment
Labels
curves documentation Improvements or additions to documentation enhancement New feature or request

Comments

@henrikparssinen
Copy link

Hey,

I'm trying to recreate the SOFR curve from swaps, and after roughly getting the discount factors right, it seems like the curve fails to plot longer tenors.
The data I have from Bloomberg is below:

px_last term security_typ issue_dt maturity DF
USOSFR1Z BGN Curncy 5.3256 1W SWAP 2024-07-03 2024-07-10 0.998966
USOSFR2Z BGN Curncy 5.3286 2W SWAP 2024-07-03 2024-07-17 0.997932
USOSFR3Z BGN Curncy 5.3315 3W SWAP 2024-07-03 2024-07-24 0.996900
USOSFRA BGN Curncy 5.3346 1M SWAP 2024-07-03 2024-08-05 0.995134
USOSFRB BGN Curncy 5.3352 2M SWAP 2024-07-03 2024-09-03 0.990895
USOSFRC BGN Curncy 5.3221 3M SWAP 2024-07-03 2024-10-03 0.986582
USOSFRD BGN Curncy 5.3017 4M SWAP 2024-07-03 2024-11-04 0.982066
USOSFRE BGN Curncy 5.281 5M SWAP 2024-07-03 2024-12-03 0.978048
USOSFRF BGN Curncy 5.2537 6M SWAP 2024-07-03 2025-01-03 0.973850
USOSFRG BGN Curncy 5.2215 7M SWAP 2024-07-03 2025-02-03 0.969759
USOSFRH BGN Curncy 5.187 8M SWAP 2024-07-03 2025-03-03 0.966172
USOSFRI BGN Curncy 5.1508 9M SWAP 2024-07-03 2025-04-03 0.962276
USOSFRJ BGN Curncy 5.1123 10M SWAP 2024-07-03 2025-05-05 0.958355
USOSFRK BGN Curncy 5.0765 11M SWAP 2024-07-03 2025-06-03 0.954891
USOSFR1 BGN Curncy 5.0408 1Y SWAP 2024-07-03 2025-07-03 0.951377
USOSFR1F BGN Curncy 4.7629 18M SWAP 2024-07-03 2026-01-05 0.931077
USOSFR2 BGN Curncy 4.5898 2Y SWAP 2024-07-03 2026-07-06 0.912894
USOSFR3 BGN Curncy 4.3325 3Y SWAP 2024-07-03 2027-07-06 0.879158
USOSFR4 BGN Curncy 4.1827 4Y SWAP 2024-07-03 2028-07-03 0.847588
USOSFR5 BGN Curncy 4.0946 5Y SWAP 2024-07-03 2029-07-03 0.816886
USOSFR6 BGN Curncy 4.0448 6Y SWAP 2024-07-03 2030-07-03 0.786845
USOSFR7 BGN Curncy 4.0146 7Y SWAP 2024-07-03 2031-07-03 0.757600
USOSFR8 BGN Curncy 3.9953 8Y SWAP 2024-07-03 2032-07-06 0.728914
USOSFR9 BGN Curncy 3.9847 9Y SWAP 2024-07-03 2033-07-05 0.701375
USOSFR10 BGN Curncy 3.9795 10Y SWAP 2024-07-03 2034-07-03 0.674692
USOSFR12 BGN Curncy 3.9802 12Y SWAP 2024-07-03 2036-07-03 0.623241
USOSFR15 BGN Curncy 3.9852 15Y SWAP 2024-07-03 2039-07-05 0.552861
USOSFR20 BGN Curncy 3.9536 20Y SWAP 2024-07-03 2044-07-05 0.457430
USOSFR25 BGN Curncy 3.8634 25Y SWAP 2024-07-03 2049-07-06 0.388550
USOSFR30 BGN Curncy 3.768 30Y SWAP 2024-07-03 2054-07-06 0.335664
USOSFR40 BGN Curncy 3.554 40Y SWAP 2024-07-03 2064-07-03 0.267253
USOSFR50 BGN Curncy 3.3385 50Y SWAP 2024-07-03 2074-07-03 0.228792>

image

timestamps = data[data['maturity'] >= start_date + pd.DateOffset(months = 6)]['maturity'].tolist()

new_timestamps = [timestamps[0]] * 4 + timestamps[1:-1] + [timestamps[-1]] * 4
            
curve = rl.Curve(
    id="my_curve",
    convention= 'Act360',
    interpolation= 'log_linear',
    calendar = 'nyc',
    **t,
    nodes={
        **{data['issue_dt'].iloc[0]: 1.0},  # <- this is today's DF,
        **{_: 1.0 for _ in 
           data['maturity']
          },
    }
)

args = dict(spec='sofr', curves=curve)
solver = rl.Solver(
    curves=[curve],
    instruments = [rl.IRS(termination=maturity, effective=effective_date, **args) for maturity, effective_date in zip(data["maturity"], data["issue_dt"])],
    s=data["px_last"],
    id="rates"
)
data["DF"] = [float(curve[_]) for _ in data["maturity"]]

The 1-year curve looks to be on par with Bloomberg:
image
image

However, when the tenor is 25 years, it fails by quite a bit:
image
image

@attack68
Copy link
Owner

attack68 commented Jul 3, 2024

A Curve object does not know the conventions of a swap. It does not plot a swap rate. It plots a curve rate. Normally this is used for tenors such as 1d, 1m, 3m, 6m, 12m. Tenors longer than 12m will are expressed as single period simple rates.

Your 5y discount factor is 0.816521. The first point on a plot for a 5Y rate would be calculated with:
(1.0 / 0.816521 -1) * (1 / 5.0) * 100 = 4.494%

Which is the ration of two discount factors at start and end scaled by a day count fraction between the dates.

To return a different calculation, e,g.

  • a continuously compounded zero rate
  • a swap rate type calculation
  • an internal rate of return with some frequency of compounding like a yield-to-maturity

would all require a definition and a different type of calculation.

These additional calculations are all currently not defined, nor developed.

@attack68 attack68 added documentation Improvements or additions to documentation enhancement New feature or request curves labels Jul 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
curves documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants