#!/usr/local/bin/python3

from math import exp, log

class Transactions:
    def __init__(self):
        self.amounts = []
        self.times = []
    
    def add(self, amount, time):
        self.amounts.append(amount)
        self.times.append(time)

def jns_irr(transactions):
    have_pos, have_neg = False, False
    
    for amount in transactions.amounts:
        if amount > 0.0:
            have_pos = True
        elif amount < 0.0:
            have_neg = True

    if have_neg and have_pos:
        u, converged, iterations, epsilon = 0.0, False, 100, 1.0e-8
        
        for i in range(iterations):
            pos, d_pos, neg, d_neg = 0.0, 0.0, 0.0, 0.0
            
            for j in range(len(transactions.amounts)):
                an_amount, a_time = transactions.amounts[j], transactions.times[j]
                tmp = an_amount * exp(u * a_time)
            
                if an_amount > 0.0:
                    pos += tmp
                    d_pos += tmp * a_time
                else:
                    neg -= tmp;
                    d_neg -= tmp * a_time

            delta = log(neg / pos) / (d_neg / neg - d_pos / pos)
            u -= delta
            if abs(delta) < epsilon:
                converged = True
                break
        if converged:
            result = -u
        else:
            result = 'No convergence'
    else:
        result = 'Bad Data!'
    
    return result
    
if __name__ == "__main__":
    import sys
    amounts = [-1000.00, 500.00, -2000.00, 1500.00, -2000.00, 4000.00]
    times = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
    ts = Transactions()
    for i in range(len(amounts)):
        ts.add(amounts[i], times[i])
    irr = jns_irr(ts)
    print('The internal rate of return is {0:.2f}%.'.format(100 * irr))

# Test Ouput:
# The internal rate of return is 10.16%.