根据加权平均标准优化贷款组合

时间:2017-05-30 21:55:09

标签: optimization linear-programming solver pulp mixed-integer-programming

编辑:我意识到我之前尝试描述问题的方法并不是很有帮助,实际上并没有真正模拟我目前正在做的事情,所以我已经改写了帖子。我已经包含了我的工作代码。我将使用的示例中的数据是贷款俱乐部贷款数据(csv格式),可以从这里下载:https://www.kaggle.com/wendykan/lending-club-loan-data

我目前正在python中使用PuLP和pandas来解决我目前的优化问题。我对线性编程很陌生,最近利用它来解决最小化成本问题的问题。

对于这个借贷俱乐部的例子,假设我有10万美元。鉴于贷款俱乐部贷款是证券化的并且可以由个人投资,我想分发10万美元,以便:

1。投资100,000美元的加权平均利率不能低于8%。

2。投资100,000美元的加权平均债务与收入比率不能超过10

暂时忽略 3。为了尽量减少任何一笔贷款的风险,平均贷款额度为     优化的投资组合不能超过10,000美元。)

我难以实施约束3以及我的投资上限为100,000美元的限制。对于约束1& 2,我按贷款规模加权贷款,并按权重乘以利率和债务收入比率,从而可以线性方式对这些约束进行建模,以便:

Sum of weighted interest rates => 0.08
Sum of weighted debt-income ratios <= 10 

购买的最终贷款组合不需要等于100,000美元。目标函数是在约束条件下达到接近100,000,即LpMaximise。

我选择将贷款选择模型化为二元变量,因为我只想知道它们是否存在。此外,为了速度和记忆,我从数据中选择了50行的切片。

这是我的代码:

import pandas as pd
from pulp import *
import numpy as np



df = pd.read_csv('~/Desktop/loan.csv')
df.columns = [c.replace(' ','') for c in df.columns]

#cleaning up the data to get rid of spaces and to standardise percentage data

df.loc[:,'id'] = df.loc[:,'id'].astype(int)
df['int_rate'] = df['int_rate']/100     #convert interest rate to ratios.

#slicing the data to get a small sample of 50 loans
df = df.iloc[0:49,:]

#setting up the weighted averages for linear equations
sumloans = df.loc[:,'funded_amnt'].sum()
df['weights'] = df['funded_amnt'].div(sumloans,axis='index')

#Converting dataframe to weighted values!
df2 = df[["id","funded_amnt","dti","int_rate"]]
df2[["funded_amntwtd","dtiwtd","int_ratewtd"]] = df[["funded_amnt","dti","int_rate"]].multiply(df["weights"],axis="index")
df3 = pd.merge(df,df2.iloc[:,[4,5,6]],on=df["id"],how='left')

#Free up memory
df = None
df2 = None

#Variable construction
loanid = df3['id'].tolist()
dtiwtd = df3.set_index('id').to_dict()['dtiwtd']
loanmix = df3.set_index('id').to_dict()['funded_amnt']
wtdloanmix = df3.set_index('id').to_dict()['funded_amntwtd']
wa_int = df3.set_index('id').to_dict()['int_ratewtd']


id_vars = LpVariable.dicts("ID",indexs=loanid, cat='Integer',lowBound=0, upBound=1)


#Objective function added first. Summing all the loan values but examining constraints

prob = LpProblem("Funding",pulp.LpMaximize)
prob += lpSum([loanmix[i]*id_vars[i] for i in id_vars]) 
prob += lpSum([loanmix[i]*id_vars[i] for i in id_vars]) <= 100000 #"Sum of loans purchased must be equal to or less than $100,000"
prob += lpSum([dtiwtd[i]*id_vars[i] for i in id_vars]) <= 10 #"Sum of weighted dtis cannot be greater than 10"
prob += lpSum([wa_int[i]*id_vars[i] for i in id_vars]) >= 0.08 #"Sum of weighted interest rates cannot be less than 8%"  
#Placeholder for inserting constraint on avg. loan size
prob.solve()

print("Status:", pulp.LpStatus[prob.status])

for v in prob.variables():
    print(v.name, "=", v.varValue)

print("Total amount invested = ", value(prob.objective))    

解决方案状态显示为“不可行”&#39;并且输出有一些非二进制整数。

我很感激有关这件事的任何帮助。我是线性代数和高等数学的新手,但我已经阅读了这个页面(http://lpsolve.sourceforge.net/5.1/ratio.htm),它帮助我建立了前两个约束。我只是坚持如何编写一个方程式或代码,以确保优化的投资组合的平均贷款价值低于10,000美元。

1 个答案:

答案 0 :(得分:0)

你正在对整数进行线性编程,这比使用实数(双精度)更麻烦。由于您的金额可以被视为双打,因此请删除整数。

id_vars是否应该保留金额或比例(加1)?如果是后者那么你需要额外约束他们的总和。 (并且使用二进制设置,它将意味着单个和n-1个零。)如果它们是金额,那么您的加权平均值不是平均值,例如就目前而言,你要确保利率的总和(不是平均值)至少为8%,你可以用1%的8笔贷款来实现。

此外: 如果我正确理解语法(我熟悉LP但不熟悉您的库),那么您正在尝试最大化投资金额,在约束条件下它至少为100000.这是意料之外的:为什么不最大化回报?

约束2,“平均债务与收入比不能超过10”,在数学上是不正确的。如果您有两笔债务为d1和d2,收入为i1和i2,比例为a和1-a,则该地段的债务与收入比为[a * d1 +(1-a) d2] / [a i1 +(1-a) i2],而不是 d1 / i1 +(1-a)* d2 / i2。

约束3可以更好地实现为一系列约束(如评论中所示):loanmix [i]&lt; = 0.1 for all i。

最低贷款要求不是线性的(线性规划中的大禁忌)。实际上,它们的形式是:对于所有我,loanmix [i] == 0或loanmix [i]&gt; = minloan [i]。黑客可能是离散化的:而不是1000美元的最小值,使用1000美元的增量。但是你回到了Integerland。