def amortize(rate, nper, pv, freq="M"):
    """Construct an amortization schedule for a fixed-rate loan.

    Rate -> annualized input

    Example
    -------
    # a 6.75% $200,000 loan, 30-year tenor, payments due monthly
    # view the 5 final months
    print(amortize(rate=.0675, nper=30, pv=200000).round(2).tail())
         beg_bal     prin  interest  end_bal
    356  6377.95 -1261.32    -35.88  5116.63
    357  5116.63 -1268.42    -28.78  3848.22
    358  3848.22 -1275.55    -21.65  2572.67
    359  2572.67 -1282.72    -14.47  1289.94
    360  1289.94 -1289.94     -7.26    -0.00
    """

    freq = utils.get_anlz_factor(freq)
    rate = rate / freq
    nper = nper * freq

    periods = np.arange(1, nper + 1, dtype=int)

    principal = np.ppmt(rate, periods, nper, pv)
    interest = np.ipmt(rate, periods, nper, pv)
    pmt = np.pmt(rate, nper, pv)

    def balance(pv, rate, nper, pmt):
        dfac = (1 + rate) ** nper
        return pv * dfac - pmt * (dfac - 1) / rate

    res = pd.DataFrame(
        {
            "beg_bal": balance(pv, rate, periods - 1, -pmt),
            "prin": principal,
            "interest": interest,
            "end_bal": balance(pv, rate, periods, -pmt),
        },
        index=periods,
    )["beg_bal", "prin", "interest", "end_bal"]
    return res