stefan-jansen / pyfolio-reloaded

Portfolio and risk analytics in Python
https://pyfolio.ml4trading.io/
Apache License 2.0
378 stars 110 forks source link

Use .loc in plot_rolling_returns (line 808 of plotting.py) #38

Closed SamoPP closed 5 months ago

SamoPP commented 11 months ago

Problem Description

Please provide a minimal, self-contained, and reproducible example:

pf.plot_rolling_returns(portfolioReturns, live_start_date='2023-08-01 00:00:00', factor_returns=subset_benchmarkReturns)

Please provide the full traceback:

{
    "name": "KeyError",
    "message": "\"None of [DatetimeIndex(['2020-01-02 00:00:00+00:00', '2020-01-03 00:00:00+00:00',\
               '2020-01-06 00:00:00+00:00', '2020-01-07 00:00:00+00:00',\
               '2020-01-08 00:00:00+00:00', '2020-01-09 00:00:00+00:00',\
               '2020-01-10 00:00:00+00:00', '2020-01-13 00:00:00+00:00',\
               '2020-01-14 00:00:00+00:00', '2020-01-15 00:00:00+00:00',\
               ...\
               '2023-11-07 00:00:00+00:00', '2023-11-08 00:00:00+00:00',\
               '2023-11-09 00:00:00+00:00', '2023-11-10 00:00:00+00:00',\
               '2023-11-13 00:00:00+00:00', '2023-11-14 00:00:00+00:00',\
               '2023-11-15 00:00:00+00:00', '2023-11-16 00:00:00+00:00',\
               '2023-11-17 00:00:00+00:00', '2023-11-20 00:00:00+00:00'],\
              dtype='datetime64[ns, UTC]', name='Date', length=979, freq=None)] are in the [columns]\"",
    "stack": "---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
c:\\git\\Test\\Test.ipynb Cell 15 line 1
     <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=72'>73</a> dfTransactionsEntryExit.sort_index(inplace=True)
     <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=74'>75</a> # print(\"dfReturns:\")
     <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=75'>76</a> # print(dfReturns)
     <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=76'>77</a> # print(\"subset_benchmarkReturns:\")
   (...)
     <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=97'>98</a> # print(subset_benchmarkReturns.loc[cum_rets.index])
     <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=98'>99</a> # cum_factor_returns = ep.cum_returns(subset_benchmarkReturns.loc[cum_rets.index], 1.0)
--> <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=100'>101</a> pf.plot_rolling_returns(portfolioReturns, live_start_date='2023-08-01 00:00:00', factor_returns=subset_benchmarkReturns)
    <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=102'>103</a> #pf.create_returns_tear_sheet(dfReturns['Return'], live_start_date='2023-08-01 00:00:00', bootstrap=False, benchmark_rets=subset_benchmarkReturns)
    <a href='vscode-notebook-cell:/c%3A/git/Test/Test.ipynb#W5sZmlsZQ%3D%3D?line=103'>104</a> #pf.create_full_tear_sheet(returns=dfReturns['Return'], transactions=dfTransactionsEntryExit, live_start_date='2023-08-01', round_trips=True, bootstrap=False)

File c:\\git\\.venv\\Lib\\site-packages\\pyfolio\\plotting.py:808, in plot_rolling_returns(returns, factor_returns, live_start_date, logy, cone_std, legend_loc, volatility_match, cone_function, ax, **kwargs)
    805 ax.yaxis.set_major_formatter(FuncFormatter(y_axis_formatter))
    807 if factor_returns is not None:
--> 808     cum_factor_returns = ep.cum_returns(factor_returns[cum_rets.index], 1.0)
    809     cum_factor_returns.plot(
    810         lw=2,
    811         color=\"gray\",
   (...)
    815         **kwargs,
    816     )
    818 if live_start_date is not None:

File c:\\git\\.venv\\Lib\\site-packages\\pandas\\core\\frame.py:3813, in DataFrame.__getitem__(self, key)
   3811     if is_iterator(key):
   3812         key = list(key)
-> 3813     indexer = self.columns._get_indexer_strict(key, \"columns\")[1]
   3815 # take() does not accept boolean indexers
   3816 if getattr(indexer, \"dtype\", None) == bool:

File c:\\git\\.venv\\Lib\\site-packages\\pandas\\core\\indexes\\base.py:6070, in Index._get_indexer_strict(self, key, axis_name)
   6067 else:
   6068     keyarr, indexer, new_indexer = self._reindex_non_unique(keyarr)
-> 6070 self._raise_if_missing(keyarr, indexer, axis_name)
   6072 keyarr = self.take(indexer)
   6073 if isinstance(key, Index):
   6074     # GH 42790 - Preserve name from an Index

File c:\\git\\.venv\\Lib\\site-packages\\pandas\\core\\indexes\\base.py:6130, in Index._raise_if_missing(self, key, indexer, axis_name)
   6128     if use_interval_msg:
   6129         key = list(key)
-> 6130     raise KeyError(f\"None of [{key}] are in the [{axis_name}]\")
   6132 not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique())
   6133 raise KeyError(f\"{not_found} not in index\")

KeyError: \"None of [DatetimeIndex(['2020-01-02 00:00:00+00:00', '2020-01-03 00:00:00+00:00',\
               '2020-01-06 00:00:00+00:00', '2020-01-07 00:00:00+00:00',\
               '2020-01-08 00:00:00+00:00', '2020-01-09 00:00:00+00:00',\
               '2020-01-10 00:00:00+00:00', '2020-01-13 00:00:00+00:00',\
               '2020-01-14 00:00:00+00:00', '2020-01-15 00:00:00+00:00',\
               ...\
               '2023-11-07 00:00:00+00:00', '2023-11-08 00:00:00+00:00',\
               '2023-11-09 00:00:00+00:00', '2023-11-10 00:00:00+00:00',\
               '2023-11-13 00:00:00+00:00', '2023-11-14 00:00:00+00:00',\
               '2023-11-15 00:00:00+00:00', '2023-11-16 00:00:00+00:00',\
               '2023-11-17 00:00:00+00:00', '2023-11-20 00:00:00+00:00'],\
              dtype='datetime64[ns, UTC]', name='Date', length=979, freq=None)] are in the [columns]\""
}

Please provide any additional information below: Looks like .loc is missing in line 808 of plotting.py. Instead of cum_factor_returns = ep.cum_returns(factor_returns[cum_rets.index], 1.0) there should be cum_factor_returns = ep.cum_returns(factor_returns.loc[cum_rets.index], 1.0)

Versions