mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-29 20:24:25 -06:00
16b4976381
Found via `codespell -q 3 -L ans,ba,parm,parms,numer`
506 lines
20 KiB
Plaintext
506 lines
20 KiB
Plaintext
/** \page loanhandling Handling loan repayment in GnuCash::Scheduled Transactions
|
|
\sa The original email thread at <https://lists.gnucash.org/pipermail/gnucash-devel/2002-July/006438.html>.
|
|
|
|
July, 2002 - jsled@asynchronous.org
|
|
|
|
API: \ref SchedXaction
|
|
|
|
Bugs 84892 and 84877 detail a request for a new Loan/Mortgage account type,
|
|
and Scheduled Transaction support for loan repayment. While it's debatable
|
|
that a new account type is required, there is definitely a need for Scheduled
|
|
Transaction support for interest/payment computation for a parameterized
|
|
"loan repayment SX".
|
|
|
|
The nature of this support will not create a new top-level account type, but
|
|
instead will result in the following changes:
|
|
a. Support in the SX credit/debit formulas for such calculations.
|
|
b. A Druid to assist in the creation of such SXes.
|
|
[c. budgeting/tool bench support in the future]
|
|
|
|
We define loan repayment values in the following terms:
|
|
|
|
Identifiers:\n
|
|
P : the original principal. This is the overall principal afforded by the
|
|
loan at the time of it's creation.\n
|
|
P' : The beginning principal. This is the principal at the time of entry
|
|
into GnuCash.\n
|
|
I : The interest rate associated with the loan. Note that this may change
|
|
over time [based on an addition to the Prime rate, for instance], at
|
|
various frequencies [yearly, monthly, quarterly...]. Ideally, we can
|
|
use the FreqSpec mechanism to facilitate the interest rate adjustment.\n
|
|
N : The length of the loan in periods.\n
|
|
m : The minimum periodic payment.\n
|
|
n : The current period of the repayment.
|
|
|
|
Functions:\n
|
|
PMT : Total equal periodic payment, as per Gnumeric/Excel's definitions
|
|
[see end for more detail].\n
|
|
IPMT : Monthly payment interest portion, ""\n
|
|
PPMT : Monthly payment principal portion, ""
|
|
|
|
[ NOTE: 'PMT(I,N,P) = IPMT(I, n, N, P) + PPMT(I, n, N, P)' for 0 <= n < N ]
|
|
|
|
|
|
The formula entered into the SX template for a loan may then look like:
|
|
|
|
Example 1:
|
|
\verbatim
|
|
Desc/Memo | Account | Credit | Debit
|
|
----------+-----------------------------+----------------+-------------------
|
|
Repayment | Assets:Bank:Checking | | =PMT(I,n,N,P)
|
|
| | | + fixed_amt
|
|
Interest | Expenses:Loan_Name:Interest | =IPMT(I,n,N,P) |
|
|
PMI | Expenses:Loan_Name:Misc | fixed_amt |
|
|
Principal | Liabilities:Loan_Name | =PPMT(I,n,N,P) |
|
|
-----------------------------------------------------------------------------
|
|
\endverbatim
|
|
|
|
Or, in the case where an escrow account is involved [with thanks to warlord
|
|
for the review and fixes]:
|
|
|
|
Example 2:
|
|
\verbatim
|
|
Desc/Memo | Account | Credit | Debit
|
|
---------------+-----------------------------+----------------+--------------
|
|
Repayment | Assets:Bank:Checking | | =PMT(I,n,N,P)
|
|
| | | + escrow_amt
|
|
| | | + fixed_amt
|
|
| | | + pre_payment
|
|
Escrow | Assets:Loan_Escrow_acct | escrow_amt |
|
|
Interest | Expenses:Loan_Name:Interest | =IPMT(I,n,N,P) |
|
|
PMI | Expenses:Loan_Name:Misc | fixed_amt |
|
|
Principal | Liabilities:Loan_Name | =PPMT(I,n,N,P) |
|
|
| | + pre_payment |
|
|
\endverbatim
|
|
|
|
FreqSpec = 1 month
|
|
\verbatim
|
|
-----------------------------------------------------------------------------
|
|
|
|
Desc/Memo | Account | Credit | Debit
|
|
---------------+-----------------------------+----------------+--------------
|
|
Insurance | Assets:Loan_Escrow_acct | | insurance_amt
|
|
Insurance | Expenses:Home_Insurance | insurance_amt |
|
|
\endverbatim
|
|
|
|
FreqSpec = 1 year
|
|
\verbatim
|
|
-----------------------------------------------------------------------------
|
|
Desc/Memo | Account | Credit | Debit
|
|
---------------+-----------------------------+----------------+--------------
|
|
Taxes | Assets:Loan_Escrow_acct | | taxes_amt
|
|
Taxes | Expenses:Property_Taxes | taxes_amt |
|
|
FreqSpec = Quarterly
|
|
-----------------------------------------------------------------------------
|
|
\endverbatim
|
|
|
|
|
|
\section guidpractical Practical questions regarding the implementation of this facility are:
|
|
|
|
| 1. The transactions as in Example 2 are not going to be scheduled for the\n
|
|
| same day; are their values linked at all / do they need to share the\n
|
|
| same var bindings?
|
|
|
|
Yes, they would want to be linked. More precisely, the insurance/tax amounts
|
|
are very likely linked to the escrow_amt in Ex.2. Unfortunately, these are
|
|
very likely separate SXes...
|
|
|
|
-----
|
|
| 2. How does this effect the SX implementation of variables?
|
|
|
|
Vastly.
|
|
|
|
It becomes clear that multiple SXes will be related. While they'll have
|
|
separate FreqSpecs and template transactions, they'll share some state. For
|
|
both visualization [i.e., the SX list] and processing [credit/debit cell
|
|
value computation] we'll want some manner of dealing with this.
|
|
|
|
It becomes clear as well that the nature of variables and functions needs to
|
|
be more clearly defined with respect to these issues. We probably want to
|
|
institute a clear policy for the scoping of variables. As well, since the
|
|
SXes will have different instantiation dates, we'll need a method and
|
|
implementation for the relation of SXes to each other.
|
|
|
|
A substantial hurdle is that if a set of SXes are [strongly] related, there
|
|
is no-longer a single instantiation date for a set of related SXes. In fact,
|
|
there may be different frequencies of recurrence.
|
|
|
|
One option -- on the surface -- to relate them would be to maintain an
|
|
instance variable-binding frame cache, which would store user-entered and
|
|
computed variable bindings. The first instantiated SX of the set would create
|
|
the frame, and the "last" instance would clean it up. First "last" instance
|
|
is defined by the last-occurring SX in a related set, in a given time range.
|
|
|
|
For example: a loan SX-set is defined by two monthly SXes ["repayment" and
|
|
"insurance"], and a quarterly "tax" SX. The first monthly SX would create a
|
|
frame, which would be passed two the second monthly SX. This would occur for
|
|
the 3 months of interest. The Quarterly SX would get all 3 frames for it's
|
|
creation, and use them in an /appropriate/ [read: to be defined through a lot
|
|
of pain] way. As the time-based dependency relationship between the frames
|
|
plays out, the frame can be removed from the system.
|
|
|
|
Another option is to toss this idea entirely and instead let the user DTRT
|
|
manually.
|
|
|
|
A related option is to add the necessary grouping mechanism to the SX
|
|
storage/data structure: immediately allowing visual grouping of related SXes,
|
|
and potentially allowing a storage place for such frame data in the future
|
|
with less file-versioning headache. This is the option that will be pursued.
|
|
|
|
Another element implicit in the original requirements to support
|
|
loans/repayment calculations is implicit variables. These are symbolic names
|
|
which can be used and are automagically bound to values. The known implicit
|
|
variables to support loan/repayment are:
|
|
|
|
P [loan principal amount], N [loan repayment periods], I [interest], m
|
|
[minimum payment] and n [current period]. Some of these [P, N, I, m] are
|
|
fixed over many instances; some [n] are rebound specific to the instance.
|
|
See the 'variable-scope-frame' below for a method of handling these
|
|
variables.
|
|
|
|
And yet-another element implicit in the original requirement is support for
|
|
detecting and computing the result of functions in the template transaction's
|
|
credit/debit cells. Changes to the src/app-utils/gnc-exp-parser.[hc] and
|
|
src/calculation/expression_parser.[ch] to support functions would be
|
|
necessitated. It is conceivable that after parsing, the parsed expression
|
|
could be passed to scheme for evaluation. Hopefully this would make it
|
|
easier to add support for new functions to the SX code via Scheme.
|
|
|
|
|
|
| 3. How do we deal with periodic [yearly, semi-yearly] updating of various\n
|
|
| "fixed" variables?
|
|
|
|
Another change in the way variables are used is that some SXes -- especially
|
|
loan-repayment -- may involve variables which are not tied to the instance of
|
|
the SX, but rather to variables which:
|
|
- are also involved in another SX
|
|
- change with a frequency different than the SX
|
|
- are represented by a relationship to the outside world ["prime + 1.7"]
|
|
|
|
A partial fix for this problem is to provide multiple levels of scope for
|
|
variable bindings, and expose this to the user by a method of assigning
|
|
[perhaps time-dependent] values to these variables. Variables bound in this
|
|
manner would absolve the user of the need to bind them at SX-creation time.
|
|
|
|
An added benefit of this would be to allow some users [see Bug#85707] have
|
|
"fixed variable" values for a group of SXes.
|
|
|
|
In combination with the SX Grouping, this would provide most of a fix for the
|
|
problem described in #2, above. The variable_frame could be used to provide
|
|
the shared-state between related SXes, without imposing quite the same
|
|
burden. This approach is slightly less flexible, but that allows it to be
|
|
implemented more readily, and understood more easily.
|
|
|
|
A question which comes up when thinking about yearly-changing values such as
|
|
interest rates is if the historical information needs to be versioned. For
|
|
now, we punt on this issue, but hopefully will provide enough of a framework
|
|
for this to be reasonably added in the future.
|
|
|
|
We define four types of variables supported by this scheme:
|
|
|
|
implicit : provided only by the system
|
|
e.g.: 'n', the current index of the repayment
|
|
|
|
transient : have user-defined values, bound at instantiation time.
|
|
e.g.: existing ad-hoc variables in SXes.
|
|
|
|
static : have a user-defined values, and are not expected to change with
|
|
any measurable frequency. The user may change these at their
|
|
leisure, but no facility to assist or encourage this is
|
|
provided.
|
|
e.g.: paycheck amount, loan principal amount
|
|
|
|
periodic : have user-defined values which change at specific points in
|
|
time [July 1, yearly]. After the expiration of a variable value,
|
|
it's re-binding will prevent any dependent SXes from being
|
|
created.
|
|
e.g.: loan tax amount, loan interest rate
|
|
|
|
| 4. From where do we get the dollar amount against which to do the [PI]PMT\n
|
|
| calculation?
|
|
|
|
The user will specify the parameters of the Loan via some UI... then where
|
|
does the data go?
|
|
|
|
- KVP data for that account?
|
|
- KVP data for the SX?
|
|
- Do we have a different top-level "Loan" object?
|
|
- Present only in the SX template transactions/variable-frames?
|
|
|
|
I believe that the only location of the data after Druid creation is in the
|
|
variable-binding frames and the formulae in the template transactions. The
|
|
Druid would thus simply assist the user in creating the following SX-related
|
|
structures:
|
|
|
|
- SXGroup: Loan Repayment
|
|
- variable_frame
|
|
- P [static]
|
|
- N [static]
|
|
- n [implicit]
|
|
- I [periodic]
|
|
- pmi_amount [periodic]
|
|
- tax_amount [periodic]
|
|
- pre_payment [periodic]
|
|
- insurance_amount [periodic]
|
|
- SX: Payment
|
|
- Bank -> { Escrow,
|
|
Liability:Loan:Principal,
|
|
Expense:Loan:Interest,
|
|
Expense:Loan:Insurance }
|
|
- SX: Tax
|
|
- Escrow -> Expense:Tax
|
|
- SX: Insurance
|
|
- Escrow -> Expense:Insurance
|
|
|
|
|
|
/section loansquestions Questions
|
|
|
|
- UI - visible should all this machination be to the user? Should they even
|
|
see them as such. The current SX since-last-run UI makes them pretty
|
|
visible, and in my estimation it actually helps to make them a bit more
|
|
formal and visible. At the same time, it may be overwhelming for the user
|
|
to have to create formal variables with weird types like "implicit",
|
|
"transient", "static", and "periodic".
|
|
|
|
\section loansplan Priorities, Plan
|
|
|
|
The above represents an "ideal" set of extensions to the SX framework to
|
|
enable multiple "enhancement"-level functionalities. Therefore, the
|
|
following is the prioritized schedule, with annotations:
|
|
|
|
-# Functions [PMT, [IP]PMT] in exp_parser; implicit variables [n].
|
|
-# [Visual-only] SX grouping
|
|
-# Loan-repayment creation Druid
|
|
-# SX-only static vars
|
|
-# SX-only periodic vars
|
|
-# SX-group vars, var_frames
|
|
|
|
After the completion of item 4, the feature can safely be called "finished".
|
|
Items 5 and 6 only serve to increase the robustness of the facility and make
|
|
the user's life slightly easier, at the cost of making _my_ life harder. :)
|
|
|
|
|
|
\section loansreference Reference
|
|
|
|
|
|
\subsection loanssoftware Other software:
|
|
|
|
Gnumeric supports the following functions WRT payment calculation:
|
|
|
|
- PMT( rate, nper, pv [, fv, type] )
|
|
PMT returns the amount of payment for a loan based on a constant interest
|
|
rate and constant payments (ea. payment equal).
|
|
@rate : constant interest rate
|
|
@nper : overall number of payments
|
|
@pv : present value
|
|
@fv : future value
|
|
@type : payment type
|
|
- 0 : end of period
|
|
- 1 : beginning of period
|
|
|
|
- IPMT( rate, per, nper, pv, fv, type )
|
|
IPMT calculates the amount of a payment of an annuity going towards
|
|
interest. Formula for IPMT is:
|
|
IPMT(per) = - principal(per-1) * interest_rate
|
|
where:
|
|
principal(per-1) = amount of the remaining principal from last period.
|
|
|
|
- ISPMT( rate, per, nper, pv )
|
|
ISPMT returns the interest paid on a given period.
|
|
If @per < 1 or @per > @nper, returns #NUM! err.
|
|
|
|
- PPMT(rate, per, nper, pv [, fv, type] )
|
|
PPMT calculates the amount of a payment of an annuity going towards
|
|
principal.
|
|
PPMT(per) = PMT - IPMT(per)
|
|
where: PMT is payment
|
|
- IPMT is interest for period per
|
|
|
|
- PV( rate, nper, pmt [, fv, type] )
|
|
Calculates the present value of an investment
|
|
@rate : periodic interest rate
|
|
@nper : number of compounding periods
|
|
@pmt : payment made each period
|
|
@fv : future value
|
|
|
|
/section loanspayment Day Two:
|
|
|
|
As per warlord's comments, the definition of IPMT needs to be updated to
|
|
account for principal pre-payment. IPMT is actually defined by computation
|
|
of the value of an account at a specified point in time. This is significant
|
|
if the loan repayments involve interest.
|
|
|
|
In the face of creating multiple scheduled transactions for a time range, it
|
|
may be the case that the relevant account balance is not actually posted to
|
|
the account at the time of the variable binding. If we intend to show the
|
|
user an estimation of the IPMT cell value during variable binding, then we
|
|
would need to do something creative about this ... but as it stands, we'll
|
|
leave this as an Exercise for the Reader. :)
|
|
|
|
\section loansdruid Druid thoughts...
|
|
|
|
Page Order:
|
|
|
|
Intro ->
|
|
|
|
Params ->
|
|
|
|
Opts ->
|
|
|
|
Repayment ->
|
|
|
|
[Insurance ->]
|
|
|
|
[PMI ->]
|
|
|
|
[Taxes ->]
|
|
|
|
Review/Approval
|
|
|
|
\subsection loansdruidintro Intro
|
|
|
|
"This is a step-by-step method of creating a loan
|
|
repayment setup within GnuCash. In this Druid,
|
|
you can input the parameters of your loan and
|
|
it's repayment and give the details of it's
|
|
payback. Using that information, the appropriate
|
|
Scheduled Transactions will be created.
|
|
|
|
"If you make a mistake or want to make changes
|
|
later, you can edit the created Scheduled
|
|
Transactions directly."
|
|
|
|
\subsection loansdruidparams Params
|
|
|
|
\verbatim
|
|
Principal : [amount entry]
|
|
Actual Principal : [[optional] amount entry]
|
|
Interest Rate : [numeric entry] %
|
|
Type : [ ] Fixed
|
|
[ ] Variable ---------+
|
|
| Type : 10/1,7/1,...|
|
|
| When : [freqspec?] |
|
|
+---------------------+
|
|
Start Date : [Gnome Date Entry]
|
|
Length : [num entry] [years|v]
|
|
Remaining : [num entry]
|
|
\endverbatim
|
|
|
|
\section loansoptions Options
|
|
\verbatim
|
|
Do you...
|
|
[ ] ... utilize an escrow account?
|
|
Account: [ acct select |v]
|
|
[ ] ... pay PMI?
|
|
[ ] Via the Escrow account?
|
|
[ ] ... pay insurance?
|
|
[ ] Via the Escrow account?
|
|
[ ] ... pay taxes?
|
|
[ ] Via the Escrow account?
|
|
[ ] ... have some other expense not listed above?
|
|
[ ] Via the Escrow account?
|
|
\endverbatim
|
|
|
|
\section loansrepayment Repayment
|
|
\verbatim
|
|
Amount : [ amount entry ]
|
|
Assets from : [ account sel |v]
|
|
Princiapl to : [ account sel |v]
|
|
Interest to : [ account sel |v]
|
|
Escrow to : [ account sel |v]
|
|
Remainder to : [{escrow,principal,interest}|v]
|
|
Frequency : +- freqspec ----------------+
|
|
| .... |
|
|
+---------------------------+
|
|
\endverbatim
|
|
|
|
\section loansinsurance Insurance
|
|
\verbataim
|
|
Amount : [ amount entry ]
|
|
Account : [ account sel |v]
|
|
Frequency :
|
|
[ ] Part of Repayment Transaction
|
|
[ ] Other: +- freqspec ----------------+
|
|
| .... |
|
|
+---------------------------+
|
|
\endverbatim
|
|
|
|
\section loanstaxes Taxes/PMI/Other
|
|
|
|
[ same as Insurance ]
|
|
|
|
|
|
|
|
Options in repayment:
|
|
- loan freq != repayment freq
|
|
- floated
|
|
- not
|
|
|
|
- Where does over-payment go?
|
|
- where
|
|
- into the escrow account
|
|
- directly applied
|
|
- how
|
|
- towards principal [interest is then re-calculated]
|
|
- towards interest [principal is then re-calculated]
|
|
|
|
- still to do...
|
|
- expression parser/gnc-exp-parser extensions to handle...
|
|
- ...symbols [account names] into functions
|
|
- ...errors better
|
|
- ...iter/count/implicit vars
|
|
- druid...
|
|
- add ipmt', ppmt' calculations, using above
|
|
- kvp storage of "real" data
|
|
- sx grouping
|
|
|
|
http://www.interest.com/hugh/calc/mort_links.html
|
|
|
|
\section loansfeedback Druid Feedback:
|
|
|
|
\verbatim
|
|
<Wilddev> jsled: <auspex> Wilddev: The labels need colons, mnemonics, and right-alignment.
|
|
<Wilddev> <auspex> Wilddev: It may be worthwhile for gnucash to create GtkSpinButton subclasses which show the percent symbol and others within the field.
|
|
<Wilddev> <auspex> Wilddev: I don't know how complicated that will be.
|
|
<Wilddev> <Wilddev> me either :P
|
|
<Wilddev> <auspex> Wilddev: The strings need review, but there may be other changes to make first.
|
|
<Wilddev> <auspex> Wilddev: "Interest Rate Change Frequency" should perhaps be on the next page?
|
|
<Wilddev> jsled: I dont know if you did another page for this, but shouldn't there be a field for ballon amount too?
|
|
<jsled> Excellent feedback; thanks. I don't presently handle balloon payments; how do they work?
|
|
<Wilddev> I think, from what I've read before, the are an amount you pay at the end of the loan to close it
|
|
<jsled> gnc-account-sel == combo box account selection with pull-down account list [like the register] and auto-completion [hopefully]
|
|
|
|
<Wilddev> <auspex> Is "Length" the length of a period, or the sum of the periods?
|
|
<jsled> The sum of all periods; the length of the loan.
|
|
<Wilddev> he's suggesting to think of a better label for that
|
|
<Wilddev> ah I thought it was the period between loan transactions
|
|
<jsled> Hmm. Okay. The between-transaction period is a frequency editor on the Repayment page.
|
|
<Wilddev> <auspex> I'm wondering if "Original Principal" should be a vulgate
|
|
such as "Loan Amount"
|
|
\endverbatim
|
|
|
|
|
|
\section loansexpression Expression changes, round 2
|
|
|
|
We need the following abilities in order to get mortgage/loan repayment
|
|
working:
|
|
- Ability to get the original value of an account
|
|
- [perhaps, ability to reference an external value?]
|
|
- Ability to get the present value of an account
|
|
- Ability to get the current i in an "i-of-N" sequence
|
|
|
|
As well, it'd be nice to have:
|
|
- some sort of signature checking on functions in expressions
|
|
- safe[r] error handling?
|
|
|
|
We decide that the original/present value of the account should be handled in
|
|
scheme, and thus we actually need a way to reference accounts down to the
|
|
scheme expressions. We decide to use the Quote symbols to refer to a string
|
|
literal. The expression parser should be modified to parse this.
|
|
|
|
The current 'i' and 'N' are going to be handled by having a list of
|
|
predefined variables which the user cannot have access to. For the time
|
|
being, this is 'i' and 'N'.
|
|
|
|
*/
|