Skip to content

Commit

Permalink
add compound solver, tiered investment accouunts
Browse files Browse the repository at this point in the history
  • Loading branch information
genedan committed Jul 28, 2020
1 parent a8d2628 commit 2462809
Showing 1 changed file with 133 additions and 2 deletions.
135 changes: 133 additions & 2 deletions tmval/growth.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import datetime as dt
import numpy as np

from typing import Callable

Expand Down Expand Up @@ -53,12 +54,32 @@ def effective_rate(
)
return effective_rate

def discount_interval(
self,
t1,
t2
):

discount_rate = (self.val(t=t2) - self.val(t=t1)) / self.val(t=t2)
return discount_rate

def effective_discount(
self,
n
):
t1 = n - 1
t2 = n
effective_discount = self.discount_interval(
t1=t1,
t2=t2
)
return effective_discount

def get_accumulation(self):
k = self.k
amt_func = self.func

def acc_func(t):
return amt_func(t, k) / k
return amt_func(k=1, t=t)

accumulation = Accumulation(f=acc_func)
return accumulation
Expand Down Expand Up @@ -225,3 +246,113 @@ def __init__(

def acc_func(self, t):
return (1 + self.interest_rate) ** t


def compound_solver(pv=None, fv=None, i=None, t=None):

args = [pv, fv, i, t]
if args.count(None) > 1:
raise Exception("Only one argument can be missing.")

if pv is None:
res = fv / ((1 + i) ** t)
elif fv is None:
res = pv * ((1 + i) ** t)
elif i is None:
res = ((fv / pv) ** (1 / t)) - 1
else:
res = np.log(fv / pv) / np.log(1 + i)

return res


class TieredBal:
"""
Tiered investment account
"""
def __init__(
self,
tiers: list,
rates: list
):
self.tiers = tiers
self.rates = rates

def __call__(
self,
k: float,
t: float
):
# determine jump balances and rates
jump_balances = [i for i in self.tiers if i > k]
if len(jump_balances) == 0:
jump_rates = []
else:
jump_rates = self.rates[:len(self.rates) - 1]
jump_rates = jump_rates[-len(jump_balances):]

# determine jump times
jump_times = []
pv = k
t_base = 0
for fv, i in zip(jump_balances, jump_rates):
jump_increment = compound_solver(pv=pv, fv=fv, i=i)
jump_times.append(t_base + jump_increment)
t_base = t_base + jump_increment
pv = fv

# find applicable tiers
jump_times.insert(0, 0)
jump_rates = self.rates[-len(jump_times):]
jump_tiers = self.tiers[-len(jump_times):]

# construct growth function and calculate balance
index = len([i for i in jump_times if i <= t]) - 1
lower_t = jump_times[index]
base_amt = max(jump_tiers[index], k)
rate = jump_rates[index]
time = t - lower_t

bal = base_amt * ((1 + rate) ** time)

return bal


class TieredTime:
"""
Tiered time investment account. Interest varies with time.
"""

def __init__(
self,
tiers: list,
rates: list
):
self.tiers = tiers
self.rates = rates

def __call__(
self,
k: float,
t: float
):
# find the cumulative tiers that apply at time t
jump_times = np.cumsum(self.tiers)
jump_times = [i for i in jump_times if i < t]

rates = self.rates[:len(jump_times)]
times = self.tiers[:len(jump_times)]
times.pop(0)
times.append(t - max(jump_times))

# for each tier that applies, calculate the cumulative balance
bal = k
for rate, time in zip(rates, times):
bal = bal * ((1 + rate) ** time)

return bal


def k_solver(f: Callable, fv=None, t=None):
res = fv / f(t)
return res

0 comments on commit 2462809

Please sign in to comment.