|
From: Stats S. <sta...@gm...> - 2025-07-30 11:23:07
|
Thanks, Luigi. Will do.
On Fri, Jul 25, 2025 at 7:04 PM Luigi Ballabio <lui...@gm...>
wrote:
> Hi—it turns out that the rates coming out of the spreaded curve are not as
> expected. If you calculate the original rates from the curve and then add
> the spread, as you did in your sample code, you get
>
> >>> zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded,
> ql.Monthly ).rate() for ii,l in enumerate(leg) ]
> >>> print([r + zspread for r in zero_rates])
> [0.054693695527939915, 0.05243448138456887]
>
> while if you extract the same rates from the spreaded curve you get
>
> >>> print([ zspreaded_handle.zeroRate( l.date(), daycount, ql.Compounded,
> ql.Monthly ).rate() for ii,l in enumerate(leg) ])
> [0.05502806821107864, 0.05226732979489501]
>
> The problem seems to be that the curve and the added spread have two
> different day counters (act/360 for the curve and 30/360 for the spread)
> and somehow ZeroSpreadedTermStructure fails to account for that. If the
> two day counters are the same (either both 30/360 or both act/360) the
> problem disappears, which is probably why nobody noticed until now.
>
> May you open an issue on GitHub so someone can pick it up and analyse it
> further? Thanks!
>
> Luigi
>
>
>
> On Tue, Jun 10, 2025 at 6:17 AM Stats Student <sta...@gm...>
> wrote:
>
>> Hi - I have been trying to use the spread from ql.CashFlows.zSpread to
>> discount cash flows. I am able to use it in ZeroSpreadedTermStructure and
>> get the right numbers.
>> But I would like to understand how to replicate the same output by hand.
>> The NPV I get is very close, but there is still a small difference which I
>> suspect will likely get bigger over longer periods.
>>
>> Does anyone know what is causing this discrepancy? Thanks in advance.
>>
>>
>>
>> zspread: 0.009989751634951987 ( from ql.CashFlows.zSpread )
>>
>>
>> zSpread / ZeroSpreadedTermStructure npv: 198.6780*623718125 (CORRECT)*
>>
>>
>> zSpread manual npv: 198.6780*7379166345*
>>
>>
>>
>> ###########################################
>>
>>
>> import QuantLib as ql
>>
>> daycount = ql.Thirty360(ql.Thirty360.USA)
>>
>> start = ql.Date(1, 1, 2025)
>>
>> ql.Settings.instance().evaluationDate = start
>>
>> rates = ( ['SOFR1D', 4.3564348072], ['SOFR1W', 4.3493027605], ['SOFR1M',
>> 4.3238954677], ['SOFR3M', 4.3084328938], ['SOFR6M', 4.2045895664] )
>>
>> sofr_index = ql.Sofr()
>>
>> ois_helpers = []
>>
>> for period, rate in rates:
>> tenor = period.replace('SOFR','')
>> ois_helpers.append( ql.OISRateHelper(0,
>> ql.Period ( tenor ),
>>
>> ql.QuoteHandle(ql.SimpleQuote(rate/100)),
>> sofr_index) )
>>
>> curve = ql.PiecewiseLogCubicDiscount( start, ois_helpers, ql.Actual360() )
>>
>> handle = ql.YieldTermStructureHandle( curve )
>>
>> leg = ql.Leg( [ ql.SimpleCashFlow( 100, ql.Date(1,2,2025) ),
>> ql.SimpleCashFlow( 100, ql.Date(1,3,2025) ) ] )
>>
>> spreaded_npv = 198.6780623718125
>>
>> zspread = ql.CashFlows.zSpread(leg, spreaded_npv, curve, daycount,
>> ql.Compounded, ql.Monthly, True)
>>
>> print(f"zspread: {zspread}") # zspread: 0.009989751634951987
>>
>> zspread_quote = ql.SimpleQuote( zspread )
>>
>> zspreaded_curve = ql.ZeroSpreadedTermStructure( handle,
>> ql.QuoteHandle(zspread_quote), ql.Compounded, ql.Monthly, daycount )
>>
>> zspreaded_handle = ql.YieldTermStructureHandle( zspreaded_curve )
>>
>> zspreaded_npv = ql.CashFlows.npv(leg, zspreaded_handle, True)
>>
>> print(f"zSpread ZeroSpreadedTermStructure npv: {zspreaded_npv}") # zSpread
>> npv: 198.6780623718125 (MATCH)
>>
>> zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded,
>> ql.Monthly ).rate() for ii,l in enumerate(leg) ]
>>
>> # zero_rates = [ handle.zeroRate( (ii+1)/12, ql.Compounded, ql.Monthly
>> ).rate() for ii,l in enumerate(leg) ] # 198.67814955576728 (BIGGER
>> DELTA)
>>
>> zpread_manual_npv = 100 / (1 + (zero_rates[0] + zspread) / 12) + 100 / (
>> 1 + (zero_rates[1] + zspread) / 12 ) ** 2
>>
>> print(f"zSpread manual npv: {zpread_manual_npv}\n") # manual zSpread
>> npv: 198.67807379166345 (*NO MATCH*)
>>
>>
>>
>> _______________________________________________
>> QuantLib-users mailing list
>> Qua...@li...
>> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>>
>
|