Simple Finance Version 2.1 - Standard (c) 1997 Bob Wolfson (bwolfson@myself.com) RPN.1.r [x]xr1+xnP;[y]Cxxr1+/; [Z]xpCx*xiCx1-*xr/+; [z]xnxp*Cy*xrxn*Cy*Cx1--xi*xr/xr/+; [G]xfCZ-Cz/xr+; [V]xpCx*Cx1-xr/xi*+; [r]xr0#'99'=@; "Simple Finance 2.1" "CA" 0Xp0Xf0Xn0Xi0Xr; "Vals" xpxfxnxixr; ~ "P"Xp; "F"Xf; "N"Xn; "I"Xi; "R"Xr; ~ "p" Cr(xfxixn*-:xfxr*xi+Cx/xi-xr/)Xpxp; "f" Cr(xpxixn*+:CV)Xfxf; "n" Cr(xfxp-xi/:xixr/xf+xixr/xp+/lxr1+l/)Xnxn; "i" Cr(xfxp-xn/:xfxpCx*-Cx1-/xr*)Xixi; "r" 1XrCVxf-Xa{xrHXrCVxf-Xbxa0&xa0>xb0<&|xr0=7|(B:xbXa)}xr0=7(1:xr2*)Xd0Xb#'.9'Xr{xrxd=7(xdXrB)xdXrCGXdxb1+Xbxd0|(1nXrB)}xr; Simple Finance version 2.1 Documentation (c) 1997 Bob Wolfson Email: bwolfson@myself.com *** Legal Matters ***************************************************************************** The Simple Finance version 2.1 script and documenation is FREEWARE. You may use and distribute it freely provided that you do so without modification. The Simple Finance script and documentation are provided with no expressed or implied warantees of any kind. You accept the script and documentation in "as is" condition, and agree to use them at your own risk and without attributing any liability to the author. *********************************************************************************************** *** INTRODUCTION The Simple Finance script provides buttons to enter and calculate 5 related financial values, any one of which can be calculated from given values for the other four: Present Value (p) - The current value of an investment, or the amount owed (a negative value) on a loan. Future Value (f) - The value at the end of a certain number of periods. A negative value represents future debt. Number of Periods (n) - The number of periods between the current and future values. No units are assumed, and the value should be positive since time doesn't run backwards. Installment Value (i) - The (positive) value of an deposit or payment per period. A negative number would represent a withdrawal or annuity payment. Interest Rate (r) - The interest rate per period. Remember to divide annual rates by 12 when periods are months! 12 buttons are used to work with these values: The P, F, N, I and R buttons are used to enter values. The p, f, n, i and r buttons are used to calculate values. The 'Xa' button clears all previously entered values. The 'Vals' button pushes all the values in the above order onto the stack. Xa sets all values to zero. Enter all 4 other values in order to calculate the 5th. *** NOTES ON SIGNS Regarding positive and negative numbers: the 5 values are mathematically and meaningfully interrelated via the following equation: P*(1+R)^N + I*{[(1+R)^N - 1]/R} = F or P*(1+R)^N + I*{[(1+R)^N - 1]/R} - F = 0 Some people, especially those used to an HP12C, are used to dealing with a slightly different, though entirely equivalent equation: P*(1+R)^N + I*{[(1+R)^N - 1]/R} + F = 0 The only difference here is the sign of the F term, which propagates into one's general use of signs when interpreting a problem. For example, Simple Finance treats the present value of a loan as a negative amount - money you owe. In the HP12C interpretation, the initial value of a loan is a positive amount - money you have at your disposal. Similarly, Simple Finance treats deposits into a savings account and the future value of such an account as positive values - money of yours, while in the HP12C people will tend to think savings deposits as negative amounts - flows into the account - counterbalanced by a future positive withdrawal - flow back to you. All that varies between the two are the signs. The absolute value of all terms is unaffected, and either is a 'valid' interpretation of mathematics which leaves us one degree of freedom. However, to cover all bases, an HP12C variant of the standard script above follows this documentation. Use whichever variant suits you best. *** STABILITY OF VALUES No computer can perform arithmetic without introducing rounding error. If you calculate, say, F from (P,N,I,R) the result may not be *exactly* right, though it should be so close as to make no practical difference. However, if you then attempt to recall one of the values, say N, that you previously entered the script will *calculate* that value from the other three entered values (P, I, R) and the inexact, calculated value of F. F's rounding error, along with additional rounding for the new calculation, will be propagated to N, and the result you see may not match the N you entered. A prior version of the script kept track of which values were entered and which was calculated, and ensured that this 'value instability' would not happen. This forced some inconveniences upon users, e.g. one had to *enter* zeros, and was therefore removed. If you would like to see this feature reimplemented, send email to 'bwolfson@myself.com'. *** EXAMPLES All the following examples involve signs appropriate for the standard script. * Example 1: How much will you have in savings in 5 years if you have $1,000 now, add monthly deposits of $100 and earn interest at the rate of 7% per year? Present Value -> 1000 P Number of Periods -> 5 Ent 12 * N (note that we're dealing with MONTHLY payments!) Installment Value -> 100 I Interest Rate -> .07 Ent 12 / R (remember that '%' means 'divide by 100'!) Future Value -> f pushes 8576.91542 onto the stack (depending on the number of decimal places being displayed) * Example 2: How long will it take to pay off a $50,000 mortgage at 8.5% annual interest (compounded monthly) if payments are made at the rate of $800 per month? Present Value -> 50000 +/- P (you OWE $50 grand) Future Value -> 0 F (eventually you won't owe anything) Installment Value -> 800 I (a monthly reduction of debt increases your worth!) Interest Rate -> .085 Ent 12 / R Number of Periods -> n pushes 82.83268448 onto the stack - the number of months it's going to take to pay the loan. Note: This is not perfectly accurate. The formula involves a logarithm calculation and RPN has some rounding errors in this area. In the above example, the right answer is 82.83314761, so the error is only 0.00056% of the correct amount. Still, watch out. * Example 3: How much are you going to owe Guido in 3 weeks if you borrow $2,000 at 18% compounded per week? Present Value -> 2000 P (we're taking Guido's point of view: your debt is GOOD for Guido) Installment Value -> 0 I (Guido only accepts payment in full - or else!) Number of Periods -> 3 N Interest Rate -> .18 R Future Value -> f pushes 3286.064 onto the stack - let's hope your horse comes through! * Example 4: Bill Gates quits his job and cashes in his stock. Placing the $18 billion in a CD at 3.75% annually (compounded monthly) how long can Bill continue to spend $1 million per day? Present Value -> 18E9 P Future Value -> 0 F Installment Value -> 1 +/- E6 Ent 30 * I (i.e. Bill WITHDRAWS about $30 million per month - thus decreasing his worth) Interest Rate -> .0375 Ent 12 / R Number of Periods -> n pushes Numerical Error onto the stack. Why? Because even at 3.75%, Bill will earn around $675 million per year and can spend nearly $2 million per day without ever running out! This example highlights two points: (1) you may need to think carefully about the problem you're trying to solve to be sure it makes 'sense', and (2) Bill is one VERY rich s.o.b. * Example 5: You've got $75,000 in the investments, and you want to retire in 10 years with $300,000 saved. You can afford to save an additional $1000 per month. What interest rate will you need? Present Value -> 75000 P Future Value -> 300000 F Number of Periods -> 120 N Installment Value -> 1000 I Interest Rate -> r pushes .0049876 onto the stack (after about 8 seconds) - multiply by 12 to get the annual rate of 5.98512%. Whew - you should be able to make it! Notes on interest rate calculations: 1) They can be a bit slow. There's no algabraic formula for the calculation; it requires a looping algorithm to find the root of an equation. (FYI, it's a Newton-Raphson convergence algorithm.) 2) The solution algorithm involves a process that starts with a guess, and each successive iteration is supposed to refine it. The process stops when the next refinement is no more than .0000001 different than the current one, but the rate of convergence may be slow if the guess is poor. Therefore, a prior step attempts to find a good guess. This involves another loop which seeks a pair of values that the actual solution must be between. The following pairs are tested in sequence: (1 and 0.5), (0.5 and 0.25), (0.25 and 0.125)... and so on until a pair bounding the solution is found, or the lower member of the pair is less than 0.0000001. The high member of a bounding pair is chosen as the initial guess. If no bounding pair is found, the starting guess is set to 1. The theory here is that *most* interest rates are in the range tested by the pairs. And if this isn't true of the rate you're solving-for, then 1 is as good a guess as any. Thus, for a *typical* rate, the root finding process will start from a good guess and only loop a few times. The entire process usually takes around 10 seconds. 3) Interest rates greater than 1 present a problem - an unbounded one. The guessing step can't search the entire number line, and so an initial guess of 1 must suffice. Subsequent root finding may converge very slowly, and rather than allowing it to go on indefinately, it's capped at 30 iterations. If it reaches that point, the process returns -1 to indicate failure to find the rate. The net result is that rates greater than 1 will take a long time to find - if they can be found at all - and if not the process will run for about 40 seconds before it gives up. Net net: the process isn't designed to work for rates greater than 1. 4) One more oddity: during root-finding, an iteration can theoretically result in a 'refined' guess less than 0. This makes no sense; interest rates can't be negative for our purposes. When this happens the process which is supposed to converge is probably diverging instead. Therefore, the algorithm simply quits and again returns -1. For reasonable financial problems with typical interest rates compounded daily, monthly, or yearly, none of this should be of concern. It just seemed prudent to handle all possibilities gracefully (no infinite looping) and warn you up front. *** CHANGES HISTORY * Version 2.1: - Modified to be compatible with RPN 2.1. No changes in functionality, but some RPN 2.1 byte code changes make the code execute faster. * Version 2.01: - Trivial doc change * Version 2.0: - Allow root calculation to step outside of [0,1] range and find roots >1. - Speeded-up root calculation. - Inlined most variable references. - Removed tracking of entered vs. calculated values. - Changed nomenclature of buttons: e.g. '^r' and '?r' changed to 'R' and 'r' resp. - Bug fix for rates exactly = 1. Simple Finance Version 2.1 - HP12C (c) 1997 Bob Wolfson (bwolfson@myself.com) RPN.1.r [x]xr1+xnP;[y]Cxxr1+/; [Z]xpCx*xiCx1-*xr/+; [z]xnxp*Cy*xrxn*Cy*Cx1--xi*xr/xr/+; [G]xfCZ-Cz/xr+; [V]xpCx*Cx1-xr/xi*+; [r]xr0#'99'=@; "Simple Finance 2.1" "CA" 0Xp0Xf0Xn0Xi0Xr; "Vals" xpxfnxnxixr; ~ "P"Xp; "F"nXf; "N"Xn; "I"Xi; "R"Xr; ~ "p" Cr(xfxixn*-:xfxr*xi+Cx/xi-xr/)Xpxp; "f" Cr(xpxixn*+:CV)Xfxfn; "n" Cr(xfxp-xi/:xixr/xf+xixr/xp+/lxr1+l/)Xnxn; "i" Cr(xfxp-xn/:xfxpCx*-Cx1-/xr*)Xixi; "r" 1XrCVxf-Xa{xrHXrCVxf-Xbxa0&xa0>xb0<&|xr0=7|(B:xbXa)}xr0=7(1:xr2*)Xd0Xb#'.9'Xr{xrxd=7(xdXrB)xdXrCGXdxb1+Xbxd0|(1nXrB)}xr;