How to use financial functions. A comparison between SAS and Python. | by Valentin Nordstroem | Towards Data Science

Note from Towards Data Science’s editors: While we allow independent authors to publish articles in accordance with our rules and guidelines, we do not endorse each author’s contribution. You should not rely on an author’s works without seeking professional advice. See our Reader Terms for details.
Most people use Excel to make financial calculations. But both SAS and Python are very capable of helping in finance too. One of the benefits in using SAS and Python is the structured automation.
In this article, I will show you some of the most common formulas used in finance:
pmt, Calculating the monthly payment of an loan
fv, Computes the future value of an investment
pv, Computes the present value of an investment
nper, Computes the number of periodic payments
rate, Computes the interest rate per period of an annuity
ppmt, Computes the payment on the principal for an investment for a specified period
effect, Computes the effective annual interest rate
irr, Computes the internal rate of return for a series of cash flows
npv, Computes the net present value
Btw. There is a big error in SAS and Excel regarding the description on how to calculate net present values. I will show you the correct way to do it.
You can find financial functions in Python Numpy Library until version 1.17
import numpy as npimport pandas as pd
Check your Numpy version
print(np.__version__)1.15.3
If installed NumPy version is > 1.17, the financial function is moved from NumPy to NumPy Financial. So, you need to import the financial functions as npf instead of np in your Python program.
Import as follow:
import numpy_financial as npf
In this example, we want to calculate how much you have to pay monthly to pay back a loan of 10.000 in 5 years. The yearly interest rate is 6%, and is calculated monthly.
You can use a function called finance(). Its is a replica of the functionalities in Excel.
DATA pmt;  rate = 0.06/12;  nper = 5*12;  pv = 10000;  fv = 0;  pmt = FINANCE('pmt', rate, nper, pv, fv);RUN;PROC PRINT;RUN;Using SAS Config named: defaultSAS Connection established. Subprocess id is 4412
You use the np.pmt() function to compute the monthly payment. I first create a data frame with a dictionary approach with only one record. I call it Obs and give it a value of 1. I need to create a non empty data frame, so I can assign scalars values to it.
df = pd.DataFrame({'Obs':[1]})df['rate'] = 0.06/12df['nper'] = 60df['pv'] = 10000df['fv'] = 0df['pmt'] = np.pmt(df.rate, df.nper, df.pv, df.fv)df
In this example, I refer to the columns, using dot notation instead of hard brackets. As I have mentioned before, you should be careful when using this notation, since it is the same way you refer to an attribute. Therefore, I mostly use this notatin when I use a column inside a function. I still use the df['var'] when I create the variable.
You have to pay 193.33 per month to pay back a loan of 10.000 over five years.
The next example is to find out what is left of the loan of 10.000 if you pay 200 per month over the next 60 month.
The yearly interest rate is 6% per year, and is calculated monthly.
We use the same finance function, FINANCE() as before, buut this time the missing argument is fv.
DATA fv;  rate = (0.06/12);  nper = 60;  pmt = -200;  pv = 10000;  fv = FINANCE('fv', rate, nper, pmt, pv);RUN;PROC PRINT;RUN;
The result is that you have paid 465.51 more than you should.
You use the function np.fv(rate, nper, pmt, pv). Same syntax as before.
df = pd.DataFrame({'Obs':[1]})df['rate'] = 0.06/12df['nper'] = 60df['pmt'] = -200df['pv'] = 10000df['fv'] = np.fv(df.rate, df.nper, df.pmt, df.pv)df
Alternative ways in Python
I want to show you a way to do the same calculation without using a DataFrame. You can do this directly in Python. You assign the values to variables and use the variables as argument in the np.fv() function.
rate = 0.06/12nper = 60pmt= -200pv = 10000fv = np.fv(rate,nper,pmt,pv)fv465.50457647922485
Or you just type the values as an argument directly in the NumPy function.
np.fv(0.06/12,60,-200,10000)465.50457647922485
If you just have to make one calculation, that is for just one observation, the last two examples are sufficient.
In this example, we still look the loan, but this time we want to know how much we can borrow if we repay the loan with 200 per month for the next five years. The annual interest rate is 6% and is charged monthly.
We use PV to tell the finance function that we are looking for the present value.
DATA pv;   rate=0.06/12;   nper=12 * 5;   pmt=-200;   fv=0;   pv=FINANCE('pv', rate, nper, pmt, fv);RUN;PROC PRINT;RUN;
The result of the calculation is that we can borrow 10.345,11.
You use the present value function np.pv() from NumPy:
df = pd.DataFrame({'Obs':[1]})df['rate'] = 0.06/12df['nper'] = 12*5df['pmt'] = -200df['fv'] = 0df['pv'] = np.pv(df.rate, df.nper, df.pmt, df.fv)df
What about the number of payments you need to make to pay back 10.000 with 200 per month?
We use the same setup as before, but this time we set the FINANCE() function to calculate nper.
DATA nper;   rate=0.06/12;   pmt=-200;   pv=10000;   fv=0;   nper=FINANCE('nper', rate, pmt, pv, fv);RUN;PROC PRINT;RUN;
Again, the syntax is the same. This time we use the function np.fv():
df = pd.DataFrame({'Obs':[1]})df['rate'] = 0.06/12df['pmt'] = -200df['pv'] = 10000df['fv'] = 0df['nper'] = np.nper(df.rate, df.pmt, df.pv, df.fv)df
So we have to make 58 payments to pay back 10.000 over 5 years.
Now we want to look at the yearly interest rate when you pay back a loan of 10,000 with 60 monthly payments of 200.
The result from the FINANCE() function is the monthly interest. Therefore, you have to multiply the result with 12 to get the annual interest rate.
DATA rate;   nper=60;   payment=-200;   pv=10000;   fv=0;   rate=FINANCE('rate', nper, payment, pv, fv) * 12;RUN;PROC PRINT;RUN;
So to pay back a loan of 10.000 with 200 per month, the anual interest would be 7.42%
We use the np.rate() function. But, we still need to multiply it with 12 to get the yearly result.
df = pd.DataFrame({'Obs':[1]})df['nper'] = 60df['pmt'] = -200df['pv'] = 10000df['fv'] = 0df['rate'] = np.rate(df.nper, df.pmt, df.pv, df.fv) * 12df
If you want to know how much principal you would pay each month, you can use the ppmt method.
You calculate ppmt for each period using the FINANCE() function in a do loop to get the 60 principal payments.
DATA ppmt;    DO period = 1 TO 60;       rate=0.06/12;       nper=60;       pv=10000;       fv=0;       ppmt=FINANCE('ppmt', rate, period, nper, pv, fv);       output;    end;run;proc print;run;
To create one records for the 60 months, we use range(1,61) to make a list of 60 values from 1 to 60 as the period column. For each period the np.ppmt() function is then used to calculates the principal payment.
df = pd.DataFrame()df['period'] = range(1, 61)df['rate'] = 0.06/12df['nper'] = 60df['pv'] = 10000df['fv'] = 0df['ppmt'] = np.ppmt(df.rate, df.period, df.nper, df.pv, df.fv)df
Remember that SAS count the possition of the records starting with the first record having the number 1. In Python the number of the first record is 0.
For SAS users, think about it as your age, when you were born. In you first year you were zero years old.
There are other financial calculations we can do.
The first is how to calculate the effective interest rate if you are charged monthly interest.
In SAS, the finance function can do the calculation for us.
In Python, you have to calculate it yourself and that is very simple.
I’ll show you how to use the FINANCE() function and how you can calculate it yourself.
DATA effective;   rate=0.06;   nper=12;   effect_fin = FINANCE('effect', rate, nper);   effect = (1 + rate/nper)**nper - 1;RUN;PROC PRINT;RUN;
You have to calculate the effective interest rate ourselves. I will show you how to do this in Python and in a DataFrame.
rate = 0.06nper = 12effect = (1 + rate/nper)**nper - 1print('The effective interest rate is: ', effect)The effective interest rate is:  0.06167781186449828
Notice how you can add a text in your print output!
df = pd.DataFrame({'Obs':[1]})df['rate'] = ratedf['nper'] = nperdf['effect'] = (1 + df.rate/df.nper)**df.nper - 1df
So the effective interest rate is 6.16%
There are other useful calculations you can use in finance. Internal rate of return is one of them.
You can still use the FINANCE() function. But this time the arguments are different as they are the cash flow for the investment.
In this example, you invest 40.000 and receive four payment in return. The function returns the IRR of this investment.
%%SASDATA irr;   v1=-40000;   v2=5000;   v3=8000;   v4=12000;   v5=30000;   r=FINANCE('irr', v1, v2, v3, v4, v5);RUN;PROC PRINT;RUN;
The internal rate of return is 10.58%
We also have a np.irr() function and the syntax is very similar to SAS. Only that you don't need to have the cash flow in separate variables.
df = pd.DataFrame()df['cashflow'] = [-40000, 5000, 8000, 12000, 30000]df['irr'] = np.irr(df['cashflow'])df
You can also do the calculation outside the DataFrame with Series as an input or directly with the cash flow numbers as input.
irr = np.irr(df['cashflow'])irr0.10582259840890207np.irr([-40000,5000,8000,12000,30000])0.10582259840890207
This is a very interesting formula. For many years the explanations of how to use this formula have been wrong in both SAS and Excel.
When you calculate a net, you have to deduct something. But that is not explained in the documentations of SAS and Microsoft. So the function is not calculating npv.
You have to add a deduction to get the right result. In Python, every thing is calculated correctly from the beginning.
You can use the FINANCE() function in calculating the Net Present Value. You use the cash flow and interest rate as input and then deduct the investment from the output.
I will also show you the formulas for calculating npv without a function.
DATA npv;   rate=0.08;   investment=-40000;   cf1=5000;   cf2=8000;   cf3=12000;   cf4=30000;   npv = FINANCE('npv', rate, cf1, cf2, cf3, cf4) + investment;   npv_formula = cf1/(1+rate)**1 + cf2/(1+rate)**2 + cf3/(1+rate)**3 + cf4/(1+rate)**4 + investment;RUN;PROC PRINT;RUN;
On the other hand, the np.npv() function takes the full list of values, both the investment and the cashflow as arguments.
df = pd.DataFrame()df['values'] = [-40000, 5000, 8000, 12000, 30000]df['rate'] = 0.08df['npv'] = np.npv(df['rate'],df['values'])df
You can also use your own formula for calculating NPV.
5000/(1+0.08)**1 + 8000/(1+0.08)**2 + 12000/(1+0.08)**3 + 30000/(1+0.08)**4 - 400003065.222668179529
This last example shows how to separate the two values, investment and cashflow. If you have the values in each list, you can add the two list's in the function as investment+cashflow
rate = 0.08investment = [-40000]cashflow = [5000, 8000, 12000, 30000]np.npv(rate,investment+cashflow)3065.2226681795255
That all I had about financial functions. In SAS you can use FINANCE() for all the calculations. In Python you use separate functions, but with very similar syntax.
I hope you are aware of the challenge in calculating net present values in SAS and Excel and that you are not including the invesment in you function. If you are, I wish you good luck telling you boss.
We all make mistake, we are humans after all.
I hope you have enjoyed the article and I look forward writing more tips about SAS and Python.
If you want to know more about how you can learn Python the way you work in SAS, go to the following link to get more details:
https://www.nordstroem.uk
Some rights reserved