GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fin.c
1 /***************************************************************************
2  fin.c - description
3  -------------------
4  begin : Thursday June 15 2000
5  email : [email protected]
6  Author : Terry D. Boldt
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 /*
19  * Functions to compute financial equations and amortization schedules
20  * 6-15-2000
21  *
22  */
23 
24 /*
25  * Financial Calculator
26  *
27  * This version for use WITH ANSI.SYS display driver
28  *
29  * This is a complete financial computation utility to solve for the
30  * five * standard financial values: n, %i, PV, PMT and FV
31  *
32  * n == number of payment periods
33  * %i == nominal interest rate, NAR, charged
34  * PV == Present Value
35  * PMT == Periodic Payment
36  * FV == Future Value
37  *
38  * In addition, two additional parameters may be specified:
39  *
40  * 1) Compounding Frequency per year, CF. The compounding frequency
41  * per year may be discrete or continuous and may be different from
42  * the Payment Frequency per year
43  *
44  * 2) Payment Frequency per year, PF. Payments may be made at the
45  * beginning or the end of the payment period.
46  *
47  * When an amortization schedule is desired, the financial
48  * transaction Effective Date, ED, and Initial Payment Date, IP, must
49  * also be entered.
50  *
51  * Canadian and European style mortgages can be handled in a simple,
52  * straight-forward manner. Standard financial sign conventions are
53  * used:
54  *
55  * "Money paid out is Negative, Money received is Positive"
56  *
57  * Time value of money:
58  *
59  * If you borrow money, you can expect to pay rent or interest for its use;
60  * conversely you expect to receive rent interest on money you loan or invest.
61  * When you rent property, equipment, etc., rental payments are normal; this
62  * is also true when renting or borrowing money. Therefore, money is
63  * considered to have a "time value". Money available now, has a greater value
64  * than money available at some future date because of its rental value or the
65  * interest that it can produce during the intervening period.
66  *
67  * Simple Interest:
68  *
69  * If you loaned $800 to a friend with an agreement that at the end of one
70  * year he would would repay you $896, the "time value" you placed on your
71  * $800 (principal) was $96 (interest) for the one year period (term) of the
72  * loan. This relationship of principal, interest, and time (term) is most
73  * frequently expressed as an Annual Percentage Rate (APR). In this case the
74  * APR was 12.0% [(96/800)*100]. This example illustrates the four basic
75  * factors involved in a simple interest case. The time period (one year),
76  * rate (12.0% APR), present value of the principal ($800) and the future
77  * value of the principal including interest ($896).
78  *
79  * Compound Interest:
80  *
81  * In many cases the interest charge is computed periodically during the term
82  * of the agreement. For example, money left in a savings account earns
83  * interest that is periodically added to the principal and in turn earns
84  * additional interest during succeeding periods. The accumulation of interest
85  * during the investment period represents compound interest. If the loan
86  * agreement you made with your friend had specified a "compound interest
87  * rate" of 12% (compounded monthly) the $800 principal would have earned
88  * $101.46 interest for the one year period. The value of the original $800
89  * would be increased by 1% the first month to $808 which in turn would be
90  * increased by 1% to 816.08 the second month, reaching a future value of
91  * $901.46 after the twelfth iteration. The monthly compounding of the nominal
92  * annual rate (NAR) of 12% produces an effective Annual Percentage Rate (APR)
93  * of 12.683% [(101.46/800)*100]. Interest may be compounded at any regular
94  * interval; annually, semiannually, monthly, weekly, daily, even continuously
95  * (a specification in some financial models).
96  *
97  * Periodic Payments:
98  *
99  * When money is loaned for longer periods of time, it is customary for the
100  * agreement to require the borrower to make periodic payments to the lender
101  * during the term of the loan. The payments may be only large enough to repay
102  * the interest, with the principal due at the end of the loan period (an
103  * interest only loan), or large enough to fully repay both the interest and
104  * principal during the term of the loan (a fully amoritized loan). Many loans
105  * fall somewhere between, with payments that do not fully cover repayment of
106  * both the principal and interst. These loans require a larger final payment
107  * (balloon) to complete their amortization. Payments may occur at the
108  * beginning or end of a payment period. If you and your friend had agreed on
109  * monthly repayment of the $800 loan at 12% NAR compounded monthly, twelve
110  * payments of $71.08 for a total of $852.96 would be required to amortize the
111  * loan. The $101.46 interest from the annual plan is more than the $52.96
112  * under the monthly plan because under the monthly plan your friend would not
113  * have had the use of $800 for a full year.
114  *
115  * Financial Transactions:
116  *
117  * The above paragraphs introduce the basic factors that govern most
118  * financial transactions; the time period, interest rate, present value,
119  * payments and the future value. In addition, certain conventions must be
120  * adhered to: the interest rate must be relative to the compounding frequency
121  * and payment periods, and the term must be expressed as the total number of
122  * payments (or compounding periods if there are no payments). Loans, leases,
123  * mortgages, annuities, savings plans, appreciation, and compound growth are
124  * amoung the many financial problems that can be defined in these terms. Some
125  * transactions do not involve payments, but all of the other factors play a
126  * part in "time value of money" transactions. When any one of the five (four
127  * - if no payments are involved) factors is unknown, it can be derived from
128  * formulas using the known factors.
129  *
130  * Standard Financial Conventions Are:
131  *
132  * Money RECEIVED is a POSITIVE value and is represented by an arrow
133  * above * the line
134  *
135  * Money PAID OUT is a NEGATIVE value and is represented by an arrow
136  * below * the line.
137  *
138  * If payments are a part of the transaction, the number of payments
139  * must * equal the number of periods (n).
140  *
141  * Payments may be represented as occuring at the end or beginning of
142  * the * periods.
143  *
144  * Diagram to visualize the positive and negative cash flows (cash
145  * flow * diagrams):
146  *
147  * Amounts shown above the line are positve, received, and amounts
148  * shown below the line are negative, paid out.
149  *
150  * 1)
151  * FV*
152  * 1 2 3 4 . . . . . . . . . n � * Period ��������������������������������������������������������� * � * * PV * * Appreciation * Depreciation * Compound Growth * Savings Account * * **************************************************************************** * * 2) FV * PV = 0 * � * Period ��������������������������������������������������������� * � 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Annuity (series of payments) * Pension Fund * Savings Plan * Sinking Fund * * **************************************************************************** * * 3) * PV * � FV=0 * Period �������������������������������������������������������Ŀ * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
153  * Period ��������������������������������������������������������� * � * * PV * * Appreciation * Depreciation * Compound Growth * Savings Account * * **************************************************************************** * * 2) FV * PV = 0 * � * Period ��������������������������������������������������������� * � 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Annuity (series of payments) * Pension Fund * Savings Plan * Sinking Fund * * **************************************************************************** * * 3) * PV * � FV=0 * Period �������������������������������������������������������Ŀ * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
154  * � * * PV * * Appreciation * Depreciation * Compound Growth * Savings Account * * **************************************************************************** * * 2) FV * PV = 0 * � * Period ��������������������������������������������������������� * � 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Annuity (series of payments) * Pension Fund * Savings Plan * Sinking Fund * * **************************************************************************** * * 3) * PV * � FV=0 * Period �������������������������������������������������������Ŀ * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
155  *
156  * PV
157  *
158  * Appreciation
159  * Depreciation
160  * Compound Growth
161  * Savings Account
162  *
163  * ****************************************************************************
164  *
165  * 2) FV
166  * PV = 0
167  * � * Period ��������������������������������������������������������� * � 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Annuity (series of payments) * Pension Fund * Savings Plan * Sinking Fund * * **************************************************************************** * * 3) * PV * � FV=0 * Period �������������������������������������������������������Ŀ * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
168  * Period ��������������������������������������������������������� * � 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Annuity (series of payments) * Pension Fund * Savings Plan * Sinking Fund * * **************************************************************************** * * 3) * PV * � FV=0 * Period �������������������������������������������������������Ŀ * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
169  * � 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n
170  *
171  * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT
172  *
173  * Annuity (series of payments)
174  * Pension Fund
175  * Savings Plan
176  * Sinking Fund
177  *
178  * ****************************************************************************
179  *
180  * 3)
181  * PV
182  * � FV=0
183  * Period �������������������������������������������������������Ŀ * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
184  * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT * * Amortization * Direct Reduction Loan * Mortgage (fully amortized) * * **************************************************************************** * * 4) * FV* * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � + * PMT * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
185  *
186  * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT
187  *
188  * Amortization
189  * Direct Reduction Loan
190  * Mortgage (fully amortized)
191  *
192  * ****************************************************************************
193  *
194  * 4)
195  * FV*
196  * PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT PMT � +
197  * PMT
198  * 1 � 2 � 3 � 4 � . � . � . � . � . � . � . � . � . � n � * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
199  * Period ��������������������������������������������������������� * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
200  * � * * PV * * Annuity * Lease (with buy back or residual)* * Loan or Mortgage (with balloon)* * * **************************************************************************** * * First lets discuss interest before discussing the financial * equation. Most financial transactions utilize a nominal interest * rate, NAR, i.e., the interest rate per year. The NAR must be * converted to the interest rate per payment interval and the * compounding accounted for before it can be used in computing an * interest payment. After this conversion process, the interest * used is the effective interest rate, EIR. In converting NAR to * EIR, there are two concepts to discuss first, the Compounding * Frequency and the Payment Frequency and * whether the interest is * coumpounded in discrete intervals or continuously. The * compounding Frequency, CF, is simply the number of times per * year, the monies in the financial transaction are compounded. In * the U.S., monies are usually compounded daily on bank deposits, * and monthly on loans. Somtimes Long term deposits are compounded * quarterly or weekly. * * The Payment Frequency, PF, is simply how often during a year * payments are made in the transaction. Payments are usually * scheduled on a regular basis and can be made at the beginning or * end of the payment period. If made at the beginning of the * payment period, interest must be applied to the payment as well * as any previous money paid or money still owed. * * Normal values for CF and PF are: * 1 == annual * 2 == semi-annual * 3 == tri-annual * 4 == quaterly * 6 == bi-monthly * 12 == monthly * 24 == semi-monthly * 26 == bi-weekly * 52 == weekly * 360 == daily * 365 == daily * * a) the Compounding Frequency per year, CF, need not be identical * to the Payment Frequency per year, PF, and/or, * * b) Interest may be compounded in either discrete intervals or continuously * compounded. * * c) Also, payments may be made at the beginning of the payment * period or at the end of the payment period. * * CF and PF are defaulted to 1. The default is for discrete interest * intervals and payments are defaulted to the end of the payment * period. * * When a solution for n, PV, PMT or FV is required, the nominal interest * rate, i, must first be converted to the effective interest rate per payment * period. This rate, ieff, is then used to compute the selected variable. To * convert i to ieff, the following expressions are used: * * Discrete interest periods: * * 19) ieff = (1 + i/CF)^(CF/PF) - 1 * * Continuous Interest * * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1 * * When interest is computed, the computation produces the effective interest * rate, ieff. This value must then be converted to the nominal interest rate. * Function _I below returns the nominal interest rate NOT the effective * interest rate. ieff is converted to i using the following expressions: * * Discrete Case: * * i = CF*[(1+ieff)^(PF/CF) - 1] * * Continuous Case: * * i = ln[(1+ieff)^PF] * * **************************************************************************** * * NOTE: in the equations below for the financial transaction, all * interest rates are the effective interest rate, ieff. The symbol * will be shortned to just 'i'. * * **************************************************************************** * * The basic financial equation used is: * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0 * Where: X = 0 for end of period payments, and * X = 1 for beginning of period payments * * **************************************************************************** * * NOTE: this equation is derived in the following manner: * * Start with the basic equation to find the balance or Present * Value, PV[1], after one payment period. Note PV[1] is the Present * value after on payment and PV[0] is the initial Present * Value. PV[0] will be shortened to just PV. * * The interest due at the end of the first payment period is: * * ID[1] = (PV + X * PMT) * i * where: X = 0 for end of period payments, and * X = 1 for beginning of period payments. * * Thus: * PV[1] = PV + (PMT + ID[1]) * = PV + (PMT + (PV + X * PMT) * i) * = PV * (1 + i) + PMT * (1 + Xi) * * This equation works for all of the money diagrams shown * above. The Present Value, money received or paid, is modified by * a payment made at the beginning of a payment period and * multiplied by the effective interest rate to compute the interest * due during the payment period. The interest due is then added to * the payment to obtain the amount to be added to the Present Value * to compute the new Present Value. * * For diagram 1): PV < 0, PMT == 0, PV[1] < 0 * For diagram 2): PV == 0, PMT < 0, PV[1] < 0 * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0 * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0 * * X may be 0 or 1 for any diagram. * * For the standard loan, PV is the money borrowed, PMT is the * periodic payment to repay the loan and i is the effective * interest rate agreed upon. * * To calculate the Present Value after the second payment period, * the above calculation is applied iteratively to PV_1: * * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i) * = PV[1] * (1 + i) + PMT * (1 + iX) * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * Similarly: * * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i) * = PV[2] * (1 + i) + PMT * (1 + iX) * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i) * + PMT * (1+ iX)) * ( 1 + i) * + PMT * (1+ iX) * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i)^2 * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * * And for the n'th payment: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1) * + PMT * (1 + iX) * (1 + i)^(n-2) + * . * . * . * + PMT * (1 + iX) * (1 + i) * + PMT * (1 + iX) * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * * **************************************************************************** * * The sum of the finite series: * * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k) * * as can be seen by the following. Let S(n) be the series sum. Then * * S(n) - k * S(n) = 1 - k^(n+1) * * and solving for S(n): * * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n) * * **************************************************************************** * * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ... * + (1 + i) + 1] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)] * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i] * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i * * The formaula for PV[n] can be proven using mathematical induction. * * or: * * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0 * * If after n payments, the remaining balance is repaid as a lump * sum, the lump sum is known as the Future Value, FV[n]. Since * FV[n] is negative if paid and positive if received, FV[n] is the * negative of PV[n]. Since n is assumed to be the last payment, * FV[n] will be shortened to simply FV. * * Setting: FV = -PV[N] * * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0 * * Up to this point, we have said nothing about the value of * PMT. PMT can be any value mutually agreed upon by the lender and * the borrower. From the equation for PV[1]: * * PV[1] = PV + (PMT + (PV + X * PMT) * i), * * Several things can be said about PMT. * * 1. If PMT = PV * i, and X = 0 (end of period payments): * * The payment is exactly equal to the interest due and PV[1] = * PV. In this case, the borrower must make larger future * payments to reduce the balance due, or make a single payment, * after some agreed upon number of payments, with PMT = PV to * completely pay off the loan. This is an interest only payment * with a balloon payment at the end. * * 2. If PMT < PV * i, and X = 0 * * The payment is insufficient to cover even the interest charged * and the balance due grows * * 3. If PMT > PV * i, and X = 0 * * The payment is sufficient to cover the interest charged with a * residual amount to be applied to reduce the balance due. The * larger the residual amount, the faster the loan is repaid. For * most mortgages or other loans made today, the lender and * borrower agree upon a certain number of repayment periods and * the interest to be charged per payment period. The interest * may be multiplied by 12 and stated as an annual interest * rate. Then the lender and borrower want to compute a periodic * payment, PMT, which will reduce the balance due to zero after * the agreed upon number of payment have been made. If N is the * agreed upon number of periodic payments, then we want to use: * * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0 * * with FV = 0 to compute PMT: * * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1] * * The value of PMT computed will reduce the balance due to zero * after N periodic payments. * * **************************************************************************** * * * With a simple alegebraic re-arrangement, The financial Equation becomes: * * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0 * * or * * 3) (PV + C)*A + PV + FV = 0 * * where: * 4) A = (1 + i)^n - 1 * * 5) B = (1 + iX)/i * * 6) C = PMT*B * * The form of equation 3) simplifies the calculation procedure for all five * variables, which are readily solved as follows: * * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i) * * 8) PV = -[FV + A*C]/(A + 1) * * 9) PMT = -[FV + PV*(A + 1)]/[A*B] * * 10) FV = -[PV + A*(PV + C)] * * Equations 4), 5) and 6) are computed by functions: * * _A * _B * _C * * respectively. Equations 7), 8), 9) and 10) are computed by functions: * * _N * _PV * _PMT * _FV * * respectively. * * The solution for interest is broken into two cases: * * PMT == 0 * i = [FV/PV]^(1/n) - 1 * * PMT != 0 * * Since equation 3) cannot be solved explicitly for i in this * case, an iterative technique must be employed. Newton's * method, using exact expressions for the function of i and its * derivative, are employed. The expressions are: * * 12) i[k+1] = i[k] - f(i[k])/f'(i[k]) * where: i[k+1] == (k+1)st iteration of i * i[k] == kth iteration of i * and: * * 13) f(i) = A*(PV+C) + PV + FV * * 14) f'(i) = n*D*(PV+C) - (A*C)/i * * 15) D = (1 + i)^(n-1) = (A+1)/(1+i) * * To start the iterative solution for i, an initial guess must be made * for the value of i. The closer this guess is to the actual value, * the fewer iterations will have to be made, and the greater the * probability that the required solution will be obtained. The initial * guess for i is obtained as follows: * * if PMT*FV >= 0, then PV case * if PMT*FV < 0, then FV case * * PV case: * | n*PMT + PV + FV | * 16) i[0] = | ----------------| * | n*PV | * * = abs[(n*PMT + PV + FV)/(n*PV)] * * FV case: * a) PV != 0 * * | FV - n*PMT | * 17) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * b) PV == 0 * * | FV + n*PMT | * 18) i[0] = |---------------------------| * | 3*[PMT*(n-1)^2 + PV - FV] | * * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))] * * **************************************************************************** * Constant payment to principal loan * * In this loan, each total payment is different, with each * succeeding payment less than the preceeding payment. Each payment * is the total of the constant ammount to the principal plus the * interest for the period. The constant payment to the principal is * computed as: * * C = -PV / N * * Where PV is the loan amount to be repaid in N payments * (periods). Note that the constant payment to principal could be * any value agreed to by the two parties involved. * * Thus the principal after the first payment is: * PV[1] = PV[0] + C = PV + C * after the second payment, the principal is: * PV[2] = PV[1] + C = PV[0] + 2C * In general, the remaining principal after n payments is: * PV[n] = PV[0] + nC = PV + nC * * If the effective interest per payment period is i, then the * interest for the first payment is: * * I[1] = -i*PV[0] = -i*PV * and for the second: * I[2] = -i * PV[1] * and in general, for the n'th payment the interest is: * I[n] = -i * PV[n-1] * = -i * (PV + (n-1)C) * The total payment for any period, n, is: * P[n] = C + I[n] * = C + i * (PV + (n-1)C) * = C(1 + i) - i * (PV + nC) * The total interest paid to period n is: * T[n] = I[1] + I[2] + I[3] + ... + I[n] * T[n] = sum(j = 1 to n: I[j]) * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C)) * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj) * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j) * sum(j=1 to n:j) = n(n+1)/2 * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2 * T[n] = -i*n*(PV + (C*(n - 1)/2)) * * Note: substituing for C = -PV/N, in the equations for PV[n], I[n], * P[n], and T[n] would give the following equations: * * PV[n] = PV*(1 - n/N) * I[n] = -i*PV*(1 + N - n)/N * P[n] = -i*PV*(2 + N - n)/N * T[n] = -i*n*PV*(2*N - n + 1)/(2*N) * * Using these equations for the calculations would eliminate the * dependence on C, but only if C is always defined as above and * would eliminate the possibility of another value for C. If the * value of C was less than -PV/N then a balloon payment would be * due at the final payment and this is a possible alternative for * some people. * * **************************************************************************** * * Amortization Schedules. * * Financial Transactions have an effective Date, ED, and an Initial Payment * Date, IP. ED may or may not be the same as IP, but IP is always the same * or later than ED. Most financial transaction calculators assume that * IP is equal to ED for beginning of period payments or at the end of the * first payment period for end of period payments. * * This is not always true. IP may be delayed for financial reasons * such as cash flow or accounting calender. The subsequent payments * then follow the agreed upon periodicity. Since money has a time * value, the "delayed" IP must be accounted for. Computing an * "Effective PV", pve, is one means of handling a delayed IP. * * EDj == the Julian Day Number of ED, and * IPj == the Julian Day Number of IP in the following. * * pve is be computed as: * * pve = pv*(1 + i)^(s*PF/d*CF) * * Where: d = length of the payment period in days, and * s = IPj - EDj - d*X * * Computing an amortization Schedule for a given financial transaction is * simply applying the basic equation iteratively for each payment period: * * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i) * * At the end of each iteration, PV[n] is rounded to the nearest cent. For * each payment period, the interest due may be computed separately as: * * ID[n] = (PMT + (PV[n-1] + X * PMT) * i) * * and rounded to the nearest cent. PV[n] then becomes: * * PV[n] = PV[n-1] + PMT + ID[n] * * For those cases where a yearly summary only is desired, it is not * necessary to compute each transaction for each payment period, * rather the PV may be be computed for the beginning of each year, * PV[yr], and the FV computed for the end of the year, FV[yr]. The * interest paid during the year is the computed as: * * ID[yr] = (NP * PMT) + PV[yr] + FV[yr] * * Since the final payment may not be equal to the periodic payment, * the final payment must be computed separately as follows. Two * derivations are given below for the final payment equation. Both * derivations are given below since one or the other may be clearer * to some readers. Both derivations are essentially the same, they * just have different starting points. The first is the fastest. * * 1) final_pmt == final payment @ payment n == int(n) * from above the basic financial equation: * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX), * i == effective interest rate * * solving for final_pmt, we have: * * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i) * = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * * 2) final_pmt == final payment @ payment n == int(n) * i[n] == interest due @ payment n * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate * = (X * final_pmt - FV[n]) * i * * Now the final payment is the sum of the interest due, plus * the present value at the next to last payment plus any * residual future value after the last payment: * * final_pmt = -i[n] - PV[n-1] - FV[n] * = FV[n-1] - i[n] - FV[n] * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n] * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n] * * solving for final_pmt: * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n] * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX) * * final_pmt = FV[n-1]*(1 + i) - FV[n], * for X == 0, end of period payments * * = FV[n-1] - FV[n]/(1 + i), * for X == 1, beginning of period payments * *============================================================================ * * The amortization schedule is computed for four different situations: * * 1) The original financial data is used. This ignores any possible * agjustment to the Present value due to any delay in the initial * payment. This is quite common in mortgages where end of period * payments are used and the first payment is scheduled for the end * of the first whole period, i.e., any partial payment period from * ED to the beginning of the next payment period is ignored. * * 2) The original periodic payment is used, the Present Value is * adjusted for the delayed Initial Payment. The total number of * payments remains the same. The final payment is adjusted to bring * the balance into agreement with the agreed upon final Future * Value. * * 3) A new periodic payment is computed based upon the adjusted * Present Value, the agreed originally upon number of total * payments and the agreed upon Future Value. The new periodic * payments are computed to minimize the final payment in accordance * with the Future Value after the last payment. * * 4) The original periodic payment is retained and a new number of * total payments is computed based upon the adjusted Present Value * and the agreed upon Future Value. * * The amortization schedule may be computed and displayed in three manners: * * 1. The payment *, interest paid, principal paid and remaining PV * for each payment period are computed and displayed. At the end of * each year a summary is computed and displayed and the total * interest paid is diplayed at the end. * * 2. A summary is computed and displayed for each year. The * interest paid during the year is computed and displayed as well * as the remaining balance at years end. The total interest paid * is diplayed at the end. * * 3. An amortization schedule is computed for a common method of * advanced payment of principal is computed and displayed. In this * amortization, the principal for the next payment is computed and * added into the current payment. This method will cut the number * of total payments in half and will cut the interest paid almost * in half. For mortgages, this method of prepayment has the * advantage of keeping the total payments small during the initial * payment periods The payments grow until the last payment period * when presumably the borrower can afford larger payments. * * =========================================================================== * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF * == 12 or PF == 24, a 360 day calender year and 30 day month are * used. For Payment Frequencies, PF, greater than semi-monthly, PF * > 24, the actual number of days per year and per payment period * are used. The actual values are computed using the built-in * 'julian_day_number' function * * **************************************************************************** * * Note: in the following examples, the user input is preceeded by the * prompt "<>". The result of evaluating the input expression is then * displayed. I have taken the liberty of including comments in the * example input/output sessions by preceeding with ' *'. Thus, for * the line: <>n=5 *set number of periods the comment that setting the * number of periods is not really input and the true input is only: * <>n=5 * * Example 1: Simple Interest * Find annual simple interest rate (%) for an $800 loan to be repayed at the * end of one year with a single payment of $896. * <>d * <>CF=PF=1 * 1.00 * <>n=1 * 1.00 * <>pv=-800 * -800.00 * <>fv=896 * 896.00 * <>I * 12.00 * * Example 2: Compound Interest * Find the future value of $800 after one year at a nominal rate of 12% * compounded monthly. No payments are specified, so the payment frequency is * set equal to the compounding frequency at the default values. * <>d * <>n=12 * 12.00 * <>i=12 * 12.00 * <>pv=-800 * -800.00 * <>FV * 901.46 * * Example 3: Periodic Payment: * Find the monthly end-of-period payment required to fully amortize the loan * in Example 2. A fully amortized loan has a future value of zero. * <>fv=0 * 0.00 * <>PMT * 71.08 * * Example 4: Conventional Mortgage * * Find the number of monthly payments necessary to fully amortize a * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if * monthly end-of-period payments of $1125.75 are made. * * <>d * <>i=13.25 * 13.25 * <>pv=100000 * 100,000.00 * <>pmt=-1125.75 * -1,125.75 * <>_N(i,pv,pmt,fv,CF,PF,disc,bep) * 360.10 * <>N * 360 * * Example 5: Final Payment * Using the data in example 4, find the amount of the final payment if n is * changed to 360. The final payment will be equal to the regular payment plus * any balance, future value, remaining at the end of period number 360. * <>n=360 * 360.00 * <>FV * -108.87 * <>pmt+fv * -1,234.62 * * Using the data from this loan, compute the amortization schedule * when the Effective date of the loan is June 6, 1996 and the * initial payment is made on August 1, 1996. Ignore any change in * the PV due to the delayed initial payment caused by the partial * payment period from June 6 to July 1. * * <>ED = 06/06/1996 * Effective Date set: 06/06/1996 ( 2450241 ) * <>IP = 08/01/1996 * Initial Payment Date set: 08/01/1996 ( 2450297 ) * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: -108.87 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,125.75 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.10 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,023.68 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,132.57 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,090.27 * * Enter choice 1, 2, 3 or 4: <> * * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,125.75 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -236.00 -108.87 * * Total Interest: -305,270.00 * * NOTE: The amortization table leaves the FV as it was when the amortization * function was entered. Thus, a balance of 108.87 is due at the end of the * table. To completely pay the loan, set fv to 0.0: * <>fv=0 * 0.0 * <>a * Effective Date: 06/06/96 * Initial Payment Date: 08/01/96 * The amortization options are: * The Old Present Value (pv) was: 100,000.00 * The Old Periodic Payment (pmt) was: -1,125.75 * The Old Future Value (fv) was: 0.00 * 1: Amortize with Original Transaction Values * and balloon final payment: -1,234.62 * * The New Present Value (pve) is: 100,919.30 * The New Periodic Payment (pmt) is: -1,136.12 * 2: Amortize with Original Periodic Payment * and balloon final payment: -49,132.55 * 3: Amortize with New Periodic Payment * and balloon final payment: -1,148.90 * 4: Amortize with Original Periodic Payment, * new number of total payments (n): 417 * and final payment: -2,199.14 * * Enter choice 1, 2, 3 or 4: <> * Press '1' * Amortization Schedule: * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization * Enter choice y, p or a: * <> * Press 'y' * Enter Filename for Amortization Schedule. * (null string uses Standard Output): * Press enter to display output on screen * * Amortization Table * Effective Date: Thu Jun 06 00:00:00 1996 * Initial Payment Date: Thu Aug 01 00:00:00 1996 * Compounding Frequency per year: 12 * Payment Frequency per year: 12 * Compounding: Discrete * Payments: End of Period * Payments (359): -1,125.75 * Final payment: -1,234.62 * Nominal Annual Interest Rate: 13.25 * Effective Interest Rate Per Payment Period: 0.0110417 * Present Value: 100,000.00 * Year Interest Ending Balance * 1996 -5,518.42 -99,889.67 * 1997 -13,218.14 -99,598.81 * 1998 -13,177.17 -99,266.98 * 1999 -13,130.43 -98,888.41 * 2000 -13,077.11 -98,456.52 * 2001 -13,016.28 -97,963.80 * 2002 -12,946.88 -97,401.68 * 2003 -12,867.70 -96,760.38 * 2004 -12,777.38 -96,028.76 * 2005 -12,674.33 -95,194.09 * 2006 -12,556.76 -94,241.85 * 2007 -12,422.64 -93,155.49 * 2008 -12,269.63 -91,916.12 * 2009 -12,095.06 -90,502.18 * 2010 -11,895.91 -88,889.09 * 2011 -11,668.70 -87,048.79 * 2012 -11,409.50 -84,949.29 * 2013 -11,113.78 -82,554.07 * 2014 -10,776.41 -79,821.48 * 2015 -10,391.53 -76,704.01 * 2016 -9,952.43 -73,147.44 * 2017 -9,451.49 -69,089.93 * 2018 -8,879.99 -64,460.92 * 2019 -8,227.99 -59,179.91 * 2020 -7,484.16 -53,155.07 * 2021 -6,635.56 -46,281.63 * 2022 -5,667.43 -38,440.06 * 2023 -4,562.94 -29,494.00 * 2024 -3,302.89 -19,287.89 * 2025 -1,865.36 -7,644.25 * 2026 -344.87 0.00 * * Total Interest: -305,378.87 * * Example 6: Balloon Payment * On long term loans, small changes in the periodic payments can generate * large changes in the future value. If the monthly payment in example 5 is * rounded down to $1125, how much addtional (balloon) payment will be due * with the final regular payment. * <>pmt=-1125 * -1,125 * <>FV * -3,579.99 * * Example 7: Canadian Mortgage * Find the monthly end-of-period payment necessary to fully amortize a 25 year * $85,000 loan at 11% compounded semi-annually. * <>d * <>CF=2 * 2.00 * <>n=300 * 300.00 * <>i=11 * 11.00 * <>pv=85000 * 85,000.00 * <>PMT * -818.15 * * Example 8: European Mortgage * The "effective annual rate (EAR)" is used in some countries (especially * in Europe) in lieu of the nominal rate commonly used in the United States * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly * end-of-period payments. When using an EAR, the compounding frequency is * set to 1. * <>d * <>CF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=14 * 14.00 * <>pv=90000 * 90,000.00 * <>PMT * -1,007.88 * * Example 9: Bi-weekly Savings * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a * nominal annual rate of 5.5% compounded daily. (Set payment to * beginning-of-period, bep = TRUE) * <>d * <>bep=TRUE * 1.00 * <>CF=365 * 365.00 * <>PF=26 * 26.00 * <>n=3*26 * 78.00 * <>i=5.5 * 5.50 * <>pmt=-100 * -100.00 * <>FV * 8,489.32 * * Example 10: Present Value - Annuity Due * What is the present value of $500 to be received at the beginning of each * quarter over a 10 year period if money is being discounted at 10% nominal * annual rate compounded monthly? * <>d * <>bep=TRUE * 1.00 * <>PF=4 * 4.00 * <>n=4*10 * 40.00 * <>i=10 * 10.00 * <>pmt=500 * 500.00 * <>PV * -12,822.64 * * Example 11: Effective Rate - 365/360 Basis * Compute the effective annual rate (%APR) for a nominal annual rate of 12% * compounded on a 365/360 basis used by some Savings & Loan Associations. * <>d * <>n=365 * 365.00 * <>CF=365 * 365.00 * <>PF=360 * 360.00 * <>i=12 * 12.00 * <>pv=-100 * -100.00 * <>FV * 112.94 * <>fv+pv * 12.94 * * Example 12: Mortgage with "Points" * * What is the true APR of a 30 year, $75,000 loan at a nominal rate * of 13.25% compounded monthly, with monthly end-of-period payments, * if 3 "points" are charged? The pv must be reduced by the dollar * value of the points and/or any lenders fees to establish an * effective pv. Because payments remain the same, the true APR will * be higher than the nominal rate. Note, first compute the payments * on the pv of the loan amount. * * <>d * <>CF=PF=1 * 1.00 * <>n=30*12 * 360.00 * <>i=13.25/12 * 1.10 * <>pv=75000 * 75,000.00 * <>PMT * -844.33 * <>pv -= pv*.03 * 72,750.00 * <>CF=PF=12 * 12.00 * <>I * 13.69 * * Example 13: Equivalent Payments * Find the equivalent monthly payment required to amortize a 20 year $40,000 * loan at 10.5% nominal annual rate compounded monthly, with 10 annual * payments of $5029.71 remaining. Compute the pv of the remaining annual * payments, then change n, the number of periods, and the payment frequency, * PF, to a monthly basis and compute the equivalent monthly pmt. * <>d * <>PF=1 * 1.00 * <>n=10 * 10.00 * <>i=10.5 * 10.50 * <>pmt=-5029.71 * -5,029.71 * <>PV * 29,595.88 * <>PF=12 * 12.00 * <>n=120 * 120.00 * <>PMT * -399.35 * * Example 14: Perpetuity - Continuous Compounding * If you can purchase a single payment annuity with an initial investment of * $60,000 that will be invested at 15% nominal annual rate compounded * continuously, what is the maximum monthly return you can receive without * reducing the $60,000 principal? If the principal is not disturbed, the * payments can go on indefinitely (a perpetuity). Note that the term,n, of * a perpetuity is immaterial. It can be any non-zero value. * <>d * <>disc=FALSE * 0.00 * <>n=12 * 12.00 * <>CF=1 * 1.00 * <>i=15 * 15.00 * <>fv=60000 * 60,000.00 * <>pv=-60000 * -60,000.00 * <>PMT * 754.71 * * references: * 1. PPC ROM User's Manual * pages 148 - 164 * */ #include <time.h> #include <stdio.h> #include <glib.h> #include <math.h> #if defined(G_OS_WIN32) && !defined(_MSC_VER) #include <pow.h> #endif #include <string.h> #include <stdlib.h> #define FIN_STATICS #include "finvar.h" #include "finproto.h" #include "fin_static_proto.h" /* return 'x' rounded to 'places' past decimal if 'places' < 0, return * 'x' */ static double rnd (double x, unsigned places) { double r; char buf[50]; /* make buffer large enough */ sprintf (buf, "%.*f", (int) places, x); r = strtod(buf, NULL); return r; } /* rnd */ /* return absolute value of 'x' this function is provided by a macro * in C */ static double dabs (double x) { return (x >= 0.0) ? x : -x; } /* dabs */ /* Compute constant used in calculations */ static double _A (double eint, unsigned per) { return pow ((1.0 + eint), (double) per) - 1.0; } /* _A */ /* Compute constant used in calculations */ static double _B (double eint, unsigned beg) { /* if eint == 0.0, all processing _must_ stop or a recursive loop will start. */ g_return_val_if_fail(eint != 0.0, 0.0); return (1.0 + eint * (double) beg) / eint; } /* _B */ /* Compute constant used in calculations */ static double _C (double eint, double pmt, unsigned beg) { g_return_val_if_fail(eint != 0.0, 0.0); return pmt * _B(eint, beg); } /* _C */ /* compute Number of Periods from preset data */ unsigned fi_calc_num_payments (fi_ptr fi) { return fi->npp = (unsigned) rnd (_fi_calc_num_payments (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), 0); } /* fi_calc_num_payments */ /* Compute number of periods from: * 1. Nominal Interest * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_num_payments (double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double CC = _C (eint, pmt, bep); CC = (CC - fv) / (CC + pv); return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0; } /* _fi_calc_num_payments */ /* compute Interest from preset data */ double fi_calc_interest (fi_ptr fi) { if (fi->npp) fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep); return fi->ir; } /* fi_calc_interest */ double ratio = 1e4; /* ratio used in iterative solution for interest */ /* Compute Nominal Interest from: * 1. Number of periods * 2. Present Value * 3. Periodic Payment * 4. Future Value */ double _fi_calc_interest (unsigned per,/* number of periods */ double pv, /* present value */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint; double a, dik; int ri; if (pmt == 0.0) eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0; else { if ((pmt * fv) < 0.0) { if (pv) a = -1.0; else a = 1.0; eint = dabs ((fv + a * (double) per * pmt) / (3.0 * (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv - fv))); } else { if ((pv * pmt) < 0.0) { eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv)); } else { a = dabs (pmt / (dabs (pv) + dabs (fv))); eint = a + 1.0 / (a * (double) per * (double) per * (double) per); } } do { dik = fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep); eint -= dik; (void) modf (ratio * (dik / eint), &a); ri = (unsigned) a; } while (ri); } /* endif */ return 100.0 * nom_int (eint, CF, PF, disc); } /* _fi_calc_interest */ /* compute Present value from preset data */ double fi_calc_present_value (fi_ptr fi) { return fi->pv = rnd (_fi_calc_present_value (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_present_value */ /* Compute Present Value from: * 1. Number of periods * 2. Nominal Interest * 3. Periodic Payment * 4. Future Value */ double _fi_calc_present_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pmt, /* periodic payment */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(fv + (AA * CC)) / (AA + 1.0); } /* _fi_calc_present_value */ /* compute Periodic Payment from preset data */ double fi_calc_payment (fi_ptr fi) { return fi->pmt = rnd (_fi_calc_payment (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_payment */ /* Compute Periodic Payment from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Future Value */ double _fi_calc_payment (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double fv, /* future value */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc,/* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double BB = _B (eint, bep); g_return_val_if_fail(BB != 0.0, 0.0); return -(fv + pv * (AA + 1.0)) / (AA * BB); } /* _fi_calc_payment */ /* compute Future Value from preset data */ double fi_calc_future_value (fi_ptr fi) { return fi->fv = rnd (_fi_calc_future_value (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc, fi->bep), fi->prec); } /* fi_calc_future_value */ /* Compute Future Value from: * 1. Number of periods * 2. Nominal Interest * 3. Present Value * 4. Periodic Payments */ double _fi_calc_future_value (unsigned per, /* number of periods */ double nint, /* nominal interest rate */ double pv, /* present value */ double pmt, /* periodic payment */ unsigned CF, /* compounding frequency */ unsigned PF, /* payment frequency */ unsigned disc, /* discrete/continuous compounding */ unsigned bep) /* beginning/end of period payment */ { double eint = eff_int (nint / 100.0, CF, PF, disc); double AA = _A (eint, per); double CC = _C (eint, pmt, bep); return -(pv + AA * (pv + CC)); } /* _fi_calc_future_value */ /* compute Nominal Interest Rate from Effective Interest Rate */ static double nom_int (double eint, unsigned CF, unsigned PF, unsigned disc) { double nint; if (disc) { if (CF == PF) { nint = CF * eint; } else { nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0); } /* * endif */ } else nint = log (pow (1.0 + eint, PF)); return nint; } /* nom_int */ /* Compute Effective Interest Rate from Nominal Interest Rate */ static double eff_int (double nint, unsigned CF, unsigned PF, unsigned disc) { double eint; if (disc) { if (CF == PF) { eint = nint / (double) CF; } else { eint = pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0; } /* endif */ } else eint = exp (nint / (double) PF) - 1.0; return eint; } /* eff_int */ /* calculation used in interest computation */ static double fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv; } /* fi */ /* calculation used in interest computation */ static double fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep) { double AA = _A (eint, per); double CC = _C (eint, pmt, bep); double D = (AA + 1.0) / (1.0 + eint); g_return_val_if_fail(CC != 0.0, 0.0); return (double) per * (pv + CC) * D - (AA * CC) / eint; } /* fip */ void set_default (fi_ptr fi) { /* flag whether accrueing interest at beginning or end of period * FALSE --> end * TRUE --> beginning * default to end of period payment s */ fi->bep = FALSE; /* flag for discrete or continuous interest * TRUE --> discrete * FALSE --> continuous * default to discrete interest */ fi->disc = TRUE; /* set compounding, CF, and payment, PF, frequency per year * default to monthly payments and compounding */ fi->CF = fi->PF = 12; /* standard loan quantities: * number of periods: n */ fi->npp = 0; /* annual interest: i */ fi->ir = 0.0; /* Present Value: pv */ fi->pv = 0.0; /* Payment: pmt */ fi->pmt = 0.0; /* Future Value: fv */ fi->fv = 0.0; } /* set_default */ /* compute Julian Day Number from calender date */ unsigned long julian_day_number (unsigned year, unsigned month, unsigned day) { /* Gregorian/Julian Calender Flag. * TRUE == Julian * FALSE == Gregorian */ unsigned gregorian = TRUE; /* assume we are dealing with current dates */ double yr; double pfac = 0.6; unsigned long ljdn; yr = year + (month - 3.0) / 12.0; ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0) + (long) day + 1721117L; if (gregorian) ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2; return ljdn; } /* julian_day_number */ amort_sched_ptr Amortization_init (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint; double new_pmt; double pve; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; unsigned new_n; unsigned prec = amortsched->prec; unsigned long s, d, days_to_yr_end, Eff_Date_jdn = julian_day_number (amortsched->year_E, amortsched->month_E, amortsched->day_E), Init_Date_jdn = julian_day_number (amortsched->year_I, amortsched->month_I, amortsched->day_I); amortsched->Eff_Date_jdn = Eff_Date_jdn; amortsched->Init_Date_jdn = Init_Date_jdn; amortsched->yday_E = Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1); amortsched->yday_I = Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1); amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc); amortsched->fv_case = dabs (fv) > dabs (pv); amortsched->bp = bep ? 1.0 : 0.0; if (PF > 24) { /* Payment frequency per year greater than bi-monthly * use actual number of days */ s = Init_Date_jdn - Eff_Date_jdn; days_to_yr_end = julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn; d = 366 / PF; } else { /* Payment frequency per year bi-monthly or less * use 30 days/month, 360 days/year */ if (Eff_Date_jdn == Init_Date_jdn) { s = 0; } else { s = ((amortsched->year_I - amortsched->year_E) * 360) + ((amortsched->month_I - amortsched->month_E) * 30) + amortsched->day_I - amortsched->day_E; } /* endif */ days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I; d = 360 / PF; } /* endif */ if (!bep) { /* ordinary annuity */ s -= d; } /* endif */ amortsched->yr_pmt = (days_to_yr_end + d) / d; if (pmt == 0.0) { s = 0; amortsched->pve = pv; } else { amortsched->pve = rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))), prec); } /* endif */ pve = amortsched->pve; /* compute new data to fully amortize loan: * new periodic payment, new_pmt * * option 1: Amortize with original transaction - ignore interest * due to delayed initial payment * * option 2: Amortize with new pv, pve == original pv adjusted for * delayed initial payment, original payment, original fv and * original total number of payments, adjust final payment * * option 3: amortize with new pv, pve, and new payments adjusted to * minimize final payment, keep original number of payments and * original fv * * option 4: amortize with new pv, pve, original payments and new * number of payments to keep original final fv */ /* option 3, compute new periodic payment */ amortsched->new_pmt = new_pmt = rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec); /* option 4: compute new number of total payments, new_n */ amortsched->new_n = new_n = (unsigned) rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0); /* following used in QTAwk to insure integer value, not needed in C */ /* n = int(n); */ /* compute payment for constant payment to principal loan and final * payment for original loan amount include interest due */ amortsched->cpmt1 = rnd (-pv / n, prec); amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1); amortsched->final_pmt_opt_1 *= eint + 1; /* compute payment for constant payment to principal loan and final * payment for delayed loan amount include interest due */ amortsched->cpmt2 = rnd (-pve / n, prec); amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1); amortsched->final_pmt_opt_2 *= eint + 1; if (bep) { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) - (fv / (1.0 + eint)), prec); else amortsched->final_pmt_opt_6 = 0.0; } else { amortsched->final_pmt_opt_3 = rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_4 = rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); amortsched->final_pmt_opt_5 = rnd (_fi_calc_future_value (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); if (new_n) amortsched->final_pmt_opt_6 = rnd (_fi_calc_future_value (new_n - 1, nint, pve, pmt, CF, PF, disc, bep) * (1.0 + eint) - fv, prec); else amortsched->final_pmt_opt_6 = 0.0; } /* endif */ /* compute delayed interest */ amortsched->delayed_int = pv - amortsched->pve; return amortsched; } /* Amortization_init */ amort_sched_ptr Amortization_Schedule (amort_sched_ptr amortsched) { unsigned n = amortsched->n; double nint = amortsched->nint; double pv = amortsched->pv; double pmt = amortsched->pmt; double fv = amortsched->fv; double eint = amortsched->eint; unsigned CF = amortsched->CF; unsigned PF = amortsched->PF; unsigned disc = amortsched->disc; unsigned bep = amortsched->bep; double cpmt = 0; double final_pmt = 0; char summary = amortsched->summary; unsigned option = amortsched->option; unsigned yr_pmt = amortsched->yr_pmt; unsigned fv_case = amortsched->fv_case; unsigned prec = amortsched->prec; unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt; int jj; unsigned long d; double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0; yearly_summary_ptr yrly_sum; amort_sched_yr_ptr amortyr; sched_pmt_ptr pmtsched = NULL; sum_int = yr_int = 0.0; switch (option) { case 1: amortsched->cpmt = cpmt = amortsched->cpmt1; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 2: amortsched->cpmt = cpmt = amortsched->cpmt2; pv = amortsched->pve; /* re-compute final payment without interest */ amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1); summary = (summary == 'y') ? 'x' : 'o'; break; case 3: amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3; break; case 4: pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4; break; case 5: pv = amortsched->pve; pmt = amortsched->new_pmt; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5; break; case 6: n = amortsched->new_n; pv = amortsched->pve; amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6; break; } /* endswitch */ yr = amortsched->year_I; sum_prt = TRUE; switch (summary) { case 'a': /* variable advanced prepayment schedule. prepayment equals next * period principal. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = fv; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* compute principal for next payment cycle and round to nearest cent */ adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipla payment to remaining pv */ adv_pmt = -pv; /* and set remaining pv to fv */ pv = fv; } /* ## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmtsched++; pmt_cnt++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (dabs (pv) > 0.0) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'f': /* fixed prepaymet schedule prepayment specified by user */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); d = pv; /* set advnaced payment */ adv_pmt = amortsched->fixed_pmt; for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++) { /* basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period and round to nearest cent */ if (dabs (pmt) > dabs (pv)) { prin = -pv; pmt = prin + pmt_int; adv_pmt = 0.0; pv = 0.0; } else { prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (dabs (pv) >= dabs (adv_pmt)) { /* remaining pv greater than advanced principal payment * compute remaining pv and round to nearest cent */ pv = rnd (pv + adv_pmt, prec); } else { /* remaining pv less than advanced principal payment reduce * advanced pricipal payment to remaining pv and set * remaining pv to fv */ adv_pmt = -pv; pv = fv; } /*## endif */ } /* # endif */ if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); pmt_cnt = 0; sum_prt = FALSE; } else { (amortyr->num_periods)++; } /* ## endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = pmt + adv_pmt; pmtsched->balance = pv; pmt_cnt++; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* ## endif */ } /* ## endfor */ if (pv != fv) { /* # basic equation to compute interest this payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* # sum yearly interest paid */ yr_int += pmt_int; /* # sum total interest paid */ sum_int += pmt_int; /* # compute principal paid this payment period and round to nearest cent */ prin = rnd (pmt - pmt_int, prec); final_pmt = pmt; /* # compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); /* # Set advanced principal payment to remaining pv */ adv_pmt = -pv; amortyr->final_pmt = final_pmt += adv_pmt; /* # and set remaining pv to fv */ pv = fv; pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->advanced_pmt = adv_pmt; pmtsched->total_pmt = final_pmt; pmtsched->balance = pv; per_cnt++; pmt_cnt++; } /* # endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = pv - hpv; amortyr->total_interest_pd = sum_int; amortyr->num_periods = pmt_cnt; } /* endif */ amortsched->total_periods = per_cnt; break; case 'o': /* Constant payment to principal use constant payment equal to * original pv divided by number of periods. constant payment to * pricipal could be amount specified by user. */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; d = yr_pmt; for (s = 1, j = n - 1; j; j--, k++) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pv = rnd (pv + cpmt, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; k = 0; sum_prt = FALSE; } /* endif */ pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->total_pmt = cpmt + pmt_int; pmtsched->balance = pv; pmtsched++; if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = d * cpmt; amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; d = PF; yr_int = 0.0; sum_prt = TRUE; } /* endif */ } /* endfor */ if (pv) { pmt_int = -rnd (pv * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; pmtsched->period_num = s++; pmtsched->interest = -pmt_int; pmtsched->total_pmt = -pv + pmt_int; pmtsched->balance = 0.0; amortyr->final_pmt = -pv - pmt_int; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->principal_pd = -pv + k * cpmt; amortyr->total_interest_pd = sum_int; } /* endif */ break; case 'p': /* normal amortization schedule interest, principal and balance * per payment period */ amortsched->schedule.first_yr = amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortsched->total_periods = n; hpv = pv; for (s = 1, j = n - 1; j; j--) { /* basic equation for computing interest paid in payment period */ pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec); /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; /* compute principal paid this payment period */ prin = rnd (pmt - pmt_int, prec); /* compute remaining pv and round to nearest cent */ pv = rnd (pv + prin, prec); if (sum_prt) { jj = (j < yr_pmt) ? j + 1 : yr_pmt; amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt)); amortyr->num_periods = jj; sum_prt = FALSE; } /* endif */ if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; pmtsched++; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; pmtsched++; } /* endif */ if (!--yr_pmt) { yr_pmt = PF; amortyr->year = yr++; amortyr->interest_pd = yr_int; if (!fv_case) { amortyr->principal_pd = pv - hpv; } /* endif */ amortyr->yr_end_balance = pv; amortyr->total_interest_pd = sum_int; amortyr->next_yr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr)); amortyr = amortyr->next_yr; hpv = pv; yr_int = 0.0; sum_prt = TRUE; } /* * endif */ } /* * endfor */ /* determine if payment due at beginning or end of period in order * to correctly compute final payment, interest and principal */ if (bep) { /* paying remainder at beginning of period compute final payment */ final_pmt = -pv - fv / (1 + eint); /* then compute interest paid with final final payment */ pmt_int = -rnd ((pv + final_pmt) * eint, prec); /* then compute the principal paid */ prin = final_pmt + pmt_int; } else { /* basic equation for computing interest paid in payment period * for payment at end of period */ pmt_int = -rnd (pv * eint, prec); /* compute principal paid this payment period */ prin = -pv; /* compute the final payment note the final payment may be * computed either of two ways both are equivalent */ final_pmt = prin + pmt_int; } /* * endif */ pv = -fv; /* sum yearly interest paid */ yr_int += pmt_int; /* sum total interest paid */ sum_int += pmt_int; if (sum_prt) { amortyr->payments = pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt)); amortyr->num_periods = 1; } /* endif */ amortyr->final_pmt = final_pmt; if (fv_case) { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->balance = pv; } else { pmtsched->period_num = s++; pmtsched->interest = pmt_int; pmtsched->principal = prin; pmtsched->balance = pv; } /* endif */ if (dabs (yr_int) > 0.0) { amortyr->year = yr++; amortyr->interest_pd = yr_int; amortyr->total_interest_pd = sum_int; if (!bep) { amortyr->principal_pd = -hpv; } /* endif */ } /* endif */ break; case 'x': /* constant payment to principal - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); jj = 0; for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++) { if (j <= PF) { s = jj + j; yr_pmt = j; yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt; } else { s = jj + yr_pmt; yr_fv = rnd (pv + cpmt * s, prec); } /* endif */ prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0)); yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0)); yr_int = rnd (yr_int - prin, prec); jj += yr_pmt; sum_int += yr_int; yrly_sum[sum_prt].year = yr++; yrly_sum[sum_prt].interest = yr_int; yrly_sum[sum_prt].end_balance = yr_fv; } /* endfor */ break; case 'y': /* normal amortization - annual summary */ /* compute number of years to summarize */ j = n / PF; if (yr_pmt < PF) j++; if (n > (j * PF)) j++; amortsched->total_periods = j; amortsched->schedule.summary = yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary)); hpv = pv; for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++) { if (jj <= (int)PF) { yr_fv = fv; yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec); } else { yr_fv = -rnd (_fi_calc_future_value (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec); yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec); } /* * endif */ sum_int += yr_int; yrly_sum[j].year = yr++; yrly_sum[j].interest = yr_int; yrly_sum[j].end_balance = yr_fv; hpv = yr_fv; } /* * endfor */ break; } /* * endswitch */ amortsched->total_interest = sum_int; return amortsched; } /* Amortization_Schedule */ /* function to free dynamically allocated memory used for amortization schedule */ void Amortization_free (amort_sched_ptr amortsched) { amort_sched_yr_ptr amortyr, prst_yr; switch (amortsched->summary) { case 'a': case 'f': case 'o': case 'p': for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr) { if (amortyr->payments) free (amortyr->payments); prst_yr = amortyr->next_yr; free (amortyr); } /* endfor */ break; case 'y': free (amortsched->schedule.summary); break; } /* endswitch */ amortsched->schedule.first_yr = NULL; } /* amort_free */
201  *
202  * PV
203  *
204  * Annuity
205  * Lease (with buy back or residual)*
206  * Loan or Mortgage (with balloon)*
207  *
208  * ****************************************************************************
209  *
210  * First lets discuss interest before discussing the financial
211  * equation. Most financial transactions utilize a nominal interest
212  * rate, NAR, i.e., the interest rate per year. The NAR must be
213  * converted to the interest rate per payment interval and the
214  * compounding accounted for before it can be used in computing an
215  * interest payment. After this conversion process, the interest
216  * used is the effective interest rate, EIR. In converting NAR to
217  * EIR, there are two concepts to discuss first, the Compounding
218  * Frequency and the Payment Frequency and * whether the interest is
219  * coumpounded in discrete intervals or continuously. The
220  * compounding Frequency, CF, is simply the number of times per
221  * year, the monies in the financial transaction are compounded. In
222  * the U.S., monies are usually compounded daily on bank deposits,
223  * and monthly on loans. Somtimes Long term deposits are compounded
224  * quarterly or weekly.
225  *
226  * The Payment Frequency, PF, is simply how often during a year
227  * payments are made in the transaction. Payments are usually
228  * scheduled on a regular basis and can be made at the beginning or
229  * end of the payment period. If made at the beginning of the
230  * payment period, interest must be applied to the payment as well
231  * as any previous money paid or money still owed.
232  *
233  * Normal values for CF and PF are:
234  * 1 == annual
235  * 2 == semi-annual
236  * 3 == tri-annual
237  * 4 == quaterly
238  * 6 == bi-monthly
239  * 12 == monthly
240  * 24 == semi-monthly
241  * 26 == bi-weekly
242  * 52 == weekly
243  * 360 == daily
244  * 365 == daily
245  *
246  * a) the Compounding Frequency per year, CF, need not be identical
247  * to the Payment Frequency per year, PF, and/or,
248  *
249  * b) Interest may be compounded in either discrete intervals or continuously
250  * compounded.
251  *
252  * c) Also, payments may be made at the beginning of the payment
253  * period or at the end of the payment period.
254  *
255  * CF and PF are defaulted to 1. The default is for discrete interest
256  * intervals and payments are defaulted to the end of the payment
257  * period.
258  *
259  * When a solution for n, PV, PMT or FV is required, the nominal interest
260  * rate, i, must first be converted to the effective interest rate per payment
261  * period. This rate, ieff, is then used to compute the selected variable. To
262  * convert i to ieff, the following expressions are used:
263  *
264  * Discrete interest periods:
265  *
266  * 19) ieff = (1 + i/CF)^(CF/PF) - 1
267  *
268  * Continuous Interest
269  *
270  * 20) ieff = e^(i/PF) - 1 = exp(i/PF) - 1
271  *
272  * When interest is computed, the computation produces the effective interest
273  * rate, ieff. This value must then be converted to the nominal interest rate.
274  * Function _I below returns the nominal interest rate NOT the effective
275  * interest rate. ieff is converted to i using the following expressions:
276  *
277  * Discrete Case:
278  *
279  * i = CF*[(1+ieff)^(PF/CF) - 1]
280  *
281  * Continuous Case:
282  *
283  * i = ln[(1+ieff)^PF]
284  *
285  * ****************************************************************************
286  *
287  * NOTE: in the equations below for the financial transaction, all
288  * interest rates are the effective interest rate, ieff. The symbol
289  * will be shortned to just 'i'.
290  *
291  * ****************************************************************************
292  *
293  * The basic financial equation used is:
294  *
295  * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1+i)^n - 1]/i + FV = 0
296  * Where: X = 0 for end of period payments, and
297  * X = 1 for beginning of period payments
298  *
299  * ****************************************************************************
300  *
301  * NOTE: this equation is derived in the following manner:
302  *
303  * Start with the basic equation to find the balance or Present
304  * Value, PV[1], after one payment period. Note PV[1] is the Present
305  * value after on payment and PV[0] is the initial Present
306  * Value. PV[0] will be shortened to just PV.
307  *
308  * The interest due at the end of the first payment period is:
309  *
310  * ID[1] = (PV + X * PMT) * i
311  * where: X = 0 for end of period payments, and
312  * X = 1 for beginning of period payments.
313  *
314  * Thus:
315  * PV[1] = PV + (PMT + ID[1])
316  * = PV + (PMT + (PV + X * PMT) * i)
317  * = PV * (1 + i) + PMT * (1 + Xi)
318  *
319  * This equation works for all of the money diagrams shown
320  * above. The Present Value, money received or paid, is modified by
321  * a payment made at the beginning of a payment period and
322  * multiplied by the effective interest rate to compute the interest
323  * due during the payment period. The interest due is then added to
324  * the payment to obtain the amount to be added to the Present Value
325  * to compute the new Present Value.
326  *
327  * For diagram 1): PV < 0, PMT == 0, PV[1] < 0
328  * For diagram 2): PV == 0, PMT < 0, PV[1] < 0
329  * For Diagram 3): PV > 0, PMT < 0, PV[1] >= 0 or PV[1] <= 0
330  * For Diagram 4): PV < 0, PMT > 0, PV[1] <= 0 or PV[1] >= 0
331  *
332  * X may be 0 or 1 for any diagram.
333  *
334  * For the standard loan, PV is the money borrowed, PMT is the
335  * periodic payment to repay the loan and i is the effective
336  * interest rate agreed upon.
337  *
338  * To calculate the Present Value after the second payment period,
339  * the above calculation is applied iteratively to PV_1:
340  *
341  * PV[2] = PV[1] + (PMT + (PV[1] + X * PMT) * i)
342  * = PV[1] * (1 + i) + PMT * (1 + iX)
343  * = (PV * (1 + i) + PMT * (1 + iX)) * (1 + i) + PMT * (1 + iX)
344  * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i)
345  * + PMT * (1 + iX)
346  *
347  * Similarly:
348  *
349  * PV[3] = PV[2] + (PMT + (PV[2] + X * PMT) * i)
350  * = PV[2] * (1 + i) + PMT * (1 + iX)
351  * = PV * (1 + i)^2 + PMT * (1 + iX) * (1 + i)
352  * + PMT * (1+ iX)) * ( 1 + i)
353  * + PMT * (1+ iX)
354  * = PV * (1 + i)^3 + PMT * (1 + iX) * (1 + i)^2
355  * + PMT * (1 + iX) * (1 + i)^2
356  * + PMT * (1 + iX) * (1 + i)
357  * + PMT * (1 + iX)
358  *
359  * And for the n'th payment:
360  *
361  * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i)
362  * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * (1 + i)^(n-1)
363  * + PMT * (1 + iX) * (1 + i)^(n-2) +
364  * .
365  * .
366  * .
367  * + PMT * (1 + iX) * (1 + i)
368  * + PMT * (1 + iX)
369  * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ...
370  * + (1 + i) + 1]
371  *
372  * ****************************************************************************
373  *
374  * The sum of the finite series:
375  *
376  * 1 + k + (k^2) + (k^3) + ... + (k^n) = (1-k^(n+1))/(1-k)
377  *
378  * as can be seen by the following. Let S(n) be the series sum. Then
379  *
380  * S(n) - k * S(n) = 1 - k^(n+1)
381  *
382  * and solving for S(n):
383  *
384  * S(n) = [1-k^(n+1)]/[1-k] = 1 + k + (k^2) + (k^3) + ... + (k^n)
385  *
386  * ****************************************************************************
387  *
388  * PV[n] = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^(n-1) + ...
389  * + (1 + i) + 1]
390  * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[1 - (1 + i)]
391  * = PV * (1 + i)^n + PMT * (1 + iX) * [1 - (1 + i)^n]/[-i]
392  * = PV * (1 + i)^n + PMT * (1 + iX) * [(1 + i)^n - 1]/i
393  *
394  * The formaula for PV[n] can be proven using mathematical induction.
395  *
396  * or:
397  *
398  * PV * (1 + i)^n + PMT * [(1 + i)^n - 1]/i - PV[n] = 0
399  *
400  * If after n payments, the remaining balance is repaid as a lump
401  * sum, the lump sum is known as the Future Value, FV[n]. Since
402  * FV[n] is negative if paid and positive if received, FV[n] is the
403  * negative of PV[n]. Since n is assumed to be the last payment,
404  * FV[n] will be shortened to simply FV.
405  *
406  * Setting: FV = -PV[N]
407  *
408  * 1) PV*(1 + i)^n + PMT*(1 + iX)*[(1 + i)^n - 1]/i + FV = 0
409  *
410  * Up to this point, we have said nothing about the value of
411  * PMT. PMT can be any value mutually agreed upon by the lender and
412  * the borrower. From the equation for PV[1]:
413  *
414  * PV[1] = PV + (PMT + (PV + X * PMT) * i),
415  *
416  * Several things can be said about PMT.
417  *
418  * 1. If PMT = PV * i, and X = 0 (end of period payments):
419  *
420  * The payment is exactly equal to the interest due and PV[1] =
421  * PV. In this case, the borrower must make larger future
422  * payments to reduce the balance due, or make a single payment,
423  * after some agreed upon number of payments, with PMT = PV to
424  * completely pay off the loan. This is an interest only payment
425  * with a balloon payment at the end.
426  *
427  * 2. If PMT < PV * i, and X = 0
428  *
429  * The payment is insufficient to cover even the interest charged
430  * and the balance due grows
431  *
432  * 3. If PMT > PV * i, and X = 0
433  *
434  * The payment is sufficient to cover the interest charged with a
435  * residual amount to be applied to reduce the balance due. The
436  * larger the residual amount, the faster the loan is repaid. For
437  * most mortgages or other loans made today, the lender and
438  * borrower agree upon a certain number of repayment periods and
439  * the interest to be charged per payment period. The interest
440  * may be multiplied by 12 and stated as an annual interest
441  * rate. Then the lender and borrower want to compute a periodic
442  * payment, PMT, which will reduce the balance due to zero after
443  * the agreed upon number of payment have been made. If N is the
444  * agreed upon number of periodic payments, then we want to use:
445  *
446  * PV * (1 + i)^N + PMT*(1 +iX)*[(1 + i)^N - 1]/i + FV = 0
447  *
448  * with FV = 0 to compute PMT:
449  *
450  * PMT = -[PV * i * (1 + i)^(N - X)]/[(1 + i)^N - 1]
451  *
452  * The value of PMT computed will reduce the balance due to zero
453  * after N periodic payments.
454  *
455  * ****************************************************************************
456  *
457  *
458  * With a simple alegebraic re-arrangement, The financial Equation becomes:
459  *
460  * 2) [PV + PMT*(1 + iX)/i][(1 + i)^n - 1] + PV + FV = 0
461  *
462  * or
463  *
464  * 3) (PV + C)*A + PV + FV = 0
465  *
466  * where:
467  * 4) A = (1 + i)^n - 1
468  *
469  * 5) B = (1 + iX)/i
470  *
471  * 6) C = PMT*B
472  *
473  * The form of equation 3) simplifies the calculation procedure for all five
474  * variables, which are readily solved as follows:
475  *
476  * 7) n = ln[(C - FV)/(C + PV)]/ln((1 + i)
477  *
478  * 8) PV = -[FV + A*C]/(A + 1)
479  *
480  * 9) PMT = -[FV + PV*(A + 1)]/[A*B]
481  *
482  * 10) FV = -[PV + A*(PV + C)]
483  *
484  * Equations 4), 5) and 6) are computed by functions:
485  *
486  * _A
487  * _B
488  * _C
489  *
490  * respectively. Equations 7), 8), 9) and 10) are computed by functions:
491  *
492  * _N
493  * _PV
494  * _PMT
495  * _FV
496  *
497  * respectively.
498  *
499  * The solution for interest is broken into two cases:
500  *
501  * PMT == 0
502  * i = [FV/PV]^(1/n) - 1
503  *
504  * PMT != 0
505  *
506  * Since equation 3) cannot be solved explicitly for i in this
507  * case, an iterative technique must be employed. Newton's
508  * method, using exact expressions for the function of i and its
509  * derivative, are employed. The expressions are:
510  *
511  * 12) i[k+1] = i[k] - f(i[k])/f'(i[k])
512  * where: i[k+1] == (k+1)st iteration of i
513  * i[k] == kth iteration of i
514  * and:
515  *
516  * 13) f(i) = A*(PV+C) + PV + FV
517  *
518  * 14) f'(i) = n*D*(PV+C) - (A*C)/i
519  *
520  * 15) D = (1 + i)^(n-1) = (A+1)/(1+i)
521  *
522  * To start the iterative solution for i, an initial guess must be made
523  * for the value of i. The closer this guess is to the actual value,
524  * the fewer iterations will have to be made, and the greater the
525  * probability that the required solution will be obtained. The initial
526  * guess for i is obtained as follows:
527  *
528  * if PMT*FV >= 0, then PV case
529  * if PMT*FV < 0, then FV case
530  *
531  * PV case:
532  * | n*PMT + PV + FV |
533  * 16) i[0] = | ----------------|
534  * | n*PV |
535  *
536  * = abs[(n*PMT + PV + FV)/(n*PV)]
537  *
538  * FV case:
539  * a) PV != 0
540  *
541  * | FV - n*PMT |
542  * 17) i[0] = |---------------------------|
543  * | 3*[PMT*(n-1)^2 + PV - FV] |
544  *
545  * = abs[(FV-n*PMT)/(3*(PMT*(n-1)^2+PV-FV))]
546  * b) PV == 0
547  *
548  * | FV + n*PMT |
549  * 18) i[0] = |---------------------------|
550  * | 3*[PMT*(n-1)^2 + PV - FV] |
551  *
552  * = abs[(FV+n*PMT)/(3*(PMT*(n-1)^2+PV-FV))]
553  *
554  * ****************************************************************************
555  * Constant payment to principal loan
556  *
557  * In this loan, each total payment is different, with each
558  * succeeding payment less than the preceeding payment. Each payment
559  * is the total of the constant ammount to the principal plus the
560  * interest for the period. The constant payment to the principal is
561  * computed as:
562  *
563  * C = -PV / N
564  *
565  * Where PV is the loan amount to be repaid in N payments
566  * (periods). Note that the constant payment to principal could be
567  * any value agreed to by the two parties involved.
568  *
569  * Thus the principal after the first payment is:
570  * PV[1] = PV[0] + C = PV + C
571  * after the second payment, the principal is:
572  * PV[2] = PV[1] + C = PV[0] + 2C
573  * In general, the remaining principal after n payments is:
574  * PV[n] = PV[0] + nC = PV + nC
575  *
576  * If the effective interest per payment period is i, then the
577  * interest for the first payment is:
578  *
579  * I[1] = -i*PV[0] = -i*PV
580  * and for the second:
581  * I[2] = -i * PV[1]
582  * and in general, for the n'th payment the interest is:
583  * I[n] = -i * PV[n-1]
584  * = -i * (PV + (n-1)C)
585  * The total payment for any period, n, is:
586  * P[n] = C + I[n]
587  * = C + i * (PV + (n-1)C)
588  * = C(1 + i) - i * (PV + nC)
589  * The total interest paid to period n is:
590  * T[n] = I[1] + I[2] + I[3] + ... + I[n]
591  * T[n] = sum(j = 1 to n: I[j])
592  * T[n] = sum(j = 1 to n: -i * (PV + (j-1)C))
593  * T[n] = sum(j=1 to n: -i*PV) + sum(j=1 to n: iC) + sum(j=1 to n: -iCj)
594  * T[n] = -i*n*PV + i*n*C - i*C*sum(j=1 to n:j)
595  * sum(j=1 to n:j) = n(n+1)/2
596  * T[n] = -i*n*(PV + C) - i*C*n(n+1)/2
597  * T[n] = -i*n*(PV + (C*(n - 1)/2))
598  *
599  * Note: substituing for C = -PV/N, in the equations for PV[n], I[n],
600  * P[n], and T[n] would give the following equations:
601  *
602  * PV[n] = PV*(1 - n/N)
603  * I[n] = -i*PV*(1 + N - n)/N
604  * P[n] = -i*PV*(2 + N - n)/N
605  * T[n] = -i*n*PV*(2*N - n + 1)/(2*N)
606  *
607  * Using these equations for the calculations would eliminate the
608  * dependence on C, but only if C is always defined as above and
609  * would eliminate the possibility of another value for C. If the
610  * value of C was less than -PV/N then a balloon payment would be
611  * due at the final payment and this is a possible alternative for
612  * some people.
613  *
614  * ****************************************************************************
615  *
616  * Amortization Schedules.
617  *
618  * Financial Transactions have an effective Date, ED, and an Initial Payment
619  * Date, IP. ED may or may not be the same as IP, but IP is always the same
620  * or later than ED. Most financial transaction calculators assume that
621  * IP is equal to ED for beginning of period payments or at the end of the
622  * first payment period for end of period payments.
623  *
624  * This is not always true. IP may be delayed for financial reasons
625  * such as cash flow or accounting calender. The subsequent payments
626  * then follow the agreed upon periodicity. Since money has a time
627  * value, the "delayed" IP must be accounted for. Computing an
628  * "Effective PV", pve, is one means of handling a delayed IP.
629  *
630  * EDj == the Julian Day Number of ED, and
631  * IPj == the Julian Day Number of IP in the following.
632  *
633  * pve is be computed as:
634  *
635  * pve = pv*(1 + i)^(s*PF/d*CF)
636  *
637  * Where: d = length of the payment period in days, and
638  * s = IPj - EDj - d*X
639  *
640  * Computing an amortization Schedule for a given financial transaction is
641  * simply applying the basic equation iteratively for each payment period:
642  *
643  * PV[n] = PV[n-1] + (PMT + (PV[n-1] + X * PMT) * i)
644  *
645  * At the end of each iteration, PV[n] is rounded to the nearest cent. For
646  * each payment period, the interest due may be computed separately as:
647  *
648  * ID[n] = (PMT + (PV[n-1] + X * PMT) * i)
649  *
650  * and rounded to the nearest cent. PV[n] then becomes:
651  *
652  * PV[n] = PV[n-1] + PMT + ID[n]
653  *
654  * For those cases where a yearly summary only is desired, it is not
655  * necessary to compute each transaction for each payment period,
656  * rather the PV may be be computed for the beginning of each year,
657  * PV[yr], and the FV computed for the end of the year, FV[yr]. The
658  * interest paid during the year is the computed as:
659  *
660  * ID[yr] = (NP * PMT) + PV[yr] + FV[yr]
661  *
662  * Since the final payment may not be equal to the periodic payment,
663  * the final payment must be computed separately as follows. Two
664  * derivations are given below for the final payment equation. Both
665  * derivations are given below since one or the other may be clearer
666  * to some readers. Both derivations are essentially the same, they
667  * just have different starting points. The first is the fastest.
668  *
669  * 1) final_pmt == final payment @ payment n == int(n)
670  * from above the basic financial equation:
671  * PV[n] = PV[n-1]*(1 + i) + final_pmt * (1 + iX),
672  * i == effective interest rate
673  *
674  * solving for final_pmt, we have:
675  *
676  * final_pmt * (1 + iX) = PV[n] - PV[n-1]*(1 + i)
677  * = FV[n-1]*(1 + i) - FV[n]
678  * final_pmt = FV[n-1]*(1+i)/(1 + iX) - FV[n]/(1 + iX)
679  *
680  * final_pmt = FV[n-1]*(1 + i) - FV[n],
681  * for X == 0, end of period payments
682  *
683  * = FV[n-1] - FV[n]/(1 + i),
684  * for X == 1, beginning of period payments
685  *
686  * 2) final_pmt == final payment @ payment n == int(n)
687  * i[n] == interest due @ payment n
688  * i[n] = (PV[n-1] + X * final_pmt) * i, i == effective interest rate
689  * = (X * final_pmt - FV[n]) * i
690  *
691  * Now the final payment is the sum of the interest due, plus
692  * the present value at the next to last payment plus any
693  * residual future value after the last payment:
694  *
695  * final_pmt = -i[n] - PV[n-1] - FV[n]
696  * = FV[n-1] - i[n] - FV[n]
697  * = FV[n-1] - (X *final_pmt - FV[n-1])*i - FV[n]
698  * = FV[n-1]*(1 + i) - X*final_pmt*i - FV[n]
699  *
700  * solving for final_pmt:
701  * final_pmt*(1 + iX) = FV[n-1]*(1 + i) - FV[n]
702  * final_pmt = FV[n-1]*(1 + i)/(1 + iX) - FV[n]/(1 + iX)
703  *
704  * final_pmt = FV[n-1]*(1 + i) - FV[n],
705  * for X == 0, end of period payments
706  *
707  * = FV[n-1] - FV[n]/(1 + i),
708  * for X == 1, beginning of period payments
709  *
710  *============================================================================
711  *
712  * The amortization schedule is computed for four different situations:
713  *
714  * 1) The original financial data is used. This ignores any possible
715  * agjustment to the Present value due to any delay in the initial
716  * payment. This is quite common in mortgages where end of period
717  * payments are used and the first payment is scheduled for the end
718  * of the first whole period, i.e., any partial payment period from
719  * ED to the beginning of the next payment period is ignored.
720  *
721  * 2) The original periodic payment is used, the Present Value is
722  * adjusted for the delayed Initial Payment. The total number of
723  * payments remains the same. The final payment is adjusted to bring
724  * the balance into agreement with the agreed upon final Future
725  * Value.
726  *
727  * 3) A new periodic payment is computed based upon the adjusted
728  * Present Value, the agreed originally upon number of total
729  * payments and the agreed upon Future Value. The new periodic
730  * payments are computed to minimize the final payment in accordance
731  * with the Future Value after the last payment.
732  *
733  * 4) The original periodic payment is retained and a new number of
734  * total payments is computed based upon the adjusted Present Value
735  * and the agreed upon Future Value.
736  *
737  * The amortization schedule may be computed and displayed in three manners:
738  *
739  * 1. The payment *, interest paid, principal paid and remaining PV
740  * for each payment period are computed and displayed. At the end of
741  * each year a summary is computed and displayed and the total
742  * interest paid is diplayed at the end.
743  *
744  * 2. A summary is computed and displayed for each year. The
745  * interest paid during the year is computed and displayed as well
746  * as the remaining balance at years end. The total interest paid
747  * is diplayed at the end.
748  *
749  * 3. An amortization schedule is computed for a common method of
750  * advanced payment of principal is computed and displayed. In this
751  * amortization, the principal for the next payment is computed and
752  * added into the current payment. This method will cut the number
753  * of total payments in half and will cut the interest paid almost
754  * in half. For mortgages, this method of prepayment has the
755  * advantage of keeping the total payments small during the initial
756  * payment periods The payments grow until the last payment period
757  * when presumably the borrower can afford larger payments.
758  *
759  * ===========================================================================
760  * NOTE: For Payment Frequencies, PF, semi-monthly or less, i.e., PF
761  * == 12 or PF == 24, a 360 day calender year and 30 day month are
762  * used. For Payment Frequencies, PF, greater than semi-monthly, PF
763  * > 24, the actual number of days per year and per payment period
764  * are used. The actual values are computed using the built-in
765  * 'julian_day_number' function
766  *
767  * ****************************************************************************
768  *
769  * Note: in the following examples, the user input is preceeded by the
770  * prompt "<>". The result of evaluating the input expression is then
771  * displayed. I have taken the liberty of including comments in the
772  * example input/output sessions by preceeding with ' *'. Thus, for
773  * the line: <>n=5 *set number of periods the comment that setting the
774  * number of periods is not really input and the true input is only:
775  * <>n=5
776  *
777  * Example 1: Simple Interest
778  * Find annual simple interest rate (%) for an $800 loan to be repayed at the
779  * end of one year with a single payment of $896.
780  * <>d
781  * <>CF=PF=1
782  * 1.00
783  * <>n=1
784  * 1.00
785  * <>pv=-800
786  * -800.00
787  * <>fv=896
788  * 896.00
789  * <>I
790  * 12.00
791  *
792  * Example 2: Compound Interest
793  * Find the future value of $800 after one year at a nominal rate of 12%
794  * compounded monthly. No payments are specified, so the payment frequency is
795  * set equal to the compounding frequency at the default values.
796  * <>d
797  * <>n=12
798  * 12.00
799  * <>i=12
800  * 12.00
801  * <>pv=-800
802  * -800.00
803  * <>FV
804  * 901.46
805  *
806  * Example 3: Periodic Payment:
807  * Find the monthly end-of-period payment required to fully amortize the loan
808  * in Example 2. A fully amortized loan has a future value of zero.
809  * <>fv=0
810  * 0.00
811  * <>PMT
812  * 71.08
813  *
814  * Example 4: Conventional Mortgage
815  *
816  * Find the number of monthly payments necessary to fully amortize a
817  * loan of $100,000 at a nominal rate of 13.25% compounded monthly, if
818  * monthly end-of-period payments of $1125.75 are made.
819  *
820  * <>d
821  * <>i=13.25
822  * 13.25
823  * <>pv=100000
824  * 100,000.00
825  * <>pmt=-1125.75
826  * -1,125.75
827  * <>_N(i,pv,pmt,fv,CF,PF,disc,bep)
828  * 360.10
829  * <>N
830  * 360
831  *
832  * Example 5: Final Payment
833  * Using the data in example 4, find the amount of the final payment if n is
834  * changed to 360. The final payment will be equal to the regular payment plus
835  * any balance, future value, remaining at the end of period number 360.
836  * <>n=360
837  * 360.00
838  * <>FV
839  * -108.87
840  * <>pmt+fv
841  * -1,234.62
842  *
843  * Using the data from this loan, compute the amortization schedule
844  * when the Effective date of the loan is June 6, 1996 and the
845  * initial payment is made on August 1, 1996. Ignore any change in
846  * the PV due to the delayed initial payment caused by the partial
847  * payment period from June 6 to July 1.
848  *
849  * <>ED = 06/06/1996
850  * Effective Date set: 06/06/1996 ( 2450241 )
851  * <>IP = 08/01/1996
852  * Initial Payment Date set: 08/01/1996 ( 2450297 )
853  * <>a
854  * Effective Date: 06/06/96
855  * Initial Payment Date: 08/01/96
856  * The amortization options are:
857  * The Old Present Value (pv) was: 100,000.00
858  * The Old Periodic Payment (pmt) was: -1,125.75
859  * The Old Future Value (fv) was: -108.87
860  * 1: Amortize with Original Transaction Values
861  * and balloon final payment: -1,125.75
862  *
863  * The New Present Value (pve) is: 100,919.30
864  * The New Periodic Payment (pmt) is: -1,136.10
865  * 2: Amortize with Original Periodic Payment
866  * and balloon final payment: -49,023.68
867  * 3: Amortize with New Periodic Payment
868  * and balloon final payment: -1,132.57
869  * 4: Amortize with Original Periodic Payment,
870  * new number of total payments (n): 417
871  * and final payment: -2,090.27
872  *
873  * Enter choice 1, 2, 3 or 4: <>
874  *
875  * Press '1'
876  * Amortization Schedule:
877  * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization
878  * Enter choice y, p or a:
879  * <>
880  *
881  * Press 'y'
882  * Enter Filename for Amortization Schedule.
883  * (null string uses Standard Output):
884  * Press enter to display output on screen
885  *
886  * Amortization Table
887  * Effective Date: Thu Jun 06 00:00:00 1996
888  * Initial Payment Date: Thu Aug 01 00:00:00 1996
889  * Compounding Frequency per year: 12
890  * Payment Frequency per year: 12
891  * Compounding: Discrete
892  * Payments: End of Period
893  * Payments (359): -1,125.75
894  * Final payment: -1,125.75
895  * Nominal Annual Interest Rate: 13.25
896  * Effective Interest Rate Per Payment Period: 0.0110417
897  * Present Value: 100,000.00
898  * Year Interest Ending Balance
899  * 1996 -5,518.42 -99,889.67
900  * 1997 -13,218.14 -99,598.81
901  * 1998 -13,177.17 -99,266.98
902  * 1999 -13,130.43 -98,888.41
903  * 2000 -13,077.11 -98,456.52
904  * 2001 -13,016.28 -97,963.80
905  * 2002 -12,946.88 -97,401.68
906  * 2003 -12,867.70 -96,760.38
907  * 2004 -12,777.38 -96,028.76
908  * 2005 -12,674.33 -95,194.09
909  * 2006 -12,556.76 -94,241.85
910  * 2007 -12,422.64 -93,155.49
911  * 2008 -12,269.63 -91,916.12
912  * 2009 -12,095.06 -90,502.18
913  * 2010 -11,895.91 -88,889.09
914  * 2011 -11,668.70 -87,048.79
915  * 2012 -11,409.50 -84,949.29
916  * 2013 -11,113.78 -82,554.07
917  * 2014 -10,776.41 -79,821.48
918  * 2015 -10,391.53 -76,704.01
919  * 2016 -9,952.43 -73,147.44
920  * 2017 -9,451.49 -69,089.93
921  * 2018 -8,879.99 -64,460.92
922  * 2019 -8,227.99 -59,179.91
923  * 2020 -7,484.16 -53,155.07
924  * 2021 -6,635.56 -46,281.63
925  * 2022 -5,667.43 -38,440.06
926  * 2023 -4,562.94 -29,494.00
927  * 2024 -3,302.89 -19,287.89
928  * 2025 -1,865.36 -7,644.25
929  * 2026 -236.00 -108.87
930  *
931  * Total Interest: -305,270.00
932  *
933  * NOTE: The amortization table leaves the FV as it was when the amortization
934  * function was entered. Thus, a balance of 108.87 is due at the end of the
935  * table. To completely pay the loan, set fv to 0.0:
936  * <>fv=0
937  * 0.0
938  * <>a
939  * Effective Date: 06/06/96
940  * Initial Payment Date: 08/01/96
941  * The amortization options are:
942  * The Old Present Value (pv) was: 100,000.00
943  * The Old Periodic Payment (pmt) was: -1,125.75
944  * The Old Future Value (fv) was: 0.00
945  * 1: Amortize with Original Transaction Values
946  * and balloon final payment: -1,234.62
947  *
948  * The New Present Value (pve) is: 100,919.30
949  * The New Periodic Payment (pmt) is: -1,136.12
950  * 2: Amortize with Original Periodic Payment
951  * and balloon final payment: -49,132.55
952  * 3: Amortize with New Periodic Payment
953  * and balloon final payment: -1,148.90
954  * 4: Amortize with Original Periodic Payment,
955  * new number of total payments (n): 417
956  * and final payment: -2,199.14
957  *
958  * Enter choice 1, 2, 3 or 4: <>
959  * Press '1'
960  * Amortization Schedule:
961  * Yearly, y, per Payment, p, or Advanced Payment, a, Amortization
962  * Enter choice y, p or a:
963  * <>
964  * Press 'y'
965  * Enter Filename for Amortization Schedule.
966  * (null string uses Standard Output):
967  * Press enter to display output on screen
968  *
969  * Amortization Table
970  * Effective Date: Thu Jun 06 00:00:00 1996
971  * Initial Payment Date: Thu Aug 01 00:00:00 1996
972  * Compounding Frequency per year: 12
973  * Payment Frequency per year: 12
974  * Compounding: Discrete
975  * Payments: End of Period
976  * Payments (359): -1,125.75
977  * Final payment: -1,234.62
978  * Nominal Annual Interest Rate: 13.25
979  * Effective Interest Rate Per Payment Period: 0.0110417
980  * Present Value: 100,000.00
981  * Year Interest Ending Balance
982  * 1996 -5,518.42 -99,889.67
983  * 1997 -13,218.14 -99,598.81
984  * 1998 -13,177.17 -99,266.98
985  * 1999 -13,130.43 -98,888.41
986  * 2000 -13,077.11 -98,456.52
987  * 2001 -13,016.28 -97,963.80
988  * 2002 -12,946.88 -97,401.68
989  * 2003 -12,867.70 -96,760.38
990  * 2004 -12,777.38 -96,028.76
991  * 2005 -12,674.33 -95,194.09
992  * 2006 -12,556.76 -94,241.85
993  * 2007 -12,422.64 -93,155.49
994  * 2008 -12,269.63 -91,916.12
995  * 2009 -12,095.06 -90,502.18
996  * 2010 -11,895.91 -88,889.09
997  * 2011 -11,668.70 -87,048.79
998  * 2012 -11,409.50 -84,949.29
999  * 2013 -11,113.78 -82,554.07
1000  * 2014 -10,776.41 -79,821.48
1001  * 2015 -10,391.53 -76,704.01
1002  * 2016 -9,952.43 -73,147.44
1003  * 2017 -9,451.49 -69,089.93
1004  * 2018 -8,879.99 -64,460.92
1005  * 2019 -8,227.99 -59,179.91
1006  * 2020 -7,484.16 -53,155.07
1007  * 2021 -6,635.56 -46,281.63
1008  * 2022 -5,667.43 -38,440.06
1009  * 2023 -4,562.94 -29,494.00
1010  * 2024 -3,302.89 -19,287.89
1011  * 2025 -1,865.36 -7,644.25
1012  * 2026 -344.87 0.00
1013  *
1014  * Total Interest: -305,378.87
1015  *
1016  * Example 6: Balloon Payment
1017  * On long term loans, small changes in the periodic payments can generate
1018  * large changes in the future value. If the monthly payment in example 5 is
1019  * rounded down to $1125, how much addtional (balloon) payment will be due
1020  * with the final regular payment.
1021  * <>pmt=-1125
1022  * -1,125
1023  * <>FV
1024  * -3,579.99
1025  *
1026  * Example 7: Canadian Mortgage
1027  * Find the monthly end-of-period payment necessary to fully amortize a 25 year
1028  * $85,000 loan at 11% compounded semi-annually.
1029  * <>d
1030  * <>CF=2
1031  * 2.00
1032  * <>n=300
1033  * 300.00
1034  * <>i=11
1035  * 11.00
1036  * <>pv=85000
1037  * 85,000.00
1038  * <>PMT
1039  * -818.15
1040  *
1041  * Example 8: European Mortgage
1042  * The "effective annual rate (EAR)" is used in some countries (especially
1043  * in Europe) in lieu of the nominal rate commonly used in the United States
1044  * and Canada. For a 30 year $90,000 mortgage at 14% (EAR), compute the monthly
1045  * end-of-period payments. When using an EAR, the compounding frequency is
1046  * set to 1.
1047  * <>d
1048  * <>CF=1
1049  * 1.00
1050  * <>n=30*12
1051  * 360.00
1052  * <>i=14
1053  * 14.00
1054  * <>pv=90000
1055  * 90,000.00
1056  * <>PMT
1057  * -1,007.88
1058  *
1059  * Example 9: Bi-weekly Savings
1060  * Compute the future value, fv, of bi-weekly savings of $100 for 3 years at a
1061  * nominal annual rate of 5.5% compounded daily. (Set payment to
1062  * beginning-of-period, bep = TRUE)
1063  * <>d
1064  * <>bep=TRUE
1065  * 1.00
1066  * <>CF=365
1067  * 365.00
1068  * <>PF=26
1069  * 26.00
1070  * <>n=3*26
1071  * 78.00
1072  * <>i=5.5
1073  * 5.50
1074  * <>pmt=-100
1075  * -100.00
1076  * <>FV
1077  * 8,489.32
1078  *
1079  * Example 10: Present Value - Annuity Due
1080  * What is the present value of $500 to be received at the beginning of each
1081  * quarter over a 10 year period if money is being discounted at 10% nominal
1082  * annual rate compounded monthly?
1083  * <>d
1084  * <>bep=TRUE
1085  * 1.00
1086  * <>PF=4
1087  * 4.00
1088  * <>n=4*10
1089  * 40.00
1090  * <>i=10
1091  * 10.00
1092  * <>pmt=500
1093  * 500.00
1094  * <>PV
1095  * -12,822.64
1096  *
1097  * Example 11: Effective Rate - 365/360 Basis
1098  * Compute the effective annual rate (%APR) for a nominal annual rate of 12%
1099  * compounded on a 365/360 basis used by some Savings & Loan Associations.
1100  * <>d
1101  * <>n=365
1102  * 365.00
1103  * <>CF=365
1104  * 365.00
1105  * <>PF=360
1106  * 360.00
1107  * <>i=12
1108  * 12.00
1109  * <>pv=-100
1110  * -100.00
1111  * <>FV
1112  * 112.94
1113  * <>fv+pv
1114  * 12.94
1115  *
1116  * Example 12: Mortgage with "Points"
1117  *
1118  * What is the true APR of a 30 year, $75,000 loan at a nominal rate
1119  * of 13.25% compounded monthly, with monthly end-of-period payments,
1120  * if 3 "points" are charged? The pv must be reduced by the dollar
1121  * value of the points and/or any lenders fees to establish an
1122  * effective pv. Because payments remain the same, the true APR will
1123  * be higher than the nominal rate. Note, first compute the payments
1124  * on the pv of the loan amount.
1125  *
1126  * <>d
1127  * <>CF=PF=1
1128  * 1.00
1129  * <>n=30*12
1130  * 360.00
1131  * <>i=13.25/12
1132  * 1.10
1133  * <>pv=75000
1134  * 75,000.00
1135  * <>PMT
1136  * -844.33
1137  * <>pv -= pv*.03
1138  * 72,750.00
1139  * <>CF=PF=12
1140  * 12.00
1141  * <>I
1142  * 13.69
1143  *
1144  * Example 13: Equivalent Payments
1145  * Find the equivalent monthly payment required to amortize a 20 year $40,000
1146  * loan at 10.5% nominal annual rate compounded monthly, with 10 annual
1147  * payments of $5029.71 remaining. Compute the pv of the remaining annual
1148  * payments, then change n, the number of periods, and the payment frequency,
1149  * PF, to a monthly basis and compute the equivalent monthly pmt.
1150  * <>d
1151  * <>PF=1
1152  * 1.00
1153  * <>n=10
1154  * 10.00
1155  * <>i=10.5
1156  * 10.50
1157  * <>pmt=-5029.71
1158  * -5,029.71
1159  * <>PV
1160  * 29,595.88
1161  * <>PF=12
1162  * 12.00
1163  * <>n=120
1164  * 120.00
1165  * <>PMT
1166  * -399.35
1167  *
1168  * Example 14: Perpetuity - Continuous Compounding
1169  * If you can purchase a single payment annuity with an initial investment of
1170  * $60,000 that will be invested at 15% nominal annual rate compounded
1171  * continuously, what is the maximum monthly return you can receive without
1172  * reducing the $60,000 principal? If the principal is not disturbed, the
1173  * payments can go on indefinitely (a perpetuity). Note that the term,n, of
1174  * a perpetuity is immaterial. It can be any non-zero value.
1175  * <>d
1176  * <>disc=FALSE
1177  * 0.00
1178  * <>n=12
1179  * 12.00
1180  * <>CF=1
1181  * 1.00
1182  * <>i=15
1183  * 15.00
1184  * <>fv=60000
1185  * 60,000.00
1186  * <>pv=-60000
1187  * -60,000.00
1188  * <>PMT
1189  * 754.71
1190  *
1191  * references:
1192  * 1. PPC ROM User's Manual
1193  * pages 148 - 164
1194  *
1195  */
1196 
1197 #include <time.h>
1198 #include <stdio.h>
1199 #include <glib.h>
1200 #include <math.h>
1201 #if defined(G_OS_WIN32) && !defined(_MSC_VER)
1202 #include <pow.h>
1203 #endif
1204 #include <string.h>
1205 #include <stdlib.h>
1206 
1207 #define FIN_STATICS
1208 #include "finvar.h"
1209 #include "finproto.h"
1210 #include "fin_static_proto.h"
1211 
1212 /* return 'x' rounded to 'places' past decimal if 'places' < 0, return
1213  * 'x' */
1214 static double
1215 rnd (double x, unsigned places)
1216 {
1217  double r;
1218  char buf[50]; /* make buffer large enough */
1219 
1220  sprintf (buf, "%.*f", (int) places, x);
1221  r = strtod(buf, NULL);
1222 
1223  return r;
1224 } /* rnd */
1225 
1226 /* return absolute value of 'x' this function is provided by a macro
1227  * in C */
1228 static double
1229 dabs (double x)
1230 {
1231  return (x >= 0.0) ? x : -x;
1232 } /* dabs */
1233 
1234 /* Compute constant used in calculations */
1235 static double
1236 _A (double eint, unsigned per)
1237 {
1238  return pow ((1.0 + eint), (double) per) - 1.0;
1239 } /* _A */
1240 
1241 /* Compute constant used in calculations */
1242 static double
1243 _B (double eint, unsigned beg)
1244 {
1245  /* if eint == 0.0, all processing _must_ stop or
1246  a recursive loop will start. */
1247  g_return_val_if_fail(eint != 0.0, 0.0);
1248  return (1.0 + eint * (double) beg) / eint;
1249 } /* _B */
1250 
1251 /* Compute constant used in calculations */
1252 static double
1253 _C (double eint, double pmt, unsigned beg)
1254 {
1255  g_return_val_if_fail(eint != 0.0, 0.0);
1256  return pmt * _B(eint, beg);
1257 } /* _C */
1258 
1259 /* compute Number of Periods from preset data */
1260 unsigned
1261 fi_calc_num_payments (fi_ptr fi)
1262 {
1263  return fi->npp =
1264  (unsigned)
1265  rnd (_fi_calc_num_payments
1266  (fi->ir, fi->pv, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep),
1267  0);
1268 } /* fi_calc_num_payments */
1269 
1270 /* Compute number of periods from:
1271  * 1. Nominal Interest
1272  * 2. Present Value
1273  * 3. Periodic Payment
1274  * 4. Future Value
1275  */
1276 double
1277 _fi_calc_num_payments (double nint, /* nominal interest rate */
1278  double pv, /* present value */
1279  double pmt, /* periodic payment */
1280  double fv, /* future value */
1281  unsigned CF, /* compounding frequency */
1282  unsigned PF, /* payment frequency */
1283  unsigned disc, /* discrete/continuous compounding */
1284  unsigned bep) /* beginning/end of period payment */
1285 {
1286  double eint = eff_int (nint / 100.0, CF, PF, disc);
1287  double CC = _C (eint, pmt, bep);
1288  CC = (CC - fv) / (CC + pv);
1289  return (CC > 0.0) ? log (CC) / log (1.0 + eint) : 0.0;
1290 } /* _fi_calc_num_payments */
1291 
1292 /* compute Interest from preset data */
1293 double
1294 fi_calc_interest (fi_ptr fi)
1295 {
1296  if (fi->npp)
1297  fi->ir = _fi_calc_interest (fi->npp, fi->pv, fi->pmt, fi->fv,
1298  fi->CF, fi->PF, fi->disc, fi->bep);
1299 
1300  return fi->ir;
1301 } /* fi_calc_interest */
1302 
1303 double ratio = 1e4; /* ratio used in iterative solution for interest */
1304 
1305 /* Compute Nominal Interest from:
1306  * 1. Number of periods
1307  * 2. Present Value
1308  * 3. Periodic Payment
1309  * 4. Future Value
1310  */
1311 double
1312 _fi_calc_interest (unsigned per,/* number of periods */
1313  double pv, /* present value */
1314  double pmt, /* periodic payment */
1315  double fv, /* future value */
1316  unsigned CF, /* compounding frequency */
1317  unsigned PF, /* payment frequency */
1318  unsigned disc, /* discrete/continuous compounding */
1319  unsigned bep) /* beginning/end of period payment */
1320 {
1321  double eint;
1322  double a, dik;
1323  int ri;
1324 
1325  if (pmt == 0.0)
1326  eint = pow ((dabs (fv) / dabs (pv)), (1.0 / (double) per)) - 1.0;
1327  else
1328  {
1329  if ((pmt * fv) < 0.0)
1330  {
1331  if (pv)
1332  a = -1.0;
1333  else
1334  a = 1.0;
1335  eint =
1336  dabs ((fv + a * (double) per * pmt) /
1337  (3.0 *
1338  (((double) per - 1.0) * ((double) per - 1.0) * pmt + pv -
1339  fv)));
1340  }
1341  else
1342  {
1343  if ((pv * pmt) < 0.0)
1344  {
1345  eint = dabs (((double) per * pmt + pv + fv) / ((double) per * pv));
1346  }
1347  else
1348  {
1349  a = dabs (pmt / (dabs (pv) + dabs (fv)));
1350  eint = a + 1.0 / (a * (double) per * (double) per * (double) per);
1351  }
1352  }
1353  do
1354  {
1355  dik =
1356  fi (per, eint, pv, pmt, fv, bep) / fip (per, eint, pv, pmt, fv, bep);
1357  eint -= dik;
1358  (void) modf (ratio * (dik / eint), &a);
1359  ri = (unsigned) a;
1360  }
1361  while (ri);
1362  } /* endif */
1363 
1364  return 100.0 * nom_int (eint, CF, PF, disc);
1365 } /* _fi_calc_interest */
1366 
1367 /* compute Present value from preset data */
1368 double
1369 fi_calc_present_value (fi_ptr fi)
1370 {
1371  return fi->pv =
1372  rnd (_fi_calc_present_value
1373  (fi->npp, fi->ir, fi->pmt, fi->fv, fi->CF, fi->PF, fi->disc,
1374  fi->bep), fi->prec);
1375 } /* fi_calc_present_value */
1376 
1377 /* Compute Present Value from:
1378  * 1. Number of periods
1379  * 2. Nominal Interest
1380  * 3. Periodic Payment
1381  * 4. Future Value
1382  */
1383 double
1384 _fi_calc_present_value (unsigned per, /* number of periods */
1385  double nint, /* nominal interest rate */
1386  double pmt, /* periodic payment */
1387  double fv, /* future value */
1388  unsigned CF, /* compounding frequency */
1389  unsigned PF, /* payment frequency */
1390  unsigned disc, /* discrete/continuous compounding */
1391  unsigned bep) /* beginning/end of period payment */
1392 {
1393  double eint = eff_int (nint / 100.0, CF, PF, disc);
1394  double AA = _A (eint, per);
1395  double CC = _C (eint, pmt, bep);
1396 
1397  return -(fv + (AA * CC)) / (AA + 1.0);
1398 } /* _fi_calc_present_value */
1399 
1400 /* compute Periodic Payment from preset data */
1401 double
1402 fi_calc_payment (fi_ptr fi)
1403 {
1404  return fi->pmt =
1405  rnd (_fi_calc_payment
1406  (fi->npp, fi->ir, fi->pv, fi->fv, fi->CF, fi->PF, fi->disc, fi->bep),
1407  fi->prec);
1408 } /* fi_calc_payment */
1409 
1410 /* Compute Periodic Payment from:
1411  * 1. Number of periods
1412  * 2. Nominal Interest
1413  * 3. Present Value
1414  * 4. Future Value
1415  */
1416 double
1417 _fi_calc_payment (unsigned per, /* number of periods */
1418  double nint, /* nominal interest rate */
1419  double pv, /* present value */
1420  double fv, /* future value */
1421  unsigned CF, /* compounding frequency */
1422  unsigned PF, /* payment frequency */
1423  unsigned disc,/* discrete/continuous compounding */
1424  unsigned bep) /* beginning/end of period payment */
1425 {
1426  double eint = eff_int (nint / 100.0, CF, PF, disc);
1427  double AA = _A (eint, per);
1428  double BB = _B (eint, bep);
1429  g_return_val_if_fail(BB != 0.0, 0.0);
1430 
1431  return -(fv + pv * (AA + 1.0)) / (AA * BB);
1432 } /* _fi_calc_payment */
1433 
1434 /* compute Future Value from preset data */
1435 double
1436 fi_calc_future_value (fi_ptr fi)
1437 {
1438  return fi->fv =
1439  rnd (_fi_calc_future_value
1440  (fi->npp, fi->ir, fi->pv, fi->pmt, fi->CF, fi->PF, fi->disc,
1441  fi->bep), fi->prec);
1442 } /* fi_calc_future_value */
1443 
1444 /* Compute Future Value from:
1445  * 1. Number of periods
1446  * 2. Nominal Interest
1447  * 3. Present Value
1448  * 4. Periodic Payments
1449  */
1450 double
1451 _fi_calc_future_value (unsigned per, /* number of periods */
1452  double nint, /* nominal interest rate */
1453  double pv, /* present value */
1454  double pmt, /* periodic payment */
1455  unsigned CF, /* compounding frequency */
1456  unsigned PF, /* payment frequency */
1457  unsigned disc, /* discrete/continuous compounding */
1458  unsigned bep) /* beginning/end of period payment */
1459 {
1460  double eint = eff_int (nint / 100.0, CF, PF, disc);
1461  double AA = _A (eint, per);
1462  double CC = _C (eint, pmt, bep);
1463 
1464  return -(pv + AA * (pv + CC));
1465 } /* _fi_calc_future_value */
1466 
1467 /* compute Nominal Interest Rate from Effective Interest Rate */
1468 static double
1469 nom_int (double eint, unsigned CF, unsigned PF, unsigned disc)
1470 {
1471  double nint;
1472 
1473  if (disc)
1474  {
1475  if (CF == PF)
1476  {
1477  nint = CF * eint;
1478  }
1479  else
1480  {
1481  nint = CF * (pow ((1.0 + eint), ((double) PF / (double) CF)) - 1.0);
1482  } /* * endif */
1483  }
1484  else
1485  nint = log (pow (1.0 + eint, PF));
1486 
1487  return nint;
1488 } /* nom_int */
1489 
1490 /* Compute Effective Interest Rate from Nominal Interest Rate */
1491 static double
1492 eff_int (double nint, unsigned CF, unsigned PF, unsigned disc)
1493 {
1494  double eint;
1495 
1496  if (disc)
1497  {
1498  if (CF == PF)
1499  {
1500  eint = nint / (double) CF;
1501  }
1502  else
1503  {
1504  eint =
1505  pow ((1.0 + nint / (double) CF), ((double) CF / (double) PF)) - 1.0;
1506  } /* endif */
1507  }
1508  else
1509  eint = exp (nint / (double) PF) - 1.0;
1510 
1511  return eint;
1512 } /* eff_int */
1513 
1514 /* calculation used in interest computation */
1515 static double
1516 fi (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep)
1517 {
1518  return _A (eint, per) * (pv + _C (eint, pmt, bep)) + pv + fv;
1519 } /* fi */
1520 
1521 /* calculation used in interest computation
1522  */
1523 static double
1524 fip (unsigned per, double eint, double pv, double pmt, double fv, unsigned bep)
1525 {
1526  double AA = _A (eint, per);
1527  double CC = _C (eint, pmt, bep);
1528  double D = (AA + 1.0) / (1.0 + eint);
1529  g_return_val_if_fail(CC != 0.0, 0.0);
1530  return (double) per * (pv + CC) * D - (AA * CC) / eint;
1531 } /* fip */
1532 
1533 void
1534 set_default (fi_ptr fi)
1535 {
1536  /* flag whether accrueing interest at beginning or end of period
1537  * FALSE --> end
1538  * TRUE --> beginning
1539  * default to end of period payment s
1540  */
1541  fi->bep = FALSE;
1542 
1543  /* flag for discrete or continuous interest
1544  * TRUE --> discrete
1545  * FALSE --> continuous
1546  * default to discrete interest
1547  */
1548  fi->disc = TRUE;
1549 
1550  /* set compounding, CF, and payment, PF, frequency per year
1551  * default to monthly payments and compounding
1552  */
1553  fi->CF = fi->PF = 12;
1554 
1555  /* standard loan quantities:
1556  * number of periods: n
1557  */
1558  fi->npp = 0;
1559 
1560  /* annual interest: i
1561  */
1562  fi->ir = 0.0;
1563 
1564  /* Present Value: pv
1565  */
1566  fi->pv = 0.0;
1567 
1568  /* Payment: pmt
1569  */
1570  fi->pmt = 0.0;
1571 
1572  /* Future Value: fv
1573  */
1574  fi->fv = 0.0;
1575 
1576 } /* set_default */
1577 
1578 /* compute Julian Day Number from calender date
1579  */
1580 unsigned long
1581 julian_day_number (unsigned year, unsigned month, unsigned day)
1582 {
1583  /* Gregorian/Julian Calender Flag.
1584  * TRUE == Julian
1585  * FALSE == Gregorian
1586  */
1587  unsigned gregorian = TRUE; /* assume we are dealing with current dates */
1588  double yr;
1589  double pfac = 0.6;
1590  unsigned long ljdn;
1591 
1592  yr = year + (month - 3.0) / 12.0;
1593  ljdn = (long) (367.0 * yr + pfac) - (2 * (long) (yr)) + (long) (yr / 4.0)
1594  + (long) day + 1721117L;
1595  if (gregorian)
1596  ljdn += -(long) (yr / 100.0) + (long) (yr / 400.0) + 2;
1597 
1598  return ljdn;
1599 } /* julian_day_number */
1600 
1602 Amortization_init (amort_sched_ptr amortsched)
1603 {
1604  unsigned n = amortsched->n;
1605  double nint = amortsched->nint;
1606  double pv = amortsched->pv;
1607  double pmt = amortsched->pmt;
1608  double fv = amortsched->fv;
1609  double eint;
1610  double new_pmt;
1611  double pve;
1612  unsigned CF = amortsched->CF;
1613  unsigned PF = amortsched->PF;
1614  unsigned disc = amortsched->disc;
1615  unsigned bep = amortsched->bep;
1616  unsigned new_n;
1617  unsigned prec = amortsched->prec;
1618  unsigned long s,
1619  d,
1620  days_to_yr_end,
1621  Eff_Date_jdn =
1622  julian_day_number (amortsched->year_E, amortsched->month_E,
1623  amortsched->day_E), Init_Date_jdn =
1624  julian_day_number (amortsched->year_I, amortsched->month_I,
1625  amortsched->day_I);
1626 
1627  amortsched->Eff_Date_jdn = Eff_Date_jdn;
1628  amortsched->Init_Date_jdn = Init_Date_jdn;
1629  amortsched->yday_E =
1630  Eff_Date_jdn - julian_day_number (amortsched->year_E, 1, 1);
1631  amortsched->yday_I =
1632  Init_Date_jdn - julian_day_number (amortsched->year_I, 1, 1);
1633  amortsched->eint = eint = eff_int (nint / 100.0, CF, PF, disc);
1634  amortsched->fv_case = dabs (fv) > dabs (pv);
1635  amortsched->bp = bep ? 1.0 : 0.0;
1636 
1637  if (PF > 24)
1638  {
1639  /* Payment frequency per year greater than bi-monthly
1640  * use actual number of days
1641  */
1642  s = Init_Date_jdn - Eff_Date_jdn;
1643  days_to_yr_end =
1644  julian_day_number (amortsched->year_I + 1, 1, 0) - Init_Date_jdn;
1645  d = 366 / PF;
1646  }
1647  else
1648  {
1649  /* Payment frequency per year bi-monthly or less
1650  * use 30 days/month, 360 days/year
1651  */
1652  if (Eff_Date_jdn == Init_Date_jdn)
1653  {
1654  s = 0;
1655  }
1656  else
1657  {
1658  s =
1659  ((amortsched->year_I - amortsched->year_E) * 360) +
1660  ((amortsched->month_I - amortsched->month_E) * 30) +
1661  amortsched->day_I - amortsched->day_E;
1662  } /* endif */
1663  days_to_yr_end = 390 - (amortsched->month_I * 30) - amortsched->day_I;
1664  d = 360 / PF;
1665  } /* endif */
1666 
1667  if (!bep)
1668  {
1669  /* ordinary annuity
1670  */
1671  s -= d;
1672  } /* endif */
1673 
1674  amortsched->yr_pmt = (days_to_yr_end + d) / d;
1675 
1676  if (pmt == 0.0)
1677  {
1678  s = 0;
1679  amortsched->pve = pv;
1680  }
1681  else
1682  {
1683  amortsched->pve =
1684  rnd (pv * pow ((1.0 + eint), ((double) (s * PF) / (double) (d * CF))),
1685  prec);
1686  } /* endif */
1687 
1688  pve = amortsched->pve;
1689 
1690  /* compute new data to fully amortize loan:
1691  * new periodic payment, new_pmt
1692  *
1693  * option 1: Amortize with original transaction - ignore interest
1694  * due to delayed initial payment
1695  *
1696  * option 2: Amortize with new pv, pve == original pv adjusted for
1697  * delayed initial payment, original payment, original fv and
1698  * original total number of payments, adjust final payment
1699  *
1700  * option 3: amortize with new pv, pve, and new payments adjusted to
1701  * minimize final payment, keep original number of payments and
1702  * original fv
1703  *
1704  * option 4: amortize with new pv, pve, original payments and new
1705  * number of payments to keep original final fv */
1706 
1707  /* option 3, compute new periodic payment */
1708  amortsched->new_pmt = new_pmt =
1709  rnd (_fi_calc_payment (n, nint, pve, fv, CF, PF, disc, bep), prec);
1710 
1711  /* option 4: compute new number of total payments, new_n */
1712  amortsched->new_n = new_n =
1713  (unsigned)
1714  rnd (_fi_calc_num_payments (nint, pve, pmt, fv, CF, PF, disc, bep), 0);
1715 
1716  /* following used in QTAwk to insure integer value, not needed in C */
1717  /* n = int(n); */
1718 
1719  /* compute payment for constant payment to principal loan and final
1720  * payment for original loan amount include interest due */
1721  amortsched->cpmt1 = rnd (-pv / n, prec);
1722  amortsched->final_pmt_opt_1 = -pv - amortsched->cpmt1 * (n - 1);
1723  amortsched->final_pmt_opt_1 *= eint + 1;
1724 
1725  /* compute payment for constant payment to principal loan and final
1726  * payment for delayed loan amount include interest due */
1727  amortsched->cpmt2 = rnd (-pve / n, prec);
1728  amortsched->final_pmt_opt_2 = -pve - amortsched->cpmt2 * (n - 1);
1729  amortsched->final_pmt_opt_2 *= eint + 1;
1730 
1731  if (bep)
1732  {
1733  amortsched->final_pmt_opt_3 =
1734  rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) -
1735  (fv / (1.0 + eint)), prec);
1736  amortsched->final_pmt_opt_4 =
1737  rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) -
1738  (fv / (1.0 + eint)), prec);
1739  amortsched->final_pmt_opt_5 =
1740  rnd (_fi_calc_future_value
1741  (n - 1, nint, pve, new_pmt, CF, PF, disc,
1742  bep) - (fv / (1.0 + eint)), prec);
1743  if (new_n)
1744  amortsched->final_pmt_opt_6 =
1745  rnd (_fi_calc_future_value
1746  (new_n - 1, nint, pve, pmt, CF, PF, disc,
1747  bep) - (fv / (1.0 + eint)), prec);
1748  else
1749  amortsched->final_pmt_opt_6 = 0.0;
1750  }
1751  else
1752  {
1753  amortsched->final_pmt_opt_3 =
1754  rnd (_fi_calc_future_value (n - 1, nint, pv, pmt, CF, PF, disc, bep) *
1755  (1.0 + eint) - fv, prec);
1756  amortsched->final_pmt_opt_4 =
1757  rnd (_fi_calc_future_value (n - 1, nint, pve, pmt, CF, PF, disc, bep) *
1758  (1.0 + eint) - fv, prec);
1759  amortsched->final_pmt_opt_5 =
1760  rnd (_fi_calc_future_value
1761  (n - 1, nint, pve, new_pmt, CF, PF, disc, bep) * (1.0 + eint) - fv,
1762  prec);
1763  if (new_n)
1764  amortsched->final_pmt_opt_6 =
1765  rnd (_fi_calc_future_value
1766  (new_n - 1, nint, pve, pmt, CF, PF, disc,
1767  bep) * (1.0 + eint) - fv, prec);
1768  else
1769  amortsched->final_pmt_opt_6 = 0.0;
1770  } /* endif */
1771 
1772  /* compute delayed interest */
1773  amortsched->delayed_int = pv - amortsched->pve;
1774 
1775  return amortsched;
1776 } /* Amortization_init */
1777 
1779 Amortization_Schedule (amort_sched_ptr amortsched)
1780 {
1781  unsigned n = amortsched->n;
1782  double nint = amortsched->nint;
1783  double pv = amortsched->pv;
1784  double pmt = amortsched->pmt;
1785  double fv = amortsched->fv;
1786  double eint = amortsched->eint;
1787  unsigned CF = amortsched->CF;
1788  unsigned PF = amortsched->PF;
1789  unsigned disc = amortsched->disc;
1790  unsigned bep = amortsched->bep;
1791  double cpmt = 0;
1792  double final_pmt = 0;
1793  char summary = amortsched->summary;
1794  unsigned option = amortsched->option;
1795  unsigned yr_pmt = amortsched->yr_pmt;
1796  unsigned fv_case = amortsched->fv_case;
1797  unsigned prec = amortsched->prec;
1798  unsigned j, s, yr, per_cnt, pmt_cnt = 0, k = 0, sum_prt;
1799 
1800  int jj;
1801 
1802  unsigned long d;
1803 
1804  double yr_fv, sum_int, yr_int, prin, adv_pmt, pmt_int, hpv = 0.0;
1805  yearly_summary_ptr yrly_sum;
1806  amort_sched_yr_ptr amortyr;
1807  sched_pmt_ptr pmtsched = NULL;
1808 
1809  sum_int = yr_int = 0.0;
1810 
1811  switch (option)
1812  {
1813  case 1:
1814  amortsched->cpmt = cpmt = amortsched->cpmt1;
1815  /* re-compute final payment without interest
1816  */
1817  amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1);
1818  summary = (summary == 'y') ? 'x' : 'o';
1819  break;
1820  case 2:
1821  amortsched->cpmt = cpmt = amortsched->cpmt2;
1822  pv = amortsched->pve;
1823  /* re-compute final payment without interest
1824  */
1825  amortsched->final_pmt = final_pmt = -pv - cpmt * (n - 1);
1826  summary = (summary == 'y') ? 'x' : 'o';
1827  break;
1828  case 3:
1829  amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_3;
1830  break;
1831  case 4:
1832  pv = amortsched->pve;
1833  amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_4;
1834  break;
1835  case 5:
1836  pv = amortsched->pve;
1837  pmt = amortsched->new_pmt;
1838  amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_5;
1839  break;
1840  case 6:
1841  n = amortsched->new_n;
1842  pv = amortsched->pve;
1843  amortsched->final_pmt = final_pmt = amortsched->final_pmt_opt_6;
1844  break;
1845  } /* endswitch */
1846 
1847  yr = amortsched->year_I;
1848  sum_prt = TRUE;
1849  switch (summary)
1850  {
1851  case 'a':
1852  /* variable advanced prepayment schedule. prepayment equals next
1853  * period principal. */
1854  amortsched->schedule.first_yr =
1855  amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
1856 
1857  d = pv;
1858 
1859  for (per_cnt = 0, s = 1, j = n; pv != fv; j -= 2, per_cnt++)
1860  {
1861  /* basic equation to compute interest this payment period */
1862  pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
1863 
1864  /* sum yearly interest paid */
1865  yr_int += pmt_int;
1866 
1867  /* sum total interest paid */
1868  sum_int += pmt_int;
1869 
1870  /* compute principal paid this payment period and round to
1871  nearest cent */
1872  if (dabs (pmt) > dabs (pv))
1873  {
1874  prin = -pv;
1875  pmt = prin + pmt_int;
1876  adv_pmt = 0.0;
1877  pv = fv;
1878  }
1879  else
1880  {
1881  prin = rnd (pmt - pmt_int, prec);
1882 
1883  /* compute remaining pv and round to nearest cent */
1884  pv = rnd (pv + prin, prec);
1885 
1886  /* compute principal for next payment cycle and round to
1887  nearest cent */
1888  adv_pmt = rnd (pmt + (pv + (amortsched->bp * pmt)) * eint, prec);
1889 
1890  if (dabs (pv) >= dabs (adv_pmt))
1891  {
1892  /* remaining pv greater than advanced principal payment
1893  * compute remaining pv and round to nearest cent */
1894  pv = rnd (pv + adv_pmt, prec);
1895  }
1896  else
1897  {
1898  /* remaining pv less than advanced principal payment reduce
1899  * advanced pricipla payment to remaining pv */
1900  adv_pmt = -pv;
1901 
1902  /* and set remaining pv to fv */
1903  pv = fv;
1904  } /* ## endif */
1905  } /* # endif */
1906 
1907  if (sum_prt)
1908  {
1909  jj = (j < yr_pmt) ? j + 1 : yr_pmt;
1910  amortyr->payments =
1911  pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
1912  pmt_cnt = 0;
1913 
1914  sum_prt = FALSE;
1915  } /* endif */
1916 
1917  pmtsched->period_num = s++;
1918  pmtsched->interest = pmt_int;
1919  pmtsched->principal = prin;
1920  pmtsched->advanced_pmt = adv_pmt;
1921  pmtsched->total_pmt = pmt + adv_pmt;
1922  pmtsched->balance = pv;
1923  pmtsched++;
1924  pmt_cnt++;
1925 
1926  if (!--yr_pmt)
1927  {
1928  yr_pmt = PF;
1929 
1930  amortyr->year = yr++;
1931  amortyr->interest_pd = yr_int;
1932  amortyr->principal_pd = pv - hpv;
1933  amortyr->yr_end_balance = pv;
1934  amortyr->total_interest_pd = sum_int;
1935  amortyr->num_periods = pmt_cnt;
1936  amortyr->next_yr =
1937  (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
1938  amortyr = amortyr->next_yr;
1939 
1940  hpv = pv;
1941  yr_int = 0.0;
1942  sum_prt = TRUE;
1943  } /* endif */
1944  } /* endfor */
1945 
1946  if (dabs (pv) > 0.0)
1947  {
1948  /* basic equation to compute interest this payment period */
1949  pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
1950 
1951  /* sum yearly interest paid */
1952  yr_int += pmt_int;
1953 
1954  /* sum total interest paid */
1955  sum_int += pmt_int;
1956 
1957  /* compute principal paid this payment period and round to
1958  nearest cent */
1959  prin = rnd (pmt - pmt_int, prec);
1960  final_pmt = pmt;
1961 
1962  /* compute remaining pv and round to nearest cent */
1963  pv = rnd (pv + prin, prec);
1964 
1965  /* Set advanced principal payment to remaining pv */
1966  adv_pmt = -pv;
1967  amortyr->final_pmt = final_pmt += adv_pmt;
1968 
1969  /* and set remaining pv to fv */
1970  pv = fv;
1971 
1972  pmtsched->period_num = s++;
1973  pmtsched->interest = pmt_int;
1974  pmtsched->principal = prin;
1975  pmtsched->advanced_pmt = adv_pmt;
1976  pmtsched->total_pmt = final_pmt;
1977  pmtsched->balance = pv;
1978 
1979  per_cnt++;
1980  pmt_cnt++;
1981  } /* endif */
1982 
1983  if (dabs (yr_int) > 0.0)
1984  {
1985  amortyr->year = yr++;
1986  amortyr->interest_pd = yr_int;
1987  amortyr->principal_pd = pv - hpv;
1988  amortyr->total_interest_pd = sum_int;
1989  amortyr->num_periods = pmt_cnt;
1990  } /* endif */
1991 
1992  amortsched->total_periods = per_cnt;
1993  break;
1994  case 'f':
1995  /* fixed prepaymet schedule prepayment specified by user */
1996  amortsched->schedule.first_yr =
1997  amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
1998 
1999  d = pv;
2000 
2001  /* set advnaced payment */
2002  adv_pmt = amortsched->fixed_pmt;
2003 
2004  for (per_cnt = 0, s = 1, j = n; j && (pv != fv); j--, per_cnt++)
2005  {
2006  /* basic equation to compute interest this payment period */
2007  pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
2008  /* sum yearly interest paid
2009  */
2010  yr_int += pmt_int;
2011  /* sum total interest paid */
2012  sum_int += pmt_int;
2013 
2014  /* compute principal paid this payment period and round to
2015  nearest cent */
2016  if (dabs (pmt) > dabs (pv))
2017  {
2018  prin = -pv;
2019  pmt = prin + pmt_int;
2020  adv_pmt = 0.0;
2021  pv = 0.0;
2022  }
2023  else
2024  {
2025  prin = rnd (pmt - pmt_int, prec);
2026 
2027  /* compute remaining pv and round to nearest cent */
2028  pv = rnd (pv + prin, prec);
2029 
2030  if (dabs (pv) >= dabs (adv_pmt))
2031  {
2032  /* remaining pv greater than advanced principal payment
2033  * compute remaining pv and round to nearest cent */
2034  pv = rnd (pv + adv_pmt, prec);
2035  }
2036  else
2037  {
2038  /* remaining pv less than advanced principal payment reduce
2039  * advanced pricipal payment to remaining pv and set
2040  * remaining pv to fv */
2041  adv_pmt = -pv;
2042  pv = fv;
2043  } /*## endif */
2044  } /* # endif */
2045 
2046  if (sum_prt)
2047  {
2048  jj = (j < yr_pmt) ? j + 1 : yr_pmt;
2049  amortyr->payments =
2050  pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
2051  pmt_cnt = 0;
2052 
2053  sum_prt = FALSE;
2054  }
2055  else
2056  {
2057  (amortyr->num_periods)++;
2058  } /* ## endif */
2059 
2060  pmtsched->period_num = s++;
2061  pmtsched->interest = pmt_int;
2062  pmtsched->principal = prin;
2063  pmtsched->advanced_pmt = adv_pmt;
2064  pmtsched->total_pmt = pmt + adv_pmt;
2065  pmtsched->balance = pv;
2066  pmt_cnt++;
2067  pmtsched++;
2068 
2069  if (!--yr_pmt)
2070  {
2071  yr_pmt = PF;
2072 
2073  amortyr->year = yr++;
2074  amortyr->interest_pd = yr_int;
2075  amortyr->principal_pd = pv - hpv;
2076  amortyr->yr_end_balance = pv;
2077  amortyr->total_interest_pd = sum_int;
2078  amortyr->num_periods = pmt_cnt;
2079  amortyr->next_yr =
2080  (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
2081  amortyr = amortyr->next_yr;
2082 
2083  hpv = pv;
2084  yr_int = 0.0;
2085  sum_prt = TRUE;
2086  } /* ## endif */
2087  } /* ## endfor */
2088 
2089  if (pv != fv)
2090  {
2091  /* # basic equation to compute interest this payment period */
2092  pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
2093 
2094  /* # sum yearly interest paid */
2095  yr_int += pmt_int;
2096  /* # sum total interest paid */
2097  sum_int += pmt_int;
2098 
2099  /* # compute principal paid this payment period and round to
2100  nearest cent */
2101  prin = rnd (pmt - pmt_int, prec);
2102  final_pmt = pmt;
2103 
2104  /* # compute remaining pv and round to nearest cent */
2105  pv = rnd (pv + prin, prec);
2106 
2107  /* # Set advanced principal payment to remaining pv */
2108  adv_pmt = -pv;
2109  amortyr->final_pmt = final_pmt += adv_pmt;
2110 
2111  /* # and set remaining pv to fv */
2112  pv = fv;
2113 
2114  pmtsched->period_num = s++;
2115  pmtsched->interest = pmt_int;
2116  pmtsched->principal = prin;
2117  pmtsched->advanced_pmt = adv_pmt;
2118  pmtsched->total_pmt = final_pmt;
2119  pmtsched->balance = pv;
2120 
2121  per_cnt++;
2122  pmt_cnt++;
2123  } /* # endif */
2124 
2125  if (dabs (yr_int) > 0.0)
2126  {
2127  amortyr->year = yr++;
2128  amortyr->interest_pd = yr_int;
2129  amortyr->principal_pd = pv - hpv;
2130  amortyr->total_interest_pd = sum_int;
2131  amortyr->num_periods = pmt_cnt;
2132  } /* endif */
2133 
2134  amortsched->total_periods = per_cnt;
2135  break;
2136  case 'o':
2137  /* Constant payment to principal use constant payment equal to
2138  * original pv divided by number of periods. constant payment to
2139  * pricipal could be amount specified by user. */
2140  amortsched->schedule.first_yr =
2141  amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
2142  amortsched->total_periods = n;
2143 
2144  d = yr_pmt;
2145  for (s = 1, j = n - 1; j; j--, k++)
2146  {
2147  pmt_int = -rnd (pv * eint, prec);
2148 
2149  /* sum yearly interest paid */
2150  yr_int += pmt_int;
2151 
2152  /* sum total interest paid */
2153  sum_int += pmt_int;
2154 
2155  pv = rnd (pv + cpmt, prec);
2156 
2157  if (sum_prt)
2158  {
2159  jj = (j < yr_pmt) ? j + 1 : yr_pmt;
2160  amortyr->payments =
2161  pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
2162  amortyr->num_periods = jj;
2163  k = 0;
2164 
2165  sum_prt = FALSE;
2166  } /* endif */
2167 
2168  pmtsched->period_num = s++;
2169  pmtsched->interest = pmt_int;
2170  pmtsched->total_pmt = cpmt + pmt_int;
2171  pmtsched->balance = pv;
2172  pmtsched++;
2173 
2174  if (!--yr_pmt)
2175  {
2176  yr_pmt = PF;
2177 
2178  amortyr->year = yr++;
2179  amortyr->interest_pd = yr_int;
2180  amortyr->principal_pd = d * cpmt;
2181  amortyr->yr_end_balance = pv;
2182  amortyr->total_interest_pd = sum_int;
2183  amortyr->next_yr =
2184  (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
2185  amortyr = amortyr->next_yr;
2186 
2187  d = PF;
2188  yr_int = 0.0;
2189  sum_prt = TRUE;
2190  } /* endif */
2191  } /* endfor */
2192 
2193  if (pv)
2194  {
2195  pmt_int = -rnd (pv * eint, prec);
2196 
2197  /* sum yearly interest paid */
2198  yr_int += pmt_int;
2199 
2200  /* sum total interest paid */
2201  sum_int += pmt_int;
2202 
2203  pmtsched->period_num = s++;
2204  pmtsched->interest = -pmt_int;
2205  pmtsched->total_pmt = -pv + pmt_int;
2206  pmtsched->balance = 0.0;
2207 
2208  amortyr->final_pmt = -pv - pmt_int;
2209  } /* endif */
2210 
2211  if (dabs (yr_int) > 0.0)
2212  {
2213  amortyr->year = yr++;
2214  amortyr->interest_pd = yr_int;
2215  amortyr->principal_pd = -pv + k * cpmt;
2216  amortyr->total_interest_pd = sum_int;
2217  } /* endif */
2218  break;
2219  case 'p':
2220  /* normal amortization schedule interest, principal and balance
2221  * per payment period */
2222  amortsched->schedule.first_yr =
2223  amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
2224  amortsched->total_periods = n;
2225 
2226  hpv = pv;
2227  for (s = 1, j = n - 1; j; j--)
2228  {
2229  /* basic equation for computing interest paid in payment period */
2230  pmt_int = -rnd ((pv + (amortsched->bp * pmt)) * eint, prec);
2231 
2232  /* sum yearly interest paid */
2233  yr_int += pmt_int;
2234 
2235  /* sum total interest paid */
2236  sum_int += pmt_int;
2237 
2238  /* compute principal paid this payment period */
2239  prin = rnd (pmt - pmt_int, prec);
2240 
2241  /* compute remaining pv and round to nearest cent */
2242  pv = rnd (pv + prin, prec);
2243 
2244  if (sum_prt)
2245  {
2246  jj = (j < yr_pmt) ? j + 1 : yr_pmt;
2247  amortyr->payments =
2248  pmtsched = (sched_pmt_ptr) calloc (jj, sizeof (sched_pmt));
2249  amortyr->num_periods = jj;
2250 
2251  sum_prt = FALSE;
2252  } /* endif */
2253 
2254  if (fv_case)
2255  {
2256  pmtsched->period_num = s++;
2257  pmtsched->interest = pmt_int;
2258  pmtsched->balance = pv;
2259  pmtsched++;
2260  }
2261  else
2262  {
2263  pmtsched->period_num = s++;
2264  pmtsched->interest = pmt_int;
2265  pmtsched->principal = prin;
2266  pmtsched->balance = pv;
2267  pmtsched++;
2268  } /* endif */
2269 
2270  if (!--yr_pmt)
2271  {
2272  yr_pmt = PF;
2273 
2274  amortyr->year = yr++;
2275  amortyr->interest_pd = yr_int;
2276  if (!fv_case)
2277  {
2278  amortyr->principal_pd = pv - hpv;
2279  } /* endif */
2280  amortyr->yr_end_balance = pv;
2281  amortyr->total_interest_pd = sum_int;
2282  amortyr->next_yr =
2283  (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
2284  amortyr = amortyr->next_yr;
2285 
2286  hpv = pv;
2287  yr_int = 0.0;
2288  sum_prt = TRUE;
2289  } /* * endif */
2290  } /* * endfor */
2291 
2292  /* determine if payment due at beginning or end of period in order
2293  * to correctly compute final payment, interest and principal */
2294  if (bep)
2295  {
2296  /* paying remainder at beginning of period compute final payment */
2297  final_pmt = -pv - fv / (1 + eint);
2298 
2299  /* then compute interest paid with final final payment */
2300  pmt_int = -rnd ((pv + final_pmt) * eint, prec);
2301 
2302  /* then compute the principal paid */
2303  prin = final_pmt + pmt_int;
2304  }
2305  else
2306  {
2307  /* basic equation for computing interest paid in payment period
2308  * for payment at end of period */
2309  pmt_int = -rnd (pv * eint, prec);
2310 
2311  /* compute principal paid this payment period */
2312  prin = -pv;
2313 
2314  /* compute the final payment note the final payment may be
2315  * computed either of two ways both are equivalent */
2316  final_pmt = prin + pmt_int;
2317  } /* * endif */
2318 
2319  pv = -fv;
2320 
2321  /* sum yearly interest paid */
2322  yr_int += pmt_int;
2323 
2324  /* sum total interest paid */
2325  sum_int += pmt_int;
2326 
2327  if (sum_prt)
2328  {
2329  amortyr->payments =
2330  pmtsched = (sched_pmt_ptr) calloc (1, sizeof (sched_pmt));
2331  amortyr->num_periods = 1;
2332  } /* endif */
2333 
2334  amortyr->final_pmt = final_pmt;
2335 
2336  if (fv_case)
2337  {
2338  pmtsched->period_num = s++;
2339  pmtsched->interest = pmt_int;
2340  pmtsched->balance = pv;
2341  }
2342  else
2343  {
2344  pmtsched->period_num = s++;
2345  pmtsched->interest = pmt_int;
2346  pmtsched->principal = prin;
2347  pmtsched->balance = pv;
2348  } /* endif */
2349 
2350  if (dabs (yr_int) > 0.0)
2351  {
2352  amortyr->year = yr++;
2353  amortyr->interest_pd = yr_int;
2354  amortyr->total_interest_pd = sum_int;
2355  if (!bep)
2356  {
2357  amortyr->principal_pd = -hpv;
2358  } /* endif */
2359  } /* endif */
2360 
2361  break;
2362  case 'x':
2363  /* constant payment to principal - annual summary */
2364  /* compute number of years to summarize */
2365  j = n / PF;
2366  if (yr_pmt < PF)
2367  j++;
2368  amortsched->total_periods = j;
2369  amortsched->schedule.summary =
2370  yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary));
2371 
2372  jj = 0;
2373  for (j = n, sum_prt = 0; j > 0; j -= yr_pmt, yr_pmt = PF, sum_prt++)
2374  {
2375  if (j <= PF)
2376  {
2377  s = jj + j;
2378  yr_pmt = j;
2379  yr_fv = rnd (pv + cpmt * (s - 1), prec) + final_pmt;
2380  }
2381  else
2382  {
2383  s = jj + yr_pmt;
2384  yr_fv = rnd (pv + cpmt * s, prec);
2385  } /* endif */
2386  prin = -eint * jj * (pv + (cpmt * (jj - 1) / 2.0));
2387  yr_int = -eint * s * (pv + (cpmt * (s - 1) / 2.0));
2388  yr_int = rnd (yr_int - prin, prec);
2389  jj += yr_pmt;
2390 
2391  sum_int += yr_int;
2392 
2393  yrly_sum[sum_prt].year = yr++;
2394  yrly_sum[sum_prt].interest = yr_int;
2395  yrly_sum[sum_prt].end_balance = yr_fv;
2396  } /* endfor */
2397 
2398  break;
2399  case 'y':
2400  /* normal amortization - annual summary */
2401  /* compute number of years to summarize */
2402  j = n / PF;
2403  if (yr_pmt < PF)
2404  j++;
2405  if (n > (j * PF))
2406  j++;
2407  amortsched->total_periods = j;
2408  amortsched->schedule.summary =
2409  yrly_sum = (yearly_summary_ptr) calloc (j, sizeof (yearly_summary));
2410 
2411  hpv = pv;
2412 
2413  for (jj = n, j = 0; jj > 0; jj -= yr_pmt, yr_pmt = PF, j++)
2414  {
2415  if (jj <= (int)PF)
2416  {
2417  yr_fv = fv;
2418  yr_int = rnd (((jj - 1) * pmt) + hpv + final_pmt, prec);
2419  }
2420  else
2421  {
2422  yr_fv =
2423  -rnd (_fi_calc_future_value
2424  (yr_pmt, nint, hpv, pmt, CF, PF, disc, bep), prec);
2425  yr_int = rnd ((yr_pmt * pmt) + hpv - yr_fv, prec);
2426  } /* * endif */
2427 
2428  sum_int += yr_int;
2429 
2430  yrly_sum[j].year = yr++;
2431  yrly_sum[j].interest = yr_int;
2432  yrly_sum[j].end_balance = yr_fv;
2433  hpv = yr_fv;
2434  } /* * endfor */
2435 
2436  break;
2437  } /* * endswitch */
2438 
2439  amortsched->total_interest = sum_int;
2440 
2441  return amortsched;
2442 } /* Amortization_Schedule */
2443 
2444 /* function to free dynamically allocated memory used for amortization
2445  schedule */
2446 void
2447 Amortization_free (amort_sched_ptr amortsched)
2448 {
2449  amort_sched_yr_ptr amortyr, prst_yr;
2450 
2451  switch (amortsched->summary)
2452  {
2453  case 'a':
2454  case 'f':
2455  case 'o':
2456  case 'p':
2457  for (amortyr = amortsched->schedule.first_yr; amortyr; amortyr = prst_yr)
2458  {
2459  if (amortyr->payments)
2460  free (amortyr->payments);
2461  prst_yr = amortyr->next_yr;
2462  free (amortyr);
2463  } /* endfor */
2464  break;
2465  case 'y':
2466  free (amortsched->schedule.summary);
2467  break;
2468  } /* endswitch */
2469 
2470  amortsched->schedule.first_yr = NULL;
2471 } /* amort_free */