用Scipy中的linprog解决股票融资中的线性规划问题

问题:

目前有自有资金100万元,已开通融资融券,可融资额度为100万元。现已经确定需要买的10只股票(见下表),在尽量把自有资金用完的前提下,要求每只股票每只股票买入金额大致相等,并且能够使获得的融资额最大。

下表为每只股票的保证金比例及担保品折算率:

 

保证金比例(A1..A10)

担保品折算率(B1...B10)

601996

1

0.65

688598

1.5

0.5

603657

0

0.65

000875

1

0.65

002015

0

0.65

688595

1.5

0.5

601600

1

0.65

002721

0

0

000818

1

0.65

600152

0

0.65

变量分析:

10只股票,每只股票可进行担保品买入和融资买入,则有20个变量:x1,x2...x20.其中x1...x10对应上表中从上往下各股票担保品买入金额,x11...x20对应各股票融资买入金额。

规划目标分析:

融资买入总额最大MAX(z)=x11+x12+...+x20

约束条件分析:

条件1,融资警戒线为145%:x1+x2+...+y10>=1.45(x11+x12+..+x20)

条件2,担保品买入总额:x1+x2+...+x10≤1000000

条件3:  担保品折算后需大于融资额:A1*x11+A2*x12+...+A10*x20<=B1x1+B2x2+...B10*x10

条件4:只股票每只股票买入金额大致相等。每两只股票间具有如下类似关系: x1+x11≤1.2(x2+x12),总计10*9=90个约束。其中1.2为差异度,大致相当于两只股票买入金额差小于20%即为接近相等。

条件5:不能融资的股票。从上表中可以看到,有四只股票保证金比例为0,表示不能融资。例如600152不能融资,则有:X20=0。

运行结果为

[2.95546559e+04 1.33603239e+05 1.60323887e+05 2.95546557e+04

 1.60323887e+05 1.33603239e+05 2.95546560e+04 1.33603239e+05

 2.95546559e+04 1.60323887e+05 1.30769231e+05 2.83363480e-05

 0.00000000e+00 1.30769231e+05 0.00000000e+00 2.83363480e-05

 1.30769231e+05 0.00000000e+00 1.30769231e+05 0.00000000e+00]

前10个数字为各股票担保品买入额,后10各数字为各股票融资买入额。

源代码如下:

import numpy as np
from scipy.optimize import linprog

money=1000000#可用资金额
count=10#股票数量
warning_value=1.45#预警线
balance_value=1.2#股票买入额差异比
levers=[1,1.5,0,1,0,1.5,1,0,1,0]#保证金比例
guarantees=[0.65,0.5,0.65,0.65,0.65,0.5,0.65,0,0.65,0.65]#担保品折算率

#规划目标为可融资额总和,每个元素对应各变量的系数,这里后一半变量为可融资额
c=np.zeros(shape=(count*2,), dtype = np.float64)
for i in range(count):
    c[count+i]=1.0

#第一行初始化维持担保比例约束,按警戒线。
#第二行按现金确定最大担保买入量。
#第三行保证金比例约束
data=np.zeros(shape=(3,count*2), dtype = np.float64)
for i in range(count): 
    data[0][i]=-1.0
    if levers[i]>0:
        data[0][count+i]=warning_value
    else:
        data[0][count+i]=0
    data[1][i]=1.0
    data[1][count+i]=0
    data[2][i]=-guarantees[i]
    data[2][count+i]=levers[i]

#第4-93行为股票买入额相近约束
for i in range(count-1):
    line=np.zeros(shape=(1,count*2),dtype=np.float64)
    line[0][0]=1.0
    line[0][count]=1.0
    line[0][i+1]=0-balance_value
    line[0][i+count+1]=0-balance_value
    for j in range(count):
        line2=np.roll(line,j)
        data=np.concatenate((data,line2),axis=0)
A_ub=data
B_ub=np.zeros(shape=(count*(count-1)+3,), dtype = np.float64)
B_ub[1]=money

#融资额为0的约束。
A_eq=np.empty(shape=(0,count*2),dtype = np.float64)
zero_count=0
for i in range(count):
    if levers[i]>0:
        continue
    else:
        tmp=np.zeros(shape=(1,count*2), dtype = np.float64)
        tmp[0][count+i]=1.0
        A_eq=np.concatenate((A_eq,tmp),axis=0)
        zero_count=zero_count+1
B_eq=np.zeros(shape=(zero_count,), dtype = np.float64)
#第1个参数为-c,表示求最大值。
res=linprog(-c,A_ub,B_ub,A_eq,B_eq)
if res.success==False:
    exit(1)
#res.x中为对应x1,x2...x20的各个变量的值。
print(res.x)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值