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

FloatRateNote is failing to calculate cashflows #149

Open
lcohan opened this issue Apr 23, 2024 · 8 comments
Open

FloatRateNote is failing to calculate cashflows #149

lcohan opened this issue Apr 23, 2024 · 8 comments
Labels

Comments

@lcohan
Copy link

lcohan commented Apr 23, 2024

Hi! I've been trying to follow the example in the FloatingRateNote Guide, but there seems to be a bug in the definition of the fixing

I have not been able to calculate a working cashflow trying many combinations of the parameters

image

@lcohan lcohan changed the title FloatRateNote is failing to calculate FloatRateNote is failing to calculate cashflows Apr 23, 2024
@lcohan
Copy link
Author

lcohan commented Apr 24, 2024

cc @attack68

@attack68
Copy link
Owner

Hi the example in the user guide can probably be improved, actually. The specific example you seem to have taken was designed to show the calculation of accrued when some fixings in a period are provided and some are not.

E.g.

from pandas import Series, date_range
fixings = Series(2.0, index=date_range(dt(1999, 12, 1), dt(2000, 6, 2)))

frn = FloatRateNote(
    effective=dt(1998, 12, 7),
    termination=dt(2015, 12, 7),
    frequency="S",
    currency="gbp",
    convention="Act365F",
    ex_div=3,
    fixings=fixings,
    fixing_method="rfr_observation_shift",
    method_param=5,
)
frn.accrued(dt(2000, 6, 4))
# 0.9911540636168727

If you try to calculate cashflows without a curve to forecast NPVs it will display the structure of the bond and display the values it can but it cant forecast floating rates and DF, and NPVs...

Screenshot 2024-04-24 at 07 21 18

If instead you build a Curve which extends to the end of the bond and starts where the fixings have ended and try to get cashflows:

curve = Curve(
    {dt(2000, 6, 3): 1.0,
     dt(2020, 6, 3): 0.5,},
    calendar=NoInput(0),
    convention="act365f",
)
frn.cashflows(curve)
# ValueError: RFRs could not be calculated, have you missed providing `fixings` 
# or does the `Curve` begin after the start of a `FloatPeriod` includingthe `method_param` adjustment?

This error is not the clearest but essentially what it is indicating is that rateslib is trying to calculate the rate for the periods before the fixings start, i.e. between Dec 1998 and Dec 1999, using a Curve that begins in Jun 2000.
The solution is to provide all the fixing data for all of those prior Periods:

fixings = Series(2.0, index=date_range(dt(1997, 12, 1), dt(2000, 6, 2)))
frn = FloatRateNote(
    effective=dt(1998, 12, 7),
    termination=dt(2015, 12, 7),
    frequency="S",
    currency="gbp",
    convention="Act365F",
    ex_div=3,
    fixings=fixings,
    fixing_method="rfr_observation_shift",
    method_param=5,
)
frn.cashflows(curve)

Screenshot 2024-04-24 at 07 33 20

@lcohan
Copy link
Author

lcohan commented Apr 24, 2024 via email

@attack68
Copy link
Owner

If you provide all the fixings for all the periods. It should work. Provide a reproducible example otherwise it is impossible to bug fix.

@attack68
Copy link
Owner

The discounting Curve is used as reference for discounting cashflows to the present day. The immediate date is measured as the first node on the curve. This displays all cashflows and values them at zero becuase they are historical relative to the Curve.

frn = FloatRateNote(
    effective=dt(2000, 12, 7),
    termination=dt(2002, 12, 7),
    frequency="S",
    currency="gbp",
    convention="Act365F",
    ex_div=3,
    fixings=[2.5, 3.5, 4.5, 6.5],
    fixing_method="ibor",
    method_param=5,
)
curve = Curve({dt(2022, 1, 1): 1.0})
frn.cashflows(curve)

image

@lcohan
Copy link
Author

lcohan commented Apr 24, 2024

just to give you an example

In the code above, if you expand fixings to 2020 you would have the full range covered, and no need for a curve

fixings = Series(2.0, index=date_range(dt(1997, 12, 1), dt(2020, 6, 2)))

but I am still getting Nones

image

@attack68
Copy link
Owner

This is ultimately due to the evaluation of cashflows of a single FloatPeriod. The code contains:

        if curve is not NoInput.blank:
            cashflow = float(self.cashflow(curve))
            rate = float(100 * cashflow / (-self.notional * self.dcf))
            npv = float(self.npv(curve, disc_curve_))
            npv_fx = npv * float(fx)
        else:
            cashflow, rate, npv, npv_fx = None, None, None, None

Even if the rate can be known if there are enough fixings, it is still not generated. Maybe a design flaw - maybe not. In any case, if you want to trigger the evaluation of the rates and their display use a Curve with a reference date.

fixings = Series(2.0, index=date_range(dt(1997, 12, 1), dt(2020, 6, 2)))

frn = FloatRateNote(
    effective=dt(1998, 12, 7),
    termination=dt(2015, 12, 7),
    frequency="S",
    currency="gbp",
    convention="Act365F",
    ex_div=3,
    fixings=fixings,
    fixing_method="rfr_observation_shift",
    method_param=5,
)
frn.cashflows(Curve({dt(2020, 6, 3): 1.0}))

@attack68 attack68 closed this as not planned Won't fix, can't repro, duplicate, stale May 19, 2024
@attack68
Copy link
Owner

attack68 commented Aug 8, 2024

Maybe an idea to add a psuedo curve to generate results..

@attack68 attack68 reopened this Aug 8, 2024
@attack68 attack68 added enhancement New feature or request derivatives curves labels Aug 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants