Python 循环中的偏移量
Python offset in loop
我有一段代码可以计算贷款的摊销情况,并允许违约(cdr = 固定违约率)和预付款(cpr = 固定预付率)。
我也想包括回收款,但这些回收款应该在未来一段时间内收到。在下面的示例中,我应用了 3% 的 cdr,我希望在六个月后收回 60% 的违约贷款余额。
我正在努力解决这个问题,因为在每个循环中它都需要回顾上一个时期。
解决这个问题的方法是首先创建一个没有恢复的 table / 数据框,然后在第二阶段通过在列恢复中添加 60% 的默认值来应用恢复,抵消 6 个月。
不过我希望在 amortize 函数中有更好/更简洁的方法。
如有任何帮助,我们将不胜感激。
import pandas as pd
import numpy as np
from datetime import date
from collections import OrderedDict
from dateutil.relativedelta import *
pd.options.display.float_format = '{:,.2f}'.format
def amortize(principal, int_rate,periods, cpr, cdr, date, recovery_rate, recovery_timing):
p = 0
beg_balance = principal
end_balance = principal
while end_balance > 1:
default = round((1-(1-cdr/100)**(1/12)) * beg_balance,2)
interest = round((int_rate/12)*max(beg_balance-default,0),2)
if p < periods:
pmt = -round(np.pmt(int_rate/12, periods -p,
beg_balance - default),2)
else:
pmt = 0
principal = pmt - interest
prepay = round((1-(1-cpr/100)**(1/12)) * (beg_balance - principal),2)
end_balance = max(beg_balance - principal - prepay - default,0)
recovery = default * recovery_rate/100
total_cash = pmt + prepay + recovery #plus a recovery lag
yield OrderedDict([('Period',p+1),
('Month', date),
('Begin_Bal', beg_balance),
('Default',default),
('Sched Princ',principal),
('Prepay Princ',prepay),
('Interest',interest),
('Recovery',recovery),
('Total CF',total_cash),
('End Balance', end_balance)])
p += 1
date += relativedelta(months=1)
beg_balance = end_balance
table = amortize(300000,0.03,360,10,3,date(2017,12,11),60,6)
pd.DataFrame(table).head()
您的解决方案听起来很干净。您还可以使用 defaults.append(..)
创建一个过去的默认值列表,然后参考 defaults[-6]
如果贷款期限很长,可以使用固定容量为6的collections.deque
代替列表,避免保留过多的旧计算。
我有一段代码可以计算贷款的摊销情况,并允许违约(cdr = 固定违约率)和预付款(cpr = 固定预付率)。
我也想包括回收款,但这些回收款应该在未来一段时间内收到。在下面的示例中,我应用了 3% 的 cdr,我希望在六个月后收回 60% 的违约贷款余额。 我正在努力解决这个问题,因为在每个循环中它都需要回顾上一个时期。
解决这个问题的方法是首先创建一个没有恢复的 table / 数据框,然后在第二阶段通过在列恢复中添加 60% 的默认值来应用恢复,抵消 6 个月。
不过我希望在 amortize 函数中有更好/更简洁的方法。
如有任何帮助,我们将不胜感激。
import pandas as pd
import numpy as np
from datetime import date
from collections import OrderedDict
from dateutil.relativedelta import *
pd.options.display.float_format = '{:,.2f}'.format
def amortize(principal, int_rate,periods, cpr, cdr, date, recovery_rate, recovery_timing):
p = 0
beg_balance = principal
end_balance = principal
while end_balance > 1:
default = round((1-(1-cdr/100)**(1/12)) * beg_balance,2)
interest = round((int_rate/12)*max(beg_balance-default,0),2)
if p < periods:
pmt = -round(np.pmt(int_rate/12, periods -p,
beg_balance - default),2)
else:
pmt = 0
principal = pmt - interest
prepay = round((1-(1-cpr/100)**(1/12)) * (beg_balance - principal),2)
end_balance = max(beg_balance - principal - prepay - default,0)
recovery = default * recovery_rate/100
total_cash = pmt + prepay + recovery #plus a recovery lag
yield OrderedDict([('Period',p+1),
('Month', date),
('Begin_Bal', beg_balance),
('Default',default),
('Sched Princ',principal),
('Prepay Princ',prepay),
('Interest',interest),
('Recovery',recovery),
('Total CF',total_cash),
('End Balance', end_balance)])
p += 1
date += relativedelta(months=1)
beg_balance = end_balance
table = amortize(300000,0.03,360,10,3,date(2017,12,11),60,6)
pd.DataFrame(table).head()
您的解决方案听起来很干净。您还可以使用 defaults.append(..)
创建一个过去的默认值列表,然后参考 defaults[-6]
如果贷款期限很长,可以使用固定容量为6的collections.deque
代替列表,避免保留过多的旧计算。