|
From: David D. <nh...@gm...> - 2021-04-05 09:41:22
|
The curve you are building takes continuous rates as inputs and uses linear
interpolation of zero yields for non node points.
You could alternatively specify annually compounded rates as inputs.
In any case, you can inspect the cashflow details with
ql.as_floating_coupon.
Here is an example:
bond = FloatingRateBond(0, 100, bond_schedule , myindex, Actual360())
interest_cashflows = [*map(as_floating_rate_coupon, bond.cashflows())][:-1]
rate = interest_cashflows[1].rate()
accrualDays = interest_cashflows[1].accrualDays()
print("Floating rate:", rate)
print("Cashflow", 100 * rate * accrualDays/360)
# Floating rate: 0.050644366225002097
# Cashflow 2.588489829277885
On Mon, 5 Apr 2021 at 07:02, Brian Smith <bri...@gm...> wrote:
> Thanks again.
>
> Below is my modified code with 0 replaced by a dummy 0.05. But still I
> see 0 for first coupon payment.
>
> from QuantLib import *
>
> mydate = Date(31, 1, 2018)
>
> Settings.instance().evaluationDate = mydate
>
> spots = [mydate, mydate + Period("6m"), mydate + Period("1y"), mydate
> + Period("2y"), mydate + Period("3y")]
> spotsdate = [0.05, 0.05, 0.05, 0.05, 0.05]
>
> curveHandle = YieldTermStructureHandle(ZeroCurve(spots, spotsdate,
> Actual360(), Canada(), Linear(), Continuous))
>
> myindex = Euribor6M(curveHandle)
> myindex.addFixing(Date(29, 1, 2018), 0.00)
>
> bond_schedule = Schedule(mydate, mydate + Period("1y"), Period(6,
> Months), Canada(), Unadjusted, Unadjusted, DateGeneration.Forward,
> False)
>
> [c.amount() for c in FloatingRateBond(0, 100, bond_schedule , myindex,
> Actual360()).cashflows()]
> [c.date() for c in FloatingRateBond(0, 100, bond_schedule , myindex,
> Actual360()).cashflows()]
>
> ### [0.0, 2.5884898292778846, 100.0]
> ### [Date(31,7,2018), Date(31,1,2019), Date(31,1,2019)]
>
> To match the second coupon payment, I used below manual formula to
> convert continuous compounding to semi-annual :
>
> (math.sqrt(math.exp(0.05)) - 1)*2 * Actual360().yearFraction(spots[1],
> spots[2]) * 100
> ### 2.5877678758305054
>
> With this, I got a better match, but still not exact. Should I make
> any other adjustment?
>
> Appreciate your pointer.
>
> Thanks and regards,
>
> On Mon, 5 Apr 2021 at 04:08, Arkadiy Naumov <ark...@gm...>
> wrote:
> >
> > As far as the first zero - that's your extra fixing contributing. Either
> set it to 0.05 or create a custom index that does not have 2-days
> settlement, so you don't even have to worry about it.
> > For the interest being slightly off - 0.05 is continuously compounded
> (you set your zero curve this way), but the bond resets to "simple" rate
> (which is higher, so the numbers make sense at least directionally)
> >
> > On Sun, Apr 4, 2021 at 4:09 AM Brian Smith <bri...@gm...>
> wrote:
> >>
> >> Thanks for your comments.
> >>
> >> But I still failed to understand the coupon payments at various coupon
> >> dates. Below is my full example -
> >>
> >> from QuantLib import *
> >>
> >> mydate = Date(31, 1, 2018)
> >>
> >> Settings.instance().evaluationDate = mydate
> >>
> >> spots = [mydate, mydate + Period("6m"), mydate + Period("1y"), mydate
> >> + Period("2y"), mydate + Period("3y")]
> >> spotsdate = [0, 0.05, 0.05, 0.05, 0.05]
> >>
> >> curveHandle = YieldTermStructureHandle(ZeroCurve(spots, spotsdate,
> >> Actual360(), Canada(), Linear(), Continuous))
> >>
> >> myindex = Euribor6M(curveHandle)
> >> myindex.addFixing(Date(29, 1, 2018), 0.00)
> >>
> >> bond_schedule = Schedule(mydate, mydate + Period("1y"), Period(6,
> >> Months), Canada(), Unadjusted, Unadjusted, DateGeneration.Forward,
> >> False)
> >>
> >> [c.amount() for c in FloatingRateBond(0, 100, bond_schedule , myindex,
> >> Actual360()).cashflows()]
> >> [c.date() for c in FloatingRateBond(0, 100, bond_schedule , myindex,
> >> Actual360()).cashflows()]
> >>
> >> ### [0.0, 2.5884898292778846, 100.0]
> >> ### [Date(31,7,2018), Date(31,1,2019), Date(31,1,2019)]
> >>
> >> So I see on the 1st coupon date, QL is showing coupon payment as 0. Why?
> >> And, on the last coupon date, coupon payment is 2.5884898292778846.
> >> How this number is calculated? If I manually calculate this, I get
> >> just a close match -
> >>
> >> 5 * Actual360().yearFraction(spots[1], spots[2])
> >>
> >> ### 2.5555555555555554
> >>
> >> Am I missing something?
> >>
> >> On Sun, 4 Apr 2021 at 03:27, Arkadiy Naumov <ark...@gm...>
> wrote:
> >> >
> >> > And as to the zeros - I may be wrong, but try explicitly setting the
> evaluationDate to whatever date you want to be your spot.
> >> >
> >> > On Sat, Apr 3, 2021 at 5:50 PM Arkadiy Naumov <
> ark...@gm...> wrote:
> >> >>
> >> >> Hi Brian,
> >> >>
> >> >> Without running your code - the reason Jan29th comes into play is
> because Euribor6M has a two days settlement built in:
> https://github.com/lballabio/QuantLib/blob/master/ql/indexes/ibor/eurlibor.cpp#L63
> >> >>
> >> >>
> >> >> On Sat, Apr 3, 2021 at 10:22 AM Brian Smith <
> bri...@gm...> wrote:
> >> >>>
> >> >>> Hi,
> >> >>>
> >> >>> I found out that I have to add a dummy quote to get this work. So I
> added -
> >> >>>
> >> >>> myindex = Euribor6M(curveHandle)
> >> >>> myindex.addFixing(Date(27, 7, 2018), 0.00)
> >> >>>
> >> >>> bond_schedule = Schedule(mydate,
> >> >>> mydate + Period("1y"), Period(6, Months), Canada(), Unadjusted,
> >> >>> Unadjusted, DateGeneration.Forward, False)
> >> >>>
> >> >>> [c.amount() for c in FloatingRateBond(0, 10000, bond_schedule ,
> >> >>> myindex, Actual360()).cashflows()]
> >> >>> [c.date() for c in FloatingRateBond(0, 10000, bond_schedule ,
> myindex,
> >> >>> Actual360()).cashflows()]
> >> >>>
> >> >>> However with this, I am getting strange result as all the coupon
> >> >>> payments are coming as zero.
> >> >>>
> >> >>> Can you please help me to understand what went wrong in my code?
> >> >>>
> >> >>>
> >> >>> On Sat, 3 Apr 2021 at 14:39, Brian Smith <
> bri...@gm...> wrote:
> >> >>> >
> >> >>> > Hi,
> >> >>> >
> >> >>> > I want to extract all the cash flow amounts from a bond as
> defined below -
> >> >>> >
> >> >>> > from QuantLib import *
> >> >>> >
> >> >>> > mydate = Date(31, 1, 2018)
> >> >>> >
> >> >>> > spots = [mydate, mydate + Period("6m"), mydate + Period("1y"),
> mydate
> >> >>> > + Period("2y"), mydate + Period("3y")]
> >> >>> > spotsdate = [0, 0.25, 0.45, 0.65, 0.85]
> >> >>> >
> >> >>> > curveHandle = YieldTermStructureHandle(ZeroCurve(spots, spotsdate,
> >> >>> > Actual360(), Canada(), Linear(), Continuous))
> >> >>> >
> >> >>> > [c.amount() for c in FloatingRateBond(0, 10000, Schedule(mydate,
> >> >>> > mydate + Period("1y"), Period(6, Months), Canada(), Unadjusted,
> >> >>> > Unadjusted, DateGeneration.Forward, False) ,
> Euribor6M(curveHandle),
> >> >>> > Actual360()).cashflows()]
> >> >>> >
> >> >>> > However above code failed to achieve any result, but giving out
> below error -
> >> >>> >
> >> >>> > Traceback (most recent call last):File "<stdin>", line 1, in
> >> >>> > <module>File "<stdin>", line 1, in <listcomp>File
> >> >>> > "/usr/local/lib/python3.9/site-packages/QuantLib/QuantLib.py",
> line
> >> >>> > 9967, in amountreturn _QuantLib.CashFlow_amount(self)RuntimeError:
> >> >>> > Missing Euribor6M Actual/360 fixing for January 29th, 2018
> >> >>> >
> >> >>> > I wonder where the date January 29th, 2018 comes from and how to
> resolve this?
> >> >>> >
> >> >>> > Any pointer will be highly appreciated.
> >> >>> >
> >> >>> > Thanks for your time.
> >> >>>
> >> >>>
> >> >>> _______________________________________________
> >> >>> QuantLib-users mailing list
> >> >>> Qua...@li...
> >> >>> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>
>
> _______________________________________________
> QuantLib-users mailing list
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>
|