Portfolio optimization bugs (#1388)

* Better EF plotting

* Better error handling with optimization commands

* fix test

Co-authored-by: didierlopes.eth <dro.lopes@campus.fct.unl.pt>
This commit is contained in:
jmaslek
2022-02-19 12:50:35 -05:00
committed by GitHub
parent 4697efcf26
commit 72bfa9e2d8
3 changed files with 34 additions and 7 deletions

View File

@@ -285,9 +285,13 @@ def display_efficient_risk(
Optional axes to plot data on
"""
s_title = f"{d_period[period]} Weights that maximise returns at target volatility: {target_volatility}"
ef_opt, ef = optimizer_model.get_efficient_risk_portfolio(
stocks, period, target_volatility, market_neutral
)
try:
ef_opt, ef = optimizer_model.get_efficient_risk_portfolio(
stocks, period, target_volatility, market_neutral
)
except ValueError as e:
console.print(f"[red]{e}[/red]\n")
return
weights = {key: value * round(port_value, 5) for key, port_value in ef_opt.items()}
if not market_neutral and pie:
@@ -332,9 +336,15 @@ def display_efficient_return(
Optional axes to plot data on
"""
s_title = f"{d_period[period]} Weights that minimizes volatility at target return: {target_return}"
ef_opt, ef = optimizer_model.get_efficient_return_portfolio(
stocks, period, target_return, market_neutral
)
try:
ef_opt, ef = optimizer_model.get_efficient_return_portfolio(
stocks, period, target_return, market_neutral
)
except ValueError as e:
# This means optimization failed
console.print(f"[red]{e}[/red]\n")
return
weights = {key: value * round(port_value, 5) for key, port_value in ef_opt.items()}
if not market_neutral and pie:
@@ -382,7 +392,8 @@ def display_ef(
sharpes = rets / stds
ax.scatter(stds, rets, marker=".", c=sharpes)
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True)
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=False)
for ticker, ret, std in zip(
ef.tickers, ef.expected_returns, np.sqrt(np.diag(ef.cov_matrix))
):
@@ -407,6 +418,9 @@ def display_ef(
ax.set_xlim(xmin=min(stds) * 0.8)
ax.add_line(line)
ax.set_title(f"Efficient Frontier simulating {n_portfolios} portfolios")
ax.legend(loc="best", scatterpoints=1)
theme.style_primary_axis(ax)
if external_axes is None:
theme.visualize_output()

View File

@@ -247,6 +247,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
optimizer_view.display_equal_weight(
stocks=self.tickers, value=ns_parser.value, pie=ns_parser.pie
@@ -282,6 +283,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 stocks selected to perform calculations."
)
return
optimizer_view.display_property_weighting(
self.tickers,
@@ -320,6 +322,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 stocks selected to perform calculations."
)
return
optimizer_view.display_property_weighting(
self.tickers,
@@ -367,6 +370,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 stocks selected to perform calculations."
)
return
optimizer_view.display_property_weighting(
self.tickers,
@@ -423,6 +427,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
optimizer_view.display_max_sharpe(
stocks=self.tickers,
@@ -471,6 +476,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
optimizer_view.display_min_volatility(
stocks=self.tickers,
@@ -535,6 +541,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
if ns_parser.pie and ns_parser.market_neutral:
console.print(
@@ -611,11 +618,13 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
if ns_parser.pie and ns_parser.market_neutral:
console.print(
"Cannot show pie chart for market neutral due to negative weights."
)
return
optimizer_view.display_efficient_risk(
stocks=self.tickers,
@@ -685,11 +694,13 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
if ns_parser.pie and ns_parser.market_neutral:
console.print(
"Cannot show pie chart for market neutral due to negative weights."
)
return
optimizer_view.display_efficient_return(
stocks=self.tickers,
@@ -743,6 +754,7 @@ class PortfolioOptimization(BaseController):
console.print(
"Please have at least 2 loaded tickers to calculate weights.\n"
)
return
optimizer_view.display_ef(
stocks=self.tickers,

View File

@@ -326,6 +326,7 @@ def test_call_func(
)
controller = po_controller.PortfolioOptimization(queue=None)
controller.tickers = ["AAPL", "MSFT"]
getattr(controller, tested_func)(other_args)