Pulp Programming

less of a cathedral, more of a bazaar

Derivation of Annuity Formulas (Discrete Compound Interest)

published: 26 Jun 2013

I've found out today an elegant and intuitive approach to derive equations of present and future values for $n$ annuity payments ($pv_{n}, fv_{n}$). It doesn't require much algebraic manipulation and its quite easy to visualize.

So here is the small reference and an opportunity for me to try MatJax.js, JavaScript library for writing LaTeX formulas in HTML :).

Let's imagine two infinitely long payment cash flows linearly in time. The first cash flow starts at point in time $1$ ($PIT_{1}$) and the second starts at point in time $n+1$ ($PIT_{2}$). Here is what they might look like:

     -------| cash-flow1 |------->

pmt(1)    pmt(2)     pmt(N)    pmt(n+1)   pmt(n+2)  pmt(Inf)
|---------|---------|----------|----------|----------|---------|
PIT: 0         1         2    ...   n         n+1        n+2  ...  Inf

-------| cash-flow2 |------>
pmt(1)     pmt(2)    pmt(Inf)
|---------|---------|----------|----------|----------|---------|
PIT: 0         1         2    ...   n         n+1        n+2  ...  Inf


Where pmt(1), pmt(2), ... etc. are obviously payments at time 1, 2, ... etc, and we assume that all payments are equal to each other (i.e. pmt(1) = pmt(2) = ... = pmt(Inf) = pmt).

Once derivation is done, it will be enough to keep this image in our mind in order to derive the $pv_{n}$ and $fv_{n}$ formulas at any time. No need to remember long sequences of algebraic calculations any more. Just one infinite time axis with two distinct cash flows, one starting $n+1$ time units after the other (it can't be much easier than that :)).

In order to obtain present value of the money we need to discount its future value with an interest rate $r$. Thus, the present values on cash-flow1 at $PIT_{0}$ for payments pmt(1), pmt(2), ..., pmt(n), ..., pmt($\infty$) will be equal to: $$pv_{1} = \frac{pmt}{(1+r)}, pv_{2} = \frac{pmt}{(1+r)^2}, ..., pv_{n} = \frac{pmt}{(1+r)^n}, ..., pv_{\infty} = \frac{pmt}{(1+r)^{\infty}}$$ respectively. So the sum of all present value payments on cash-flow1 will be: $$pv_{cash-flow1} = \Sigma_{i=1}^{\infty} pv(i) = \Sigma_{i=1}^{\infty} \frac{pmt}{(1+r)^i} = pmt * \Sigma_{i=1}^{\infty} \frac{1}{(1+r)^i}.$$ Note that the present values at $PIT_{n}$ in cash-flow2 are equal exactly to the present values in cash-flow1 at $PIT_{0}$. So in order to obtain present values at $PIT_{0}$ in cash-flow2 we need to additionally discount all present values at $PIT_{n}$ on this timeline with $\frac{1}{(1+r)^n}$ discount factor. If we do this the sum of all present values on in cash-flow2 will be: $$pv_{cash-flow2} = pv_{cash-flow1} * \frac{1}{(1+r)^n}.$$ Now we have formulas with lots of summation terms (for infinite number of future payments), so we need something simpler, shorter and more handy in order to calculate $pv_{n}$ and $fv_{n}$ values for $n$ future payments. In order to get there we need to know a little bit about, so called, geometric progressions. Let's see what they are.

Geometric progression of A (where A is constant less than 1) can be defined as follows: $$S = \Sigma_{i=1}^{\infty} A^i$$ It is easy to see that $$S = \frac{A}{1-A},$$ we multiply $S$ with $A$ so that $A*S = \Sigma_{i=1}^{\infty} A^{i+1}$ and when substract $S*A$ from $S$ we get $S - S*A = A$, and indeed $S = \frac{A}{1-A}$.

If we apply this cute trick to the summation term of $pv_{cash-flow1}$ we can simplify it significantly: $$pv_{cash-flow1} = pmt * \Sigma_{i=1}^{\infty} \frac{1}{(1+r)^i} = pmt * \frac{\frac{1}{(1+r)}}{1 - \frac{1}{(1+r)}} = \frac{pmt}{r}.$$ So $pv_{cash-flow2}$ becomes: $$pv_{cash-flow2} = \frac{pmt}{r} * \frac{1}{(1+r)^n}.$$ Here comes the critical part. We managed to get rid of infinite summations (geometric progressions), so we have nice simple formulas of present values for two infinite payment streams. But we need the present value for $n$ future payments. How to compute this with the given equations? Very simple. Note that it is a difference between the two present values of our cash flows. We need to substract $pv_{cash-flow2}$ from $pv_{cash-flow1}$: $$pv_{n} = pv_{cash-flow1} - pv_{cash-flow2} = \frac{pmt}{r} - \frac{pmt}{r}*\frac{1}{(1+r)^n} \\ = pmt * \left(\frac{1}{r} - \frac{1}{r*(1+r)^n} \right).$$ Voila! There it is, our first equation. The second equation (for future value of $n$ annuities - $fv_{n}$) can be obtained from the first ($pv_{n}$) even more easily. It is present value of $n$ annuities compounded to $n$ periods. So: $$fv_{n} = pv_{n} * (1+r)^n = pmt * \left(\frac{1}{r} - \frac{1}{r*(1+r)^n} \right) * (1+r)^n \\ = pmt * \left( \frac{(1+r)^n}{r} - \frac{1}{r} \right).$$ The original source for this derivation can be found here.

Parsing Gem Versions With Awk

published: 28 Apr 2013

I installed latest Ruby (2.0.0-p0) today and along with it the smallest gem versions from the previous Ruby (2.0.0-rc1). Here is awk one-liner that helped me do that.

chruby 2.0.0-rc1

gem list | \
awk '{ gsub(/$|$/, ""); line = line " -v=" $NF " "$1; } \
END  { print line; }' > gems-versions

chruby ruby-2.0.0-p0
gem install cat gems-versions


First, I switched to ruby-2.0.0-rc1 with 'chruby' in order to make a list of available gems. Then, in order to parse the list of gems I piped it to the awk command. Here is what it does:

• Removes parenthesis that enclose gem versions in each line with gsub(/$|$/, "").
• Concatenates gem version with its name in a single line in the form that the gem install command understands (i.e -v=<gem-version> <gem-name>) with line=line " -v="$NF" "$1. $NF and$1 denote the gem's version number and name respectively.
• Prints the concatenated line in the 'gems-versions' file at the end.

After I created the list of gems I switched to ruby-2.0.0-p0 and installed gems with: gem install cat gems-versions.

It is easy to adjust this to the similar use cases. If we want, for instance, to install all gem versions that are already present in the previous Ruby version the awk that will parse all gem versions will look something like this:

chruby ruby-2.0.0-p0

gem list | \
awk '{ gsub(/\)/,""); gsub(/\(|,\s/, " " $1":"); \$1=""; line = line " " $0} END { print line }' > gems-versions chruby ruby-2.0.0-p0 gem install cat gems-versions  Everything is almost the same as in the previous case except there are a couple of extra awk commands to add. • gsub(/)/,""); gsub(/(|,\s/, " "$1":") replaces string xgem (2.0, 1.0) with xgem xgem:2.0 xgem:1.0
• $1="" sets the first field (a gem name) to the empty string so the output string becomes gem_x:1.0 gem_x:2.0 which should be valid input for the gem install command. • line = line " "$0 concatenates the output string \$0 to the line variable which will be saved to the gems-versions file.

Automount With Udisks in Arch Linux

published: 27 Jan 2013

When it became obvious that systemd was going to replace sysvinit and init scripts I switched to systemd and experienced several issues in the process. One of those was that the system couldn't automount usb drives any more.

Before the transition I used devmon which was started in .xinitrc before windows manager with ck-launch-session bash -c "devmon & ..." command and it worked seamlessly. However, after the upgrade the devmon was broken. No matter whether it was issued manually in terminal or from the .xinitrc script, it reported the following error:

Poll for media failed: Not Authorized
device: [/dev/sdb1]
...
mountdev /dev/sdb1 DNC vfat
devmon: mount /dev/sdb1 --mount-options noexec,nosuid,noatime    (DNC)
Mount failed: Not Authorized
devmon: error mounting /dev/sdb1 (0)
...
udisks functions are not authorized through policykit,
so devmon cannot automount drives.
...


I also tried udiskie, another automatic disk mounter that uses udisks, and it failed to mount disk with the similar message:

attempting to mount device /org/freedesktop/UDisks/devices/sdb1 (vfat:[])
failed to mount device /org/freedesktop/UDisks/devices/sdb1:
org.freedesktop.UDisks.Error.PermissionDenied: Not Authorized


Obviously the problem was not devmon, nor udiskie. Somehow udisks functions were no longer authorized through policykit... It was clear that I should famialirize myself with polkit and find out how to authorize udisks actions.

From polkit(8) manpages I learned that in order to authorize disk mounting I should write polkit rule. These rules are placed in /etc/polkit-1/rules.d/ and /usr/share/polkit-1/rules.d/ directories in files with .rules extension. Both directories are monitored by polkitd process. If rule is changed, added or removed all rules are processed again.

So I added /etc/polkit-1/rules.d/10-udisks-automount.rules file with the following rule:

polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.udisks.filesystem-mount" &&
subject.isInGroup("storage")) {
return polkit.Result.YES;
}
});


Basically it says that udisks mount action should be allowed to the users in the storage group. Values for action.id as well as other information about polkit authorization policies can be found in /usr/share/polkit-1/actions directory. Particularly, the policy for the udisks is placed in org.freedesktop.udisks.policy file. All rules are written in JavaScript.

After I'd added this rule, devmon and udiskie started to work as expected so I haven't searched further. For that reason I suppose that what I've presented here is probably quick and dirty solution. It should serve just as a remainder to me in the future and it might also help someone with the similar problem. More comprehensive coverage of udev, udisks and polkit can be found on the Arch wiki pages for udev and with man polkit(8).