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 |
|