【发布时间】:2020-09-23 12:48:47
【问题描述】:
我试图在四个约束条件下最小化特定回报的波动性。
- 每项资产的权重都在 0 到 1 之间
- 所有权重之和等于 1
- 由资产组成的投资组合的回报等于给定的回报
- 最多只能使用 5 个资产中的 3 个
我尝试过用 Scipy 最小化这种方式:
cons_3 = ({'type': 'ineq', 'fun': lambda x: -np.count_nonzero(x) + 3},
{'type': 'eq', 'fun': lambda x: statistics(x)[0] - tret_3},
{'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
x0 = [1/3, 1/3, 1/3, 0, 0]
res_3 = sco.minimize(min_func_port, x0, method='SLSQP', bounds=bnds_3, constraints=cons_3)
但显然这是不可能的。
我还了解到使用 Z3Py 是可能的,但我似乎找不到正确的编码方式。这是我目前发现的:
import pandas as pd
from z3 import *
DesiredReturn = 0.05
df = pd.DataFrame(columns=['Name', 'Return', 'Volatility'],
data=[['Asset_1', 0.01744, 0.694149],
['Asset_2', 0.03818, 0.475544],
['Asset_3', 0.08218, 0.500724],
['Asset_4', 0.09818, 0.489052],
['Asset_5', 0.04272, 0.706223]])
W = [Real(row.Name) for row in df.itertuples()]
Vol = Real('Vol')
Ret = Real('Ret')
s = Optimize()
s.add(And([And(w >= 0, w <= 1) for w in W]))
s.add(Sum([w for w in W]) == 1)
#Missing constraint
s.add(Ret == Sum([w * row.Return for w, row in zip(W, df.itertuples())]))
s.add(Vol == Sum([w * row.Volatility for w, row in zip(W, df.itertuples())]))
s.add(Ret == DesiredReturn)
h1 = s.minimize(Vol)
print(s.check())
print(s.model())
假设本示例中资产之间的相关性为零。
非常感谢:)
【问题讨论】:
-
@JohanC 我实际上是从您对该帖子的评论中获得了我的示例模板。非常感谢您帮助我了解 Z3Py 优化的工作原理:)