robertmartin8 / PyPortfolioOpt

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

Possible Heap Corruption while calling plotting.plot_efficient_frontier() #365

Closed 10sun closed 2 years ago

10sun commented 3 years ago

Describe the bug while calling this function, I ran into the problem of ''Exiting message loop for channel Server[1]: [WinError 10054] An existing connection was forcibly closed by the remote host".

Through debugging into the function, it is found that the error happened after finishing line 248, 'ef_param_range = _ef_default_returns_range(opt, points)'.

The debug log file says '' "exitCode": 3221226356. Would this be possibly linked to a heap corruption?

Code sample

ef = EfficientFrontier.EfficientFrontier(mu, S)
try:
    ax = plotting.plot_efficient_frontier(ef, showfig=True)
except Exception as e:
    print(e)

Operating system, python version, PyPortfolioOpt version Win 10 Enterprise, OS Build: 19042.1110, python 3.7.6 PyPortfolioOpt 1.4.2

Additional context some debug printout:

D+00011.343: /handling #16 request "continue" from Client[1]/
             Client[1] <-- {
                 "seq": 24,
                 "type": "response",
                 "request_seq": 16,
                 "success": true,
                 "command": "continue",
                 "body": {
                     "allThreadsContinued": true
                 }
             }

D+00011.343: /handling #50 event "continued" from Server[1]/
             Client[1] <-- {
                 "seq": 25,
                 "type": "event",
                 "event": "continued",
                 "body": {
                     "threadId": 1,
                     "allThreadsContinued": true
                 }
             }

D+00012.937: Exiting message loop for channel Server[1]: [WinError 10054] An existing connection was forcibly closed by the remote host

D+00012.937: Closing Server[1] message stream

I+00012.953: /handling disconnect from Server[1]/
             Server[1] has disconnected; finalizing Session[1].

I+00012.953: All debug servers disconnected; waiting for remaining sessions...

I+00012.953: /handling disconnect from Server[1]/
             Session[1] waiting for "exited" event...

D+00012.968: Launcher[1] --> {
                 "seq": 3,
                 "type": "event",
                 "event": "exited",
                 "body": {
                     "exitCode": 3221226356
                 }
             }
phschiele commented 3 years ago

@10sun Can you give some more details on the environment you are running the code on? From the debug output you shared, it looks like it's some type of remote machine?

robertmartin8 commented 2 years ago

This is a bit of a strange stack trace, I'd suggest some of the following steps to debug:

  1. Try doing other matplotlib stuff.
  2. You mentioned that the problem seems to come from _ef_default_returns_range, which is defined as follows:
def _ef_default_returns_range(ef, points):
    ef_minvol = copy.deepcopy(ef)
    ef_maxret = copy.deepcopy(ef)

    ef_minvol.min_volatility()
    min_ret = ef_minvol.portfolio_performance()[0]
    max_ret = ef_maxret._max_return()
    return np.linspace(min_ret, max_ret - 0.0001, points)

Perhaps try running each of these lines separately to see if one of them in particular is causing problems?

I'm closing for now as this is stale, but feel free to reopen if needed.