jrvarma / bond_pricing

Bond pricing using YTM or zero curve. Also basic NPV/IRR functions
GNU General Public License v3.0
31 stars 8 forks source link

Clarification on Annuity Functions #6

Closed abdullahau closed 1 month ago

abdullahau commented 1 month ago

Hey Prof.,

Could you please help me understand how I can think about the cash flow frequency and compounding frequency inputs in relation to the per period discount rate in your annuity functions?

I notice that the annuity functions in present_value.py do not adjust the instalment or the n_periods based on the cash flow frequencies. The cf_freq and comp_freq are only used to convert the per period rate's periodicity using the equiv_rate function.

Typically, online calculators tend to require inputs in annual terms and convert annual rates, annual instalments, and years to maturity by the payment interval. For example, consider a bond with the following features: nominal annual market rate = 7%, years to maturity = 12, annual coupon = 30, face value = 100, payment interval = semiannual. On Excel, I would compute the present value using the following input: rate = 3.5%, period = 24, coupon = 15, face value = 100, giving me a present value of $284.67.

The annuity_pv function returns the same result with the adjusted inputs but only when the cf_freq is left to the default 1 per period, or when the per period rate is left to the annual rate of 7%, cf_freq & comp_freq is set to 2, while rest of the inputs are adjusted by their payment interval. (i.e. both the calculations return the same value: annuity_pv(rate=0.07, n_periods=24, instalment=15, terminal_payment=100, cf_freq=2, comp_freq=2 and annuity_pv(rate=0.035, n_periods=24, instalment=15, terminal_payment=100, cf_freq=1, comp_freq=1)

I just wanted to understand the rational behind why only the interest rate is adjusted by cash flow frequency and not the other related inputs.

jrvarma commented 1 month ago

My design of this function was influenced by my frustration with Excel's PV function. In the real world, interest rates are always stated as annual rates, but if I want to use PV to calculate the present value of a car loan with 48 monthly payments of 100 each with an interest rate of 10% per annum, Excel suggests that I divide 10% by 12 and give that as an interest rate: PV(10%/12,48,100)=-3942.82. My annuity_pv allows this as well annuity_pv(rate=10e-2/12, n_periods=48, instalment=100)=3942.816. But it also allows me to let the computer figure this out for me: annuity_pv(rate=10e-2, n_periods=48, instalment=100, cf_freq=12, comp_freq=12)=3942.816.

More importantly, when an interest rate is quoted as 10%, it is usually either 10% compounded annually or 10% compounded semi-annually, and in this case, Excel's suggestion of using 10%/12=0.008333% is wrong. Under annual compounding, we have to find the equivalent monthly rate as 1.1^(1/12)-1=0.007974%. So I have to write =PV(1.1^(1/12)-1,48,100,)=-3975.18. With the annuity_pv function, I can write this as annuity_pv(rate=10e-2, n_periods=48, instalment=100, cf_freq=12, comp_freq=1)=3975.181.

What I wanted was the ability to simply read the terms of a loan and enter the data into the function in a natural way. "Monthly payment of 100" becomes instalment=100, cf_freq=12,, "for 48 months" becomes n_periods=48, "interest rate of 10% annually compounded" becomes rate=10e-2, comp_freq=1. The software does all the conversion instead of asking the human to do the conversion.

I do not change the instalment because a loan agreement would rarely say 1200 per annum payable in equal monthly instalments. It would usually say 100 per month. For number of periods, it would usually say 48 months though it might sometimes say 4 years.