Describe the bug
Tried to replicate inverse vol example from bt package.
The backtest could not be completed.
Error:
TypeError: ufunc 'isinf' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Resulting traceback:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
[c:\Users\User\Desktop\vectorbt\notebooks\bt.ipynb](file:///C:/Users/User/Desktop/vectorbt/notebooks/bt.ipynb) Cell 13 line [1](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=0)
1 # create and run
[2](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=1) tsmom_invvol_bt = bt.Backtest(
[3](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=2) tsmom_invvol_strat,
[4](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=3) pdf,
(...)
[8](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=7) progress_bar=True
[9](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=8) )
---> [10](vscode-notebook-cell:/c%3A/Users/User/Desktop/vectorbt/notebooks/bt.ipynb#X31sZmlsZQ%3D%3D?line=9) tsmom_invvol_res = bt.run(tsmom_invvol_bt)
File [c:\Users\User\anaconda3\envs\vectorbt\lib\site-packages\bt\backtest.py:28](file:///C:/Users/User/anaconda3/envs/vectorbt/lib/site-packages/bt/backtest.py:28), in run(*backtests)
26 # run each backtest
27 for bkt in backtests:
---> 28 bkt.run()
30 return Result(*backtests)
File [c:\Users\User\anaconda3\envs\vectorbt\lib\site-packages\bt\backtest.py:240](file:///C:/Users/User/anaconda3/envs/vectorbt/lib/site-packages/bt/backtest.py:240), in Backtest.run(self)
237 self.strategy.update(dt)
239 if not self.strategy.bankrupt:
--> 240 self.strategy.run()
241 # need update after to save weights, values and such
242 self.strategy.update(dt)
File [c:\Users\User\anaconda3\envs\vectorbt\lib\site-packages\bt\core.py:2101](file:///C:/Users/User/anaconda3/envs/vectorbt/lib/site-packages/bt/core.py:2101), in bt.core.Strategy.run()
File [c:\Users\User\anaconda3\envs\vectorbt\lib\site-packages\bt\core.py:2040](file:///C:/Users/User/anaconda3/envs/vectorbt/lib/site-packages/bt/core.py:2040), in bt.core.AlgoStack.__call__()
File [c:\Users\User\anaconda3\envs\vectorbt\lib\site-packages\bt\algos.py:1160](file:///C:/Users/User/anaconda3/envs/vectorbt/lib/site-packages/bt/algos.py:1160), in WeighInvVol.__call__(self, target)
1158 t0 = target.now - self.lag
1159 prc = target.universe.loc[t0 - self.lookback : t0, selected]
-> 1160 tw = bt.ffn.calc_inv_vol_weights(prc.to_returns().dropna())
1161 target.temp["weights"] = tw.dropna()
1162 return True
File [c:\Users\User\anaconda3\envs\vectorbt\lib\site-packages\ffn\core.py:1571](file:///C:/Users/User/anaconda3/envs/vectorbt/lib/site-packages/ffn/core.py:1571), in calc_inv_vol_weights(returns)
1569 # calc vols
1570 vol = np.divide(1.0, np.std(returns, ddof=1))
-> 1571 vol[np.isinf(vol)] = np.NaN
1572 volsum = vol.sum()
1573 return np.divide(vol, volsum)
As I look into the issue, it seems that np.std(returns, ddof=1) may return a series of object dtype.
It seems that np.isinf cannot handle this.
foo 55.35794
bar 115.241039
fake1 148.411672
fake2 71.772825
dtype: object
Proposed fix
The solution is a quick simply one, suggest to enforce a float type.
def calc_inv_vol_weights(returns):
"""
Calculates weights proportional to inverse volatility of each column.
Returns weights that are inversely proportional to the column's
volatility resulting in a set of portfolio weights where each position
has the same level of volatility.
Note, that assets with returns all equal to NaN or 0 are excluded from
the portfolio (their weight is set to NaN).
Returns:
Series {col_name: weight}
"""
# calc vols
vol = np.divide(1.0, np.std(returns, ddof=1))**.astype(np.float64)**
vol[np.isinf(vol)] = np.NaN
volsum = vol.sum()
return np.divide(vol, volsum)
Describe the bug Tried to replicate inverse vol example from
bt
package. The backtest could not be completed. Error:Resulting traceback:
As I look into the issue, it seems that
np.std(returns, ddof=1)
may return a series ofobject
dtype. It seems thatnp.isinf
cannot handle this.Additional context Pandas version:
2.0.0
Numpy version:1.23.5
Proposed fix The solution is a quick simply one, suggest to enforce a float type.