Update portfolio_optimiser.py
Browse files- portfolio_optimiser.py +9 -9
portfolio_optimiser.py
CHANGED
|
@@ -14,7 +14,7 @@ def optimize_portfolio(data, risk_tolerance):
|
|
| 14 |
dict: Dictionary containing optimized asset weights for a diversified portfolio.
|
| 15 |
"""
|
| 16 |
try:
|
| 17 |
-
#
|
| 18 |
returns = data.pct_change().dropna()
|
| 19 |
mean_returns = returns.mean()
|
| 20 |
cov_matrix = returns.cov()
|
|
@@ -22,19 +22,19 @@ def optimize_portfolio(data, risk_tolerance):
|
|
| 22 |
num_assets = len(mean_returns)
|
| 23 |
risk_free_rate = 0.01 # Example: Assume a 1% risk-free rate
|
| 24 |
|
| 25 |
-
#
|
| 26 |
def negative_sharpe_ratio(weights):
|
| 27 |
portfolio_return = np.sum(mean_returns * weights)
|
| 28 |
portfolio_std_dev = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
|
| 29 |
sharpe_ratio = (portfolio_return - risk_free_rate) / portfolio_std_dev
|
| 30 |
-
return -sharpe_ratio
|
| 31 |
|
| 32 |
-
#
|
| 33 |
constraints = [
|
| 34 |
{"type": "eq", "fun": lambda x: np.sum(x) - 1}, # Sum of weights must be 1
|
| 35 |
]
|
| 36 |
|
| 37 |
-
#
|
| 38 |
max_allocation = 0.50 # Max 50% allocation per asset
|
| 39 |
min_assets_allocated = 2 # At least 2 assets must have nonzero allocation
|
| 40 |
|
|
@@ -43,13 +43,13 @@ def optimize_portfolio(data, risk_tolerance):
|
|
| 43 |
|
| 44 |
constraints.append({"type": "ineq", "fun": diversification_constraint})
|
| 45 |
|
| 46 |
-
#
|
| 47 |
bounds = tuple((0.05, max_allocation) for _ in range(num_assets)) # Min 5%, Max 50%
|
| 48 |
|
| 49 |
-
#
|
| 50 |
initial_weights = np.array([1 / num_assets] * num_assets)
|
| 51 |
|
| 52 |
-
#
|
| 53 |
optimized_results = minimize(
|
| 54 |
negative_sharpe_ratio,
|
| 55 |
initial_weights,
|
|
@@ -58,7 +58,7 @@ def optimize_portfolio(data, risk_tolerance):
|
|
| 58 |
constraints=constraints,
|
| 59 |
)
|
| 60 |
|
| 61 |
-
#
|
| 62 |
asset_weights = dict(zip(data.columns, optimized_results.x))
|
| 63 |
return asset_weights
|
| 64 |
|
|
|
|
| 14 |
dict: Dictionary containing optimized asset weights for a diversified portfolio.
|
| 15 |
"""
|
| 16 |
try:
|
| 17 |
+
# Calculate daily returns & covariance matrix
|
| 18 |
returns = data.pct_change().dropna()
|
| 19 |
mean_returns = returns.mean()
|
| 20 |
cov_matrix = returns.cov()
|
|
|
|
| 22 |
num_assets = len(mean_returns)
|
| 23 |
risk_free_rate = 0.01 # Example: Assume a 1% risk-free rate
|
| 24 |
|
| 25 |
+
# Objective Function: Maximize Sharpe Ratio
|
| 26 |
def negative_sharpe_ratio(weights):
|
| 27 |
portfolio_return = np.sum(mean_returns * weights)
|
| 28 |
portfolio_std_dev = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
|
| 29 |
sharpe_ratio = (portfolio_return - risk_free_rate) / portfolio_std_dev
|
| 30 |
+
return -sharpe_ratio
|
| 31 |
|
| 32 |
+
# Constraints:
|
| 33 |
constraints = [
|
| 34 |
{"type": "eq", "fun": lambda x: np.sum(x) - 1}, # Sum of weights must be 1
|
| 35 |
]
|
| 36 |
|
| 37 |
+
# Set Diversification Constraints
|
| 38 |
max_allocation = 0.50 # Max 50% allocation per asset
|
| 39 |
min_assets_allocated = 2 # At least 2 assets must have nonzero allocation
|
| 40 |
|
|
|
|
| 43 |
|
| 44 |
constraints.append({"type": "ineq", "fun": diversification_constraint})
|
| 45 |
|
| 46 |
+
# Set Bounds (Per-Asset Allocation Limits)
|
| 47 |
bounds = tuple((0.05, max_allocation) for _ in range(num_assets)) # Min 5%, Max 50%
|
| 48 |
|
| 49 |
+
# Initialise Equal Weights
|
| 50 |
initial_weights = np.array([1 / num_assets] * num_assets)
|
| 51 |
|
| 52 |
+
# Optimise Portfolio Allocation
|
| 53 |
optimized_results = minimize(
|
| 54 |
negative_sharpe_ratio,
|
| 55 |
initial_weights,
|
|
|
|
| 58 |
constraints=constraints,
|
| 59 |
)
|
| 60 |
|
| 61 |
+
# Extract Optimal Weights
|
| 62 |
asset_weights = dict(zip(data.columns, optimized_results.x))
|
| 63 |
return asset_weights
|
| 64 |
|