code: def amortize(rate, nper, pv, freq="M"):
      
  
      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
docs: 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