File size: 2,443 Bytes
e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 fdf1936 e74d865 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
import pandas as pd
import numpy as np
from scipy.optimize import minimize
def optimize_portfolio(data, risk_tolerance):
"""
Performs Modern Portfolio Theory (MPT) optimization with diversification constraints.
Args:
data (pandas.DataFrame): DataFrame containing historical stock prices.
risk_tolerance (float): Risk tolerance level (higher value means higher risk).
Returns:
dict: Dictionary containing optimized asset weights for a diversified portfolio.
"""
try:
# Calculate daily returns & covariance matrix
returns = data.pct_change().dropna()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_assets = len(mean_returns)
risk_free_rate = 0.01 # Example: Assume a 1% risk-free rate
# Objective Function: Maximize Sharpe Ratio
def negative_sharpe_ratio(weights):
portfolio_return = np.sum(mean_returns * weights)
portfolio_std_dev = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
sharpe_ratio = (portfolio_return - risk_free_rate) / portfolio_std_dev
return -sharpe_ratio
# Constraints:
constraints = [
{"type": "eq", "fun": lambda x: np.sum(x) - 1}, # Sum of weights must be 1
]
# Set Diversification Constraints
max_allocation = 0.50 # Max 50% allocation per asset
min_assets_allocated = 2 # At least 2 assets must have nonzero allocation
def diversification_constraint(weights):
return np.count_nonzero(weights) - min_assets_allocated # Enforce minimum assets
constraints.append({"type": "ineq", "fun": diversification_constraint})
# Set Bounds (Per-Asset Allocation Limits)
bounds = tuple((0.05, max_allocation) for _ in range(num_assets)) # Min 5%, Max 50%
# Initialise Equal Weights
initial_weights = np.array([1 / num_assets] * num_assets)
# Optimise Portfolio Allocation
optimized_results = minimize(
negative_sharpe_ratio,
initial_weights,
method="SLSQP",
bounds=bounds,
constraints=constraints,
)
# Extract Optimal Weights
asset_weights = dict(zip(data.columns, optimized_results.x))
return asset_weights
except Exception as e:
print(f"Error optimizing portfolio: {e}")
return None
|