Exemple #1
0
def olb_r(loan: float, q: float, period: float, gr: Union[Accumulation, float,
                                                          Rate], t) -> float:
    """
    Calculates the outstanding loan balance using the retrospective method.

    :param loan: The loan amount.
    :type loan: float
    :param q: The payment amount.
    :type q: float
    :param period: The payment period.
    :type period: float
    :param gr: A growth rate object.
    :type gr: Accumulation, float, or Rate
    :param t: The valuation time.
    :type t: float
    :return: The outstanding loan balance.
    :rtype: float
    """

    ann = Annuity(period=period, term=t, gr=gr, amount=q)

    acc = Accumulation(gr=gr)
    olb = loan * acc.val(t) - ann.sv()

    return max(olb, 0)
Exemple #2
0
def olb_p(q: float,
          period: float,
          term: float,
          gr: Union[Accumulation, float, Rate],
          t: float,
          r: float = None,
          missed: list = None) -> float:
    """
    Calculates the outstanding loan balance using the retrospective method.

    :param q: The payment amount.
    :type q: float
    :param period: The payment period.
    :type period: float
    :param term: The loan term, in years.
    :type term: float
    :param gr: A growth rate object.
    :type gr: Accumulation, float, or Rate.
    :param t: The valuation time, in years.
    :type t: float
    :param r: The final payment amount, if different from the others, defaults to None.
    :type r: float, optional
    :param missed: A list of missed payments, for example, 4th and 5th payments would be [4, 5].
    :type missed: list
    :return: The outstanding loan balance.
    :rtype: float
    """
    acc = Accumulation(gr=gr)

    if r is not None:
        ann = Annuity(period=period, term=term - t - period, gr=gr, amount=q)

        r_pv = r * acc.discount_func(term - t)

        olb = ann.pv() + r_pv

    else:
        ann = Annuity(period=min(period, term - t),
                      term=term - t,
                      gr=gr,
                      amount=q)

        olb = ann.pv()

    if missed:

        for p in missed:
            olb += q * acc.val(t - p)

    return olb
Exemple #3
0
def get_loan_pmt(loan_amt: float,
                 period: float,
                 term: float,
                 gr: Union[float, Rate, TieredTime],
                 imd: str = 'immediate',
                 gprog: float = 0.0,
                 aprog: float = 0.0,
                 cents=False) -> dict:
    """
    Returns the loan payment schedule, given a loan amount, payment period, term, growth rate, and geometric or
    arithmetic progression of payments. If cents is set to True, uses the Daniel and Vaaler rounding algorithm
    to round each payment to cents, modifying the final payment such that there is no over/under payment of the
    loan due to rounding issues.

    :param loan_amt: The loan amount to be repaid.
    :type loan_amt: float
    :param period: The payment frequency, per fraction of a year.
    :type period: float
    :param term: The term of the loan, in years.
    :type term: float
    :param gr: Some kind of growth rate object specifying the interest rate
    :type gr: Accumulation, Callable, float, Rate
    :param imd: 'immediate' or 'due'. Whether the payments occur at the end or beginning of each period, defaults to \
    'immediate'.
    :type imd: str
    :param gprog: geometric progression, payments grow at a % of the previous payment per period, defaults to 0.
    :type gprog: float
    :param aprog: arithmetic progression, payments grow by a constant amount each period, defaults to 0.
    :type aprog: float
    :param cents: Whether you want payments rounded to cents.
    :type cents: bool
    :return: a dictionary of payment amounts along with the times of the payments
    :rtype: dict
    """
    ann = Annuity(period=period, term=term, gr=gr, gprog=gprog, imd=imd)

    if aprog >= 0:
        i = ann.gr.effective_interval(t2=ann.period)
        n = ann.n_payments
        v = ann.gr.discount_func(period)
        pmt = (loan_amt - (aprog / i) * (ann.pv() - n * v**n)) / (ann.pv())
        iann = Annuity(amount=pmt,
                       period=period,
                       term=term,
                       gr=gr,
                       aprog=aprog,
                       imd=imd)
        pmts = iann.amounts
    else:
        pmt = loan_amt / ann.pv()
        pmts = [pmt * x for x in ann.amounts]

    times = ann.times

    pmts_dict = {'times': times, 'amounts': pmts}

    if cents:

        acc = Accumulation(gr=gr)

        pmt_round = round(pmt, 2)

        pv = Annuity(amount=pmt_round,
                     period=period,
                     term=term,
                     gr=gr,
                     gprog=gprog,
                     imd=imd).pv()

        if loan_amt == round(pv, 2):

            return pmts_dict

        else:

            cent = decimal.Decimal('0.01')

            pmt_round2 = float(
                decimal.Decimal(pmt).quantize(cent, rounding=decimal.ROUND_UP))

            d_ann = Annuity(amount=pmt_round2,
                            period=period,
                            term=term,
                            gr=gr,
                            gprog=gprog,
                            aprog=aprog,
                            imd=imd)

            diff = d_ann.pv() - loan_amt

            last_pmt = round(
                d_ann.amounts[-1] - round(diff * acc.val(t=term), 2), 2)

            pmts = [round(x, 2) for x in d_ann.amounts[:-1]]
            pmts.append(last_pmt)

            pmts_dict = {'times': times, 'amounts': pmts}

    return pmts_dict