0

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

我目前在 python 中使用 PuLP 和 pandas 来解决我目前遇到的优化问题。我对线性规划很陌生,最近利用它来解决有关最小化成本问题的问题。

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

1. 投资10万美元的加权平均利率不能低于8%。

2.投资10万美元的加权平均债务收入比不能超过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 美元。目标函数是在约束(即 LpMaximise)内接近 100,000。

我选择将贷款选择建模为二元变量,因为我只是想知道它们是进还是出。此外,为了速度和内存,我从数据中选择了 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))    

解决方案状态显示为“不可行”,输出有一些非二进制整数。

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

4

1 回答 1

0

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

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

另外:如果我正确理解语法(我熟悉 LP,但不熟悉您的库),您正在尝试最大化投资金额,限制条件至少为 100000。这是出乎意料的:为什么不最大化回报?

约束 2,“平均债务收入比不能超过 10”,在数学上是不正确的。如果您有 2 项投资,债务为 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] <= 0.1 for all i。

最低贷款要求不是线性的(线性规划中的大忌)。实际上,它们的形式是:对于所有 i,loanmix[i] == 0 或 loanmix[i] >= minloan[i]。一个技巧可能是离散化:而不是最小的 1000 美元,而是使用 1000 美元的增量。但随后你又回到了 Integerland。

于 2017-06-04T12:10:54.780 回答