robertmartin8 / PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
https://pyportfolioopt.readthedocs.io/
MIT License
4.43k stars 950 forks source link

Plotting issues #433

Closed acastiel closed 1 year ago

acastiel commented 2 years ago

It seems the Plotting module is not working properly:

using

from pypfopt import plotting ef = pf.EfficientFrontier(mu, S) plotting.plot_efficient_frontier(ef,ax=ax)

I have this message: TypeError: cannot pickle 'osqp.OSQP_results' object

robertmartin8 commented 2 years ago

I can't reproduce this: it works for me

yosukesan commented 2 years ago

I had probably the same issue on my host. Is this reproducible for you ? I also found pytest failed in my host env. Please check my following report after this.

Read in price data

df = pd.read_csv("PyPortfolioOpt/tests/resources/stock_prices.csv", parse_dates=True, index_col="date")

Calculate expected returns and sample covariance

mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df)

Optimize for maximal Sharpe ratio

ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.save_weights_to_file("weights.csv") # saves to file print(cleaned_weights) ef.portfolio_performance(verbose=True)

fig, ax = plt.subplots() plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True)


* Err log

python efficent_front_plot_sample.py OrderedDict([('GOOG', 0.03835), ('AAPL', 0.0689), ('FB', 0.20603), ('BABA', 0.07315), ('AMZN', 0.04033), ('GE', 0.0), ('AMD', 0.0), ('WMT', 0.0), ('BAC', 0.0), ('GM', 0.0), ('T', 0.0), ('UAA', 0.0), ('SHLD', 0.0), ('XOM', 0.0), ('RRC', 0.0), ('BBY', 0.01324), ('MA', 0.35349), ('PFE', 0.1957), ('JPM', 0.0), ('SBUX', 0.01082)]) Expected annual return: 30.5% Annual volatility: 22.2% Sharpe Ratio: 1.28 Traceback (most recent call last): File "/home/yosuke/Data/finance/py_portfolio_opt/PyPortfolioOpt/efficent_front_plot_sample.py", line 26, in plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True) File "/home/yosuke/.local/lib/python3.9/site-packages/pypfopt/plotting.py", line 261, in plot_efficient_frontier ef_param_range = _ef_default_returns_range(opt, points) File "/home/yosuke/.local/lib/python3.9/site-packages/pypfopt/plotting.py", line 159, in _ef_default_returns_range ef_minvol = copy.deepcopy(ef) File "/usr/lib/python3.9/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, rv) File "/usr/lib/python3.9/copy.py", line 270, in _reconstruct state = deepcopy(state, memo) File "/usr/lib/python3.9/copy.py", line 146, in deepcopy y = copier(x, memo) File "/usr/lib/python3.9/copy.py", line 230, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) File "/usr/lib/python3.9/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, rv) File "/usr/lib/python3.9/copy.py", line 270, in _reconstruct state = deepcopy(state, memo) File "/usr/lib/python3.9/copy.py", line 146, in deepcopy y = copier(x, memo) File "/usr/lib/python3.9/copy.py", line 230, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) File "/usr/lib/python3.9/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, *rv) File "/usr/lib/python3.9/copy.py", line 270, in _reconstruct state = deepcopy(state, memo) File "/usr/lib/python3.9/copy.py", line 146, in deepcopy y = copier(x, memo) File "/usr/lib/python3.9/copy.py", line 230, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) File "/usr/lib/python3.9/copy.py", line 146, in deepcopy y = copier(x, memo) File "/usr/lib/python3.9/copy.py", line 230, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) File "/usr/lib/python3.9/copy.py", line 161, in deepcopy rv = reductor(4) TypeError: cannot pickle 'osqp.OSQP_results' object

yosukesan commented 2 years ago

Here is my test result.

============================= test session starts ==============================
platform linux -- Python 3.9.2, pytest-6.0.2, py-1.10.0, pluggy-0.13.0
rootdir: /home/yosuke/Data/finance/py_portfolio_opt/PyPortfolioOpt
collected 312 items

tests/test_base_optimizer.py ...................                         [  6%]
tests/test_black_litterman.py .....................                      [ 12%]
tests/test_cla.py ............                                           [ 16%]
tests/test_custom_objectives.py ..................                       [ 22%]
tests/test_discrete_allocation.py .................                      [ 27%]
tests/test_efficient_cdar.py ....................                        [ 34%]
tests/test_efficient_cvar.py .....................                       [ 41%]
tests/test_efficient_frontier.py ....................................... [ 53%]
...................................                                      [ 64%]
tests/test_efficient_semivariance.py ............................        [ 73%]
tests/test_expected_returns.py ...................                       [ 79%]
tests/test_hrp.py ......                                                 [ 81%]
tests/test_imports.py ...                                                [ 82%]
tests/test_objective_functions.py ...........                            [ 86%]
tests/test_plotting.py ..FFFFF.FFFFF....                                 [ 91%]
tests/test_risk_models.py ..........................                     [100%]

=================================== FAILURES ===================================
________________________________ test_cla_plot _________________________________

    def test_cla_plot():
        plt.figure()
        df = get_data()
        rets = expected_returns.mean_historical_return(df)
        S = risk_models.exp_cov(df)
        cla = CLA(rets, S)

        ax = plotting.plot_efficient_frontier(cla, showfig=False)
>       assert len(ax.findobj()) == 142
E       AssertionError: assert 143 == 142
E        +  where 143 = len([<matplotlib.collections.PathCollection object at 0x7f6e27b28af0>, <matplotlib.collections.PathCollection object at 0x...3424e700>, <matplotlib.spines.Spine object at 0x7f6e3424e220>, <matplotlib.spines.Spine object at 0x7f6e3424ea90>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e27b28af0>, <matplotlib.collections.PathCollection object at 0x...3424e700>, <matplotlib.spines.Spine object at 0x7f6e3424e220>, <matplotlib.spines.Spine object at 0x7f6e3424ea90>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:88: AssertionError
_______________________________ test_cla_plot_ax _______________________________

    def test_cla_plot_ax():
        plt.figure()
        df = get_data()
        rets = expected_returns.mean_historical_return(df)
        S = risk_models.exp_cov(df)
        cla = CLA(rets, S)

        fig, ax = plt.subplots(figsize=(12, 10))
        plotting.plot_efficient_frontier(cla, ax=ax)
>       assert len(ax.findobj()) == 142
E       AssertionError: assert 143 == 142
E        +  where 143 = len([<matplotlib.collections.PathCollection object at 0x7f6e26f99250>, <matplotlib.collections.PathCollection object at 0x...27bb6070>, <matplotlib.spines.Spine object at 0x7f6e27bb6e80>, <matplotlib.spines.Spine object at 0x7f6e27bb6ac0>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26f99250>, <matplotlib.collections.PathCollection object at 0x...27bb6070>, <matplotlib.spines.Spine object at 0x7f6e27bb6e80>, <matplotlib.spines.Spine object at 0x7f6e27bb6ac0>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:106: AssertionError
_____________________________ test_default_ef_plot _____________________________

    def test_default_ef_plot():
        plt.figure()
        ef = setup_efficient_frontier()
        ax = plotting.plot_efficient_frontier(ef, show_assets=True)
>       assert len(ax.findobj()) == 124
E       AssertionError: assert 125 == 124
E        +  where 125 = len([<matplotlib.collections.PathCollection object at 0x7f6e26f1e370>, <matplotlib.lines.Line2D object at 0x7f6e26f2c9d0>,...26f70fd0>, <matplotlib.spines.Spine object at 0x7f6e26f36100>, <matplotlib.spines.Spine object at 0x7f6e26f361f0>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26f1e370>, <matplotlib.lines.Line2D object at 0x7f6e26f2c9d0>,...26f70fd0>, <matplotlib.spines.Spine object at 0x7f6e26f36100>, <matplotlib.spines.Spine object at 0x7f6e26f361f0>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:115: AssertionError
_________________________ test_default_ef_plot_labels __________________________

    def test_default_ef_plot_labels():
        plt.figure()
        ef = setup_efficient_frontier()
        ax = plotting.plot_efficient_frontier(ef, show_assets=True, show_tickers=True)
>       assert len(ax.findobj()) == 124 + len(ef.tickers)
E       AssertionError: assert 145 == (124 + 20)
E        +  where 145 = len([<matplotlib.collections.PathCollection object at 0x7f6e26e41ee0>, <matplotlib.lines.Line2D object at 0x7f6e26e41340>,...AAPL'), Text(0.3704067363898078, 0.2840374345617638, 'FB'), Text(0.3177391875264159, 0.19231644713860208, 'BABA'), ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26e41ee0>, <matplotlib.lines.Line2D object at 0x7f6e26e41340>,...AAPL'), Text(0.3704067363898078, 0.2840374345617638, 'FB'), Text(0.3177391875264159, 0.19231644713860208, 'BABA'), ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj
E        +  and   20 = len(['GOOG', 'AAPL', 'FB', 'BABA', 'AMZN', 'GE', ...])
E        +    where ['GOOG', 'AAPL', 'FB', 'BABA', 'AMZN', 'GE', ...] = <pypfopt.efficient_frontier.efficient_frontier.EfficientFrontier object at 0x7f6e26f16850>.tickers

tests/test_plotting.py:132: AssertionError
_____________________________ test_ef_plot_utility _____________________________

    def test_ef_plot_utility():
        plt.figure()
        ef = setup_efficient_frontier()
        delta_range = np.arange(0.001, 50, 1)
        ax = plotting.plot_efficient_frontier(
            ef, ef_param="utility", ef_param_range=delta_range, showfig=False
        )
>       assert len(ax.findobj()) == 124
E       AssertionError: assert 125 == 124
E        +  where 125 = len([<matplotlib.collections.PathCollection object at 0x7f6e26db2bb0>, <matplotlib.lines.Line2D object at 0x7f6e26db2ee0>,...26ead430>, <matplotlib.spines.Spine object at 0x7f6e26ead520>, <matplotlib.spines.Spine object at 0x7f6e26ead610>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26db2bb0>, <matplotlib.lines.Line2D object at 0x7f6e26db2ee0>,...26ead430>, <matplotlib.spines.Spine object at 0x7f6e26ead520>, <matplotlib.spines.Spine object at 0x7f6e26ead610>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:143: AssertionError
______________________________ test_ef_plot_risk _______________________________

    def test_ef_plot_risk():
        plt.figure()
        ef = setup_efficient_frontier()
        ef.min_volatility()
        min_risk = ef.portfolio_performance()[1]

        ef = setup_efficient_frontier()
        risk_range = np.linspace(min_risk + 0.05, 0.5, 30)
        ax = plotting.plot_efficient_frontier(
            ef, ef_param="risk", ef_param_range=risk_range, showfig=False
        )
>       assert len(ax.findobj()) == 124
E       AssertionError: assert 125 == 124
E        +  where 125 = len([<matplotlib.collections.PathCollection object at 0x7f6e26e41430>, <matplotlib.lines.Line2D object at 0x7f6e26e41460>,...27b7b850>, <matplotlib.spines.Spine object at 0x7f6e27b7b730>, <matplotlib.spines.Spine object at 0x7f6e27b47b20>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26e41430>, <matplotlib.lines.Line2D object at 0x7f6e26e41460>,...27b7b850>, <matplotlib.spines.Spine object at 0x7f6e27b7b730>, <matplotlib.spines.Spine object at 0x7f6e27b47b20>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:177: AssertionError
_____________________________ test_ef_plot_return ______________________________

    def test_ef_plot_return():
        plt.figure()
        ef = setup_efficient_frontier()
        # Internally _max_return() is used, so subtract epsilon
        max_ret = ef.expected_returns.max() - 0.0001
        return_range = np.linspace(0, max_ret, 30)
        ax = plotting.plot_efficient_frontier(
            ef, ef_param="return", ef_param_range=return_range, showfig=False
        )
>       assert len(ax.findobj()) == 124
E       AssertionError: assert 125 == 124
E        +  where 125 = len([<matplotlib.collections.PathCollection object at 0x7f6e27b590d0>, <matplotlib.lines.Line2D object at 0x7f6e27ad6ee0>,...34233910>, <matplotlib.spines.Spine object at 0x7f6e34233cd0>, <matplotlib.spines.Spine object at 0x7f6e34233e20>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e27b590d0>, <matplotlib.lines.Line2D object at 0x7f6e27ad6ee0>,...34233910>, <matplotlib.spines.Spine object at 0x7f6e34233cd0>, <matplotlib.spines.Spine object at 0x7f6e34233e20>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:191: AssertionError
__________________________ test_ef_plot_utility_short __________________________

    def test_ef_plot_utility_short():
        plt.figure()
        ef = EfficientFrontier(
            *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
        )
        delta_range = np.linspace(0.001, 20, 50)
        ax = plotting.plot_efficient_frontier(
            ef, ef_param="utility", ef_param_range=delta_range, showfig=False
        )
>       assert len(ax.findobj()) == 160
E       AssertionError: assert 161 == 160
E        +  where 161 = len([<matplotlib.collections.PathCollection object at 0x7f6e3439d3d0>, <matplotlib.lines.Line2D object at 0x7f6e3439d1c0>,...34262970>, <matplotlib.spines.Spine object at 0x7f6e34262940>, <matplotlib.spines.Spine object at 0x7f6e34262610>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e3439d3d0>, <matplotlib.lines.Line2D object at 0x7f6e3439d1c0>,...34262970>, <matplotlib.spines.Spine object at 0x7f6e34262940>, <matplotlib.spines.Spine object at 0x7f6e34262610>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:205: AssertionError
_______________________ test_constrained_ef_plot_utility _______________________

    def test_constrained_ef_plot_utility():
        plt.figure()
        ef = setup_efficient_frontier()
        ef.add_constraint(lambda w: w[0] >= 0.2)
        ef.add_constraint(lambda w: w[2] == 0.15)
        ef.add_constraint(lambda w: w[3] + w[4] <= 0.10)

        delta_range = np.linspace(0.001, 20, 50)
        ax = plotting.plot_efficient_frontier(
            ef, ef_param="utility", ef_param_range=delta_range, showfig=False
        )
>       assert len(ax.findobj()) == 124
E       AssertionError: assert 125 == 124
E        +  where 125 = len([<matplotlib.collections.PathCollection object at 0x7f6e26d4ad00>, <matplotlib.lines.Line2D object at 0x7f6e26d4a070>,...27a9cd30>, <matplotlib.spines.Spine object at 0x7f6e27a9cf40>, <matplotlib.spines.Spine object at 0x7f6e27a9c940>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26d4ad00>, <matplotlib.lines.Line2D object at 0x7f6e26d4a070>,...27a9cd30>, <matplotlib.spines.Spine object at 0x7f6e27a9cf40>, <matplotlib.spines.Spine object at 0x7f6e27a9c940>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:221: AssertionError
________________________ test_constrained_ef_plot_risk _________________________

    def test_constrained_ef_plot_risk():
        plt.figure()
        ef = EfficientFrontier(
            *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
        )

        ef.add_constraint(lambda w: w[0] >= 0.2)
        ef.add_constraint(lambda w: w[2] == 0.15)
        ef.add_constraint(lambda w: w[3] + w[4] <= 0.10)

        # 100 portfolios with risks between 0.10 and 0.30
        risk_range = np.linspace(0.157, 0.40, 50)
        ax = plotting.plot_efficient_frontier(
            ef, ef_param="risk", ef_param_range=risk_range, show_assets=True, showfig=False
        )
>       assert len(ax.findobj()) == 136
E       AssertionError: assert 137 == 136
E        +  where 137 = len([<matplotlib.collections.PathCollection object at 0x7f6e26cfeaf0>, <matplotlib.lines.Line2D object at 0x7f6e26cfe190>,...26d802b0>, <matplotlib.spines.Spine object at 0x7f6e26d803a0>, <matplotlib.spines.Spine object at 0x7f6e26d80490>, ...])
E        +    where [<matplotlib.collections.PathCollection object at 0x7f6e26cfeaf0>, <matplotlib.lines.Line2D object at 0x7f6e26cfe190>,...26d802b0>, <matplotlib.spines.Spine object at 0x7f6e26d803a0>, <matplotlib.spines.Spine object at 0x7f6e26d80490>, ...] = <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>>()
E        +      where <bound method Artist.findobj of <AxesSubplot:xlabel='Volatility', ylabel='Return'>> = <AxesSubplot:xlabel='Volatility', ylabel='Return'>.findobj

tests/test_plotting.py:241: AssertionError
=============================== warnings summary ===============================
tests/test_base_optimizer.py::test_exception_immutability
  /home/yosuke/Data/finance/py_portfolio_opt/PyPortfolioOpt/pypfopt/efficient_frontier/efficient_frontier.py:176: RuntimeWarning: Market neutrality requires shorting - bounds have been amended
    warnings.warn(

tests/test_black_litterman.py::test_input_errors
tests/test_black_litterman.py::test_parse_views
tests/test_black_litterman.py::test_dataframe_input
tests/test_black_litterman.py::test_default_omega
tests/test_black_litterman.py::test_bl_returns_no_prior
tests/test_black_litterman.py::test_bl_relative_views
tests/test_black_litterman.py::test_bl_cov_default
tests/test_black_litterman.py::test_bl_weights
tests/test_black_litterman.py::test_bl_no_uncertainty
  /home/yosuke/Data/finance/py_portfolio_opt/PyPortfolioOpt/pypfopt/black_litterman.py:257: UserWarning: Running Black-Litterman with no prior.
    warnings.warn("Running Black-Litterman with no prior.")

tests/test_black_litterman.py::test_bl_returns_all_views
tests/test_black_litterman.py::test_bl_returns_all_views
  <frozen importlib._bootstrap>:228: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 216 from C header, got 232 from PyObject

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:34: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    method='lar', copy_X=True, eps=np.finfo(np.float).eps,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:164: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    method='lar', copy_X=True, eps=np.finfo(np.float).eps,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:281: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    eps=np.finfo(np.float).eps, copy_Gram=True, verbose=0,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:865: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    eps=np.finfo(np.float).eps, copy_X=True, fit_path=True,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:1121: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    eps=np.finfo(np.float).eps, copy_X=True, fit_path=True,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:1149: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    eps=np.finfo(np.float).eps, positive=False):

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:1379: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:1621: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    max_n_alphas=1000, n_jobs=None, eps=np.finfo(np.float).eps,

tests/test_black_litterman.py::test_bl_returns_all_views
  /usr/lib/python3/dist-packages/sklearn/linear_model/_least_angle.py:1755: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
  Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
    eps=np.finfo(np.float).eps, copy_X=True, positive=False):

tests/test_discrete_allocation.py: 6 warnings
tests/test_efficient_cvar.py: 1 warning
tests/test_efficient_semivariance.py: 2 warnings
tests/test_plotting.py: 1 warning
  /home/yosuke/.local/lib/python3.9/site-packages/cvxpy/problems/problem.py:1337: UserWarning: Solution may be inaccurate. Try another solver, adjusting the solver settings, or solve with verbose=True for more information.
    warnings.warn(

tests/test_efficient_cdar.py::test_cdar_example
tests/test_efficient_cdar.py::test_cdar_example_weekly
tests/test_efficient_cdar.py::test_cdar_example_monthly
tests/test_efficient_cvar.py::test_cvar_example
tests/test_efficient_cvar.py::test_cvar_example_weekly
tests/test_efficient_cvar.py::test_cvar_example_monthly
tests/test_efficient_semivariance.py::test_es_example_short
  /usr/lib/python3/dist-packages/pandas/core/nanops.py:1558: DeprecationWarning: the `interpolation=` argument to percentile was renamed to `method=`, which has additional options.
  Users of the modes 'nearest', 'lower', 'higher', or 'midpoint' are encouraged to review the method they used. (Deprecated NumPy 1.22)
    return np.percentile(values, q, axis=axis, interpolation=interpolation)

tests/test_efficient_frontier.py::test_min_volatility_sector_constraints
  /home/yosuke/Data/finance/py_portfolio_opt/PyPortfolioOpt/pypfopt/base_optimizer.py:382: UserWarning: Sector constraints may not produce reasonable results if shorts are allowed.
    warnings.warn(

tests/test_efficient_frontier.py::test_max_sharpe_L2_reg_different_gamma
tests/test_efficient_frontier.py::test_max_sharpe_L2_reg_different_gamma
tests/test_efficient_frontier.py::test_max_sharpe_L2_reg_reduces_sharpe
tests/test_efficient_frontier.py::test_max_sharpe_L2_reg_with_shorts
  /home/yosuke/Data/finance/py_portfolio_opt/PyPortfolioOpt/pypfopt/efficient_frontier/efficient_frontier.py:257: UserWarning: max_sharpe transforms the optimization problem so additional objectives may not work as expected.
    warnings.warn(

-- Docs: https://docs.pytest.org/en/stable/warnings.html
=========================== short test summary info ============================
FAILED tests/test_plotting.py::test_cla_plot - AssertionError: assert 143 == 142
FAILED tests/test_plotting.py::test_cla_plot_ax - AssertionError: assert 143 ...
FAILED tests/test_plotting.py::test_default_ef_plot - AssertionError: assert ...
FAILED tests/test_plotting.py::test_default_ef_plot_labels - AssertionError: ...
FAILED tests/test_plotting.py::test_ef_plot_utility - AssertionError: assert ...
FAILED tests/test_plotting.py::test_ef_plot_risk - AssertionError: assert 125...
FAILED tests/test_plotting.py::test_ef_plot_return - AssertionError: assert 1...
FAILED tests/test_plotting.py::test_ef_plot_utility_short - AssertionError: a...
FAILED tests/test_plotting.py::test_constrained_ef_plot_utility - AssertionEr...
FAILED tests/test_plotting.py::test_constrained_ef_plot_risk - AssertionError...
============ 10 failed, 302 passed, 43 warnings in 72.19s (0:01:12) ============
robertmartin8 commented 1 year ago

In your second last comment, the error is reproducible to me but also there's a problem with the code:

One shouldn't call any optimisation method on the EfficientFrontier object before running the plotting function. So when I changed it to the below, it worked:

import pandas as pd
import matplotlib.pyplot as plt
from pypfopt import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
from pypfopt import plotting
import copy

# Read in price data
df = pd.read_csv("PyPortfolioOpt/tests/resources/stock_prices.csv", parse_dates=True, index_col="date")

# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(df)
S = risk_models.sample_cov(df)

# Optimize for maximal Sharpe ratio
ef = EfficientFrontier(mu, S)

# COMMENTING OUT BELOW
# raw_weights = ef.max_sharpe()
# cleaned_weights = ef.clean_weights()
# ef.save_weights_to_file("weights.csv")  # saves to file
# print(cleaned_weights)
# ef.portfolio_performance(verbose=True)

fig, ax = plt.subplots()
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True)

As for the testing issues you pointed out, these are indeed valid and I have observed them from time to time. I think it is a result of different plotting backends creating slightly different objects when plotting. So I will modify the tests slightly. Thanks for pointing this out!

yosukesan commented 1 year ago

Worked on my env. Thanks !

issue_433_plotting_issue

Just added plt.show() for completeness.

import pandas as pd
import matplotlib.pyplot as plt
from pypfopt import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
from pypfopt import plotting
import copy

# Read in price data
df = pd.read_csv("PyPortfolioOpt/tests/resources/stock_prices.csv", parse_dates=True, index_col="date")

# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(df)
S = risk_models.sample_cov(df)

# Optimize for maximal Sharpe ratio
ef = EfficientFrontier(mu, S)

# COMMENTING OUT BELOW
# raw_weights = ef.max_sharpe()
# cleaned_weights = ef.clean_weights()
# ef.save_weights_to_file("weights.csv")  # saves to file
# print(cleaned_weights)
# ef.portfolio_performance(verbose=True)

fig, ax = plt.subplots()
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True)
plt.show()