mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-12-02 05:29:20 -06:00
83d14e1c1c
It is split into - /libgnucash (for the non-gui bits) - /gnucash (for the gui) - /common (misc source files used by both) - /bindings (currently only holds python bindings) This is the first step in restructuring the code. It will need much more fine tuning later on.
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 <http://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 Excercise 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 baloon 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'.
|
|
|
|
*/
|