Python 投资组合优化的蒙特卡罗方法
我正在尝试创建n列长度为x的向量,并遵循以下标准: i) 每个向量的每个i分量(如x[i])都有一个最小值和一个最大值。最小值和最大值以百分比表示 ii)每列的总和为1 iii)我要确保对整个空间进行均匀取样 我编写了以下例程,称为“gen_port”,它接受两个向量,其中包含向量的下限和上限,加上要生成的随机向量数(例如,N) 例如,如果我生成10列向量,这些向量由以下向量描述:Python 投资组合优化的蒙特卡罗方法,python,numpy,random,montecarlo,Python,Numpy,Random,Montecarlo,我正在尝试创建n列长度为x的向量,并遵循以下标准: i) 每个向量的每个i分量(如x[i])都有一个最小值和一个最大值。最小值和最大值以百分比表示 ii)每列的总和为1 iii)我要确保对整个空间进行均匀取样 我编写了以下例程,称为“gen_port”,它接受两个向量,其中包含向量的下限和上限,加上要生成的随机向量数(例如,N) 例如,如果我生成10列向量,这些向量由以下向量描述: lower_bound = [0.0,0.0,0.0,0.0] upper_bound = [0.50,0.50,
lower_bound = [0.0,0.0,0.0,0.0]
upper_bound = [0.50,0.50,0.50,0.50]
gen_ports(lower_bound, upper_bound, 10)
[Out]
array([[ 0.15749895, 0.21279324, 0.35603417, 0.27367365],
[ 0.2970716 , 0.48189552, 0.04709743, 0.17393545],
[ 0.20367186, 0.47925996, 0.21349772, 0.10357047],
[ 0.29129967, 0.15936119, 0.26925573, 0.28008341],
[ 0.11058273, 0.2699138 , 0.39068379, 0.22881968],
[ 0.21286622, 0.39058314, 0.33895212, 0.05759852],
[ 0.18726399, 0.37648587, 0.32808714, 0.108163 ],
[ 0.03839954, 0.24170767, 0.40299362, 0.31689917],
[ 0.35782691, 0.31928643, 0.24712695, 0.0757597 ],
[ 0.25595576, 0.08776559, 0.16836131, 0.48791733]])
但是,如果下界和上界的值不一致,我希望能够填充向量
例如,如果
[In]:
lower_bound = [0.0,0.25,0.25,0.0]
upper_bound = [0.50,0.50,0.75,1.0]
gen_ports(lower_bound, upper_bound, 100000)
结果不等于1(以下仅包括10个样本):
我想生成100000个场景,以便对由上下限定义的空间进行均匀采样。但是我被难住了,因为当前函数在向量被上下限转换后,将向量标准化
所以,我有一个明显的第一个问题-如何在大多数情况下修改例程
此外:
i) 这种方法正确吗?例如,我通过这个实现引入了任何偏见
ii)是否有更快和/或更“pythonic”的方法来实现这一点?n=1000000和x=35大约需要15分钟,除非你有理由绝对需要使用蒙特卡罗模拟,就像这是作业一样,更有效的方法是使用数值优化器,例如:
from scipy.optimize import minimize
def find_allocations(prices):
"""Find optimal allocations for a portfolio, optimizing Sharpe ratio.
Parameters
----------
prices: DataFrame, daily prices for each stock in portfolio
Returns
-------
allocs: optimal allocations, as fractions that sum to 1.0
"""
def sharpe_ratio(allocs):
# 1e7 is arbitrary for starting portfolio value
port_vals = (prices / prices.ix[0]) * allocs * 1e7
returns = port_vals.pct_change()
avg_daily_ret = returns.means(0)
std_daily_ret = returns.std(0)
return -(252 ** 0.5) * avg_daily_ret / std_daily_ret
n = prices.shape[1]
x0 = [1.0 / n] * n
bounds = [(0.0, 1.0)] * n
constraints = ({'type': 'eq', 'fun': lambda x: 1.0 - np.sum(np.abs(x))})
allocs = minimize(sharpe_ratio, x0, method = 'SLSQP',
bounds = bounds, constraints = constraints)
return allocs.x
注意这是最小化Sharpe比率的负数,所以实际上是最大化Sharpe比率,正如您所希望的那样。根据您想要优化的内容,某些目标函数(例如约束为返回与相等分配相同的最小方差)具有解析解 如果您没有允许任何下限/上限的要求(或者,如果下限始终为0,上限始终为1),那么答案将是众所周知的Dirichlet分布 链接中有一些python代码示例。对于\vec{a}=1的最简单情况,还有一种非常简单的方法可以对Dirichlet进行采样,如果需要,我会把它挖出来。但是边界会带来额外的问题 更新 我相信你们可以使用拒绝,从Dirichlet取样,拒绝任何不符合间隔的东西,但我猜效率会很低 更新二 在所有
\alpha
都等于1的情况下找到与Python Dirichlet采样的链接
不,这不是“家庭作业”。我也不是在试图优化某个退货问题。我试图填充一个潜在投资组合的表面,其中每种资产都与其他资产具有独特的相关性。我希望有人能回答我的问题,而不是猜测我想解决什么问题。谢谢,我会检查这个。正如您所注意到的,我需要考虑不同的上限和下限。但这是有用的第一步。
[Out]:
array([[ 0.16010701, 0.31426425, 0.38776233, 0.1378664 ],
[ 0.00360632, 0.37343983, 0.57538205, 0.0475718 ],
[ 0.28273906, 0.2228893 , 0.1998151 , 0.29455654],
[ 0.06602521, 0.21386937, 0.49896407, 0.22114134],
[ 0.17785613, 0.33885919, 0.25276605, 0.23051864],
[ 0.07223014, 0.19988808, 0.16398971, 0.56389207],
[ 0.14320281, 0.14400242, 0.18276333, 0.53003144],
[ 0.04962725, 0.2578919 , 0.19029586, 0.50218499],
[ 0.01619681, 0.21040566, 0.30615235, 0.46724517],
[ 0.10905285, 0.23641745, 0.40660215, 0.24792755]])
from scipy.optimize import minimize
def find_allocations(prices):
"""Find optimal allocations for a portfolio, optimizing Sharpe ratio.
Parameters
----------
prices: DataFrame, daily prices for each stock in portfolio
Returns
-------
allocs: optimal allocations, as fractions that sum to 1.0
"""
def sharpe_ratio(allocs):
# 1e7 is arbitrary for starting portfolio value
port_vals = (prices / prices.ix[0]) * allocs * 1e7
returns = port_vals.pct_change()
avg_daily_ret = returns.means(0)
std_daily_ret = returns.std(0)
return -(252 ** 0.5) * avg_daily_ret / std_daily_ret
n = prices.shape[1]
x0 = [1.0 / n] * n
bounds = [(0.0, 1.0)] * n
constraints = ({'type': 'eq', 'fun': lambda x: 1.0 - np.sum(np.abs(x))})
allocs = minimize(sharpe_ratio, x0, method = 'SLSQP',
bounds = bounds, constraints = constraints)
return allocs.x