Financial optimization with compound interest rate

financeoptimization

Suppose that I have $P$ amount of money in a bank that accrues fixed interest rate $\bar{r}$ continuously. This interest rate charged on this bank account is simple, instead of compound interest rate.

Now, I can transfer the interest accrued after time $t$, $\bar{r}Pt$, to another bank account that collects compound interest rate with the same interest rate $\bar{r}$. However, I can only transfer the interest earned from the first bank account, instead of transferring the whole $P$. Every time I transfer the interest from the first bank account to second bank account, I incur a fixed cost $\phi$. I can transfer the accrued interest from the first bank to the second bank at any time $t$, and for as many times as I want to.

Q: What is the optimal strategy function $f$ that takes in $(P,\bar{r}, \phi, T)$ and tells me when I should transfer the interest accrued from the first bank to the second bank to maximize my income at time $T$, starting from time $t = 0$? Is there even a closed form solution to this problem?

This is motivated by a real-world example I witnessed, and wanted to know how I can tackle this question. It seems that I need to wait for an ample amount of time for the interest collected to be high enough that I would profit from moving to the second bank despite the fixed cost $\phi$. If I wait too long, then I may miss out on the opportunity that interest collected could have earned more compound interest.

EDIT: Note that there is a finite amount of time, since a comment suggested that there is no solution given infinite amount of time.

Best Answer

Let's say that you have the principal of $P=1$ at the first bank and $r=1$ (amount and time scaling is trivial) and transfer at the time moments $t_1<\dots<t_n<T$. Then your gain compared to doing nothing is (we set $t_0=0$) $$ \sum_{j=1}^n (t_j-t_{j-1})[e^{T-t_j}-1]-\varphi n=e^T\sum_{j=1}^n(t_j-t_{j-1})e^{-t_j}-t_n-\varphi n\,. $$ For fixed $n$ and $t_n$, we can now fix $t_{j-1}, t_{j+1}$ and look at $t_j$. This leads to the maximization problem $(s-t)e^{-s}+te^{-t}\to\max$, $0\le t\le s$. Differentiation yields $-e^{-s}+e^{-t}-te^{-t}=0$, so $t=1-e^{-(s-t)}$. This gives the relation $\Delta_{j+1}=\log \frac1{1-\Delta_j}$ between $\Delta_j=t_{j}-t_{j-1}$. Thus we reduced the problem to a two-parameter one. We need to choose an integer $n$ and the initial $\Delta=\Delta_1$ and then run this recursive sequence and compute and maximize the result $F_n(\Delta)$ in $n$ and $\Delta$ in the admissible range.

Thus it is clear that the closed form expression is out of question, but the programming is relatively easy. It looks like for each $n$, $F_n$ is unimodal in $\Delta$ in its domain and the maximum of $F_n$ is a unimodal function of $n$. If so, the computation of the maximum can be done rather simply and efficiently, but I'll not attempt to prove these properties now.

Here is a code in Asymptote (the syntax is almost the same as C but somewhat more flexible and it allows you to draw pictures easily, so I use it most of the time). It outputs the optimal schedule and the gain from each transaction as well as the total gain.

import graph;
size(300,300,IgnoreAspect);

real 
rate=0.03,       // your annual rate r 
Tyears=30,       // your time period in years
penalty=100,     //transfer fee 
principal=10000;  //the principal P

real T=Tyears*rate, phi=penalty/principal;

real f(int n,real d, bool b=false)
{
real s=0;
real dl=d, t=0;
for(int k=0;k<n;++k)
{
t+=dl; s+=dl*exp(-t); if(b) write(t/rate, ((exp(T-t)-1)*dl-phi)*principal);
if((k<n-1 && dl>=1)||t>T) {s=0; break;}
else if(k<n-1) dl=-log(1-dl);
}
if(b) write("total gain="+string((exp(T)*s-t-phi*n)*principal));
return max(exp(T)*s-t,0)-phi*n;

}

real[] F(int n)
{
real[] q;

real u=0,v=0.0001,w=1; 
real M=f(n,v);
for(int k=0;k<30;++k)
{
real uv=(u+v)/2, vw=(v+w)/2;
real M1=f(n,uv); 
if(M1>M) {M=M1; w=v;v=uv;} else
{
real M2=f(n,vw);
if(M2>M) {M=M2; u=v;v=vw;} else
{u=uv; w=vw;}
}
}
q[0]=v; q[1]=f(n,v);
return q;
}
 
real M=0,d;
int N;

for(int n=1;n<100;++n) 
{
real g(real x){return f(n,x);}
//draw(graph(g,0,1));
real[] q=F(n);
//dot((q[0],q[1]),red);
//write(n,q[0],q[1]);
if(q[1]>M){N=n; M=q[1]; d=q[0];}
}
write("schedule "+string(N));
f(N,d,true);

pause();