如何在数据框中使用条件求解方程组

问题描述 投票:0回答:1

我的DataFrame如下:

Name  Volatility    Return
a      0.0243        0.212
b      0.0321        0.431
c      0.0323        0.443
d      0.0391        0.2123
e      0.0433        0.3123

我希望Volatility0.035,并为该波动率最大化Return

也就是说,我希望在新的Df中,Name以及将在我的portfolio中为Return给出最大Volatility的资产的百分比等于[C0 ]。

因此,我需要解决一个具有多个条件的方程组,这将为固定结果(0.035)提供最佳解决方案(Highest Return)。

条件是:

  • 每个资产的权重在0到1之间。
  • 权重之和为1。
  • 权重之和乘以每项资产的波动率即为“所需波动率”。
  • 权重之和乘以每项资产的收益就是“总收益”。这应该最大化。
python solver z3py
1个回答
0
投票

这里是使用Volatility == 0.035(一种开源Z3Py求解器)的方法。在SAT / SMT求解器中,您可以将代码编写为条件列表,然后程序会找到最佳解决方案(或者只是将Z3用作求解器时满足所有条件的解决方案)。

最初,SAT求解器仅使用纯布尔表达式,但是现代的SAT / SMT求解器也允许使用固定位和无限制的整数,分数,实数甚至函数作为中心变量。

要将给定的方程式写到Z3中,它们实际上就被转换为Z3表达式。下面的代码注释了每个步骤。

SAT/SMT

结果:

import pandas as pd
from z3 import *

DesiredVolatility = 0.035
df = pd.DataFrame(columns=['Name', 'Volatility', 'Return'],
                  data=[['a', 0.0243, 0.212],
                        ['b', 0.0321, 0.431],
                        ['c', 0.0323, 0.443],
                        ['d', 0.0391, 0.2123],
                        ['e', 0.0433, 0.3123]])

# create a Z3 instance to optimize something
s = Optimize()
# the weight of each asset, as a Z3 variable
W = [Real(row.Name) for row in df.itertuples()]
# the total volatility
TotVol = Real('TotVol')
# the total return, to be maximized
TotReturn = Real('TotReturn')

# weights between 0 and 1, and sum to 1
s.add(And([And(w >= 0, w <= 1) for w in W]))
s.add(Sum([w for w in W]) == 1)
# the total return is calculated as the weighted sum of the asset returns
s.add(TotReturn == Sum([w * row.Return for w, row in zip(W, df.itertuples())]))
# the volatility is calculated as the weighted sum of the asset volatility
s.add(TotVol == Sum([w * row.Volatility for w, row in zip(W, df.itertuples())]))
# the volatility should be equal to the desired volatility
s.add(TotVol == DesiredVolatility)
# we're maximizing the total return
h1 = s.maximize(TotReturn)
# we ask Z3 to do its magick
res = s.check()
# we check the result, hoping for 'sat': all conditions satisfied, a maximum is found
if res == sat:
    s.upper(h1)
    m = s.model()
    #for w in W:
    #    print(f'asset {w}): {m[w]} = {m[w].numerator_as_long() / m[w] .denominator_as_long() : .6f}')
    # output the total return
    print(f'Total Return: {m[TotReturn]} = {m[TotReturn].numerator_as_long() / m[TotReturn] .denominator_as_long() : .6f}')
    # get the proportions out of the Z3 model
    proportions = [m[w].numerator_as_long() / m[w] .denominator_as_long() for w in W]
    # create a dataframe with the result
    df_result = pd.DataFrame({'Name': df.Name, 'Proportion': proportions})
    print(df_result)
else:
    print("No satisfiable solution found")

© www.soinside.com 2019 - 2024. All rights reserved.