我正在尝试通过此功能实现投资组合优化(旨在最小化跟踪误差):
def portfolio_optimization(target_volatility=target_volatility, weights_cap = weights_cap, target_scope_1_2 = target_scope_1_2,
target_scope_3 = target_scope_3, target_esg_score = target_esg_score):
n = len(benchmark_weights) # number of assets to determine initial weights
def volatility(weights):
return np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))*260/5)
def esg_score_function(weights):
return (weights*ESG_score).sum()
def scope_1_2_function(weights):
return (weights*scope_1_2).sum()
def scope_3_function(weights):
return (weights*scope_3).sum()
def tracking_error_squared(weights):
return np.dot((weights.reshape(-1,1)-reshaped_benchmark_weights).T, np.dot(cov_matrix, (weights.reshape(-1,1)-reshaped_benchmark_weights)))*260/5
def objective(weights):
return tracking_error_squared(weights)
# constraints
weights_sum_cons = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
weights_cap_cons = {'type': 'ineq', 'fun': lambda weights: weights_cap - weights}
vol_cons = {'type' : 'ineq', 'fun': lambda weights: target_volatility - volatility(weights)}
esg_score_cons = {'type' : 'ineq', 'fun': lambda weights: esg_score_function(weights) - target_esg_score}
scope_1_2_cons = {'type' : 'ineq', 'fun': lambda weights: target_scope_1_2 - scope_1_2_function(weights)}
scope_3_cons = {'type' : 'ineq', 'fun': lambda weights: target_scope_3 - scope_3_function(weights)}
constraints = [weights_sum_cons, weights_cap_cons, vol_cons, esg_score_cons, scope_1_2_cons, scope_3_cons]
bounds = tuple((0, 1) for _ in range(n)) # weights check to be between 0 and 1 (no short-selling)
initial_guess = opt_weights # initial guess for weights: equally weighted
method = 'SLSQP'
result = sco.minimize(objective, initial_guess, method=method,
constraints=constraints, bounds=bounds) # we get optimal weigths
# output
if result.success:
optimal_weights = result.x
detected_volatility = volatility(optimal_weights)
optimized_tracking_error = tracking_error_squared(optimal_weights)
return {
'Optimal Weights': optimal_weights.round(4),
'Volatility': (detected_volatility).round(5),
"Tracking Error": np.sqrt(optimized_tracking_error),
"ESG Score": esg_score_function(optimal_weights),
"Scope 1-2": scope_1_2_function(optimal_weights),
"Scope 3": scope_3_function(optimal_weights),
'Optimization Status': "Success"
}
else: #if optimization not possible, switch to equally weighted portfolio
return {
'Optimal Weights': np.ones(n) / n,
'Volatility': volatility(np.ones(n) / n),
'Optimization Status': "Failed"
}
# Optimize the portfolio
optimized_portfolio = portfolio_optimization()
# Print the results
print("Optimized portfolio:")
print(optimized_portfolio)
我认为这段代码非常可靠,应该可以工作,因为我无法检测到其中的任何缺陷...但是我的同事正在 Excel 上对相同数据进行另一次优化,我们得到了两个不同的结果(他得到 1.43%,我得到 1.43%)得到 1.84% 的跟踪误差)。这种优化是否存在某种缺陷?我考虑过将方法从 SLSQP 更改为 trust-constr,但几乎没有任何变化(跟踪误差变化了 0.01%),而且我不知道是否应该更改代码以实现更彻底的优化,或者这个是否可靠。
谢谢你。
我的代码有效,我的老板错了。