New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix43: wrap logic in a try suite #45
Conversation
Hi @avi-analytics - thanks so much for the PR! It sounds like your workflow includes calling In general, these stats functions do attempt to implement the type interfaces specified in their docstrings. As you noted in #43: "max_drawdown promises to return a float scalar in it's documentation; however in reality it returns an ndarray/Series object with same dimensionality as the input." This is true; however, it's also assuming callers fulfill their promise of providing
The test cases for I see that Thanks again! |
Hi @richafrank , many thanks for a nice review. No I'm not using 2D values. On my system even test_stats.py is failing. What is worse, it seems hard to recreate, subtle bug. I failed to recreate it on travis, even with similar set up. Problem is that Warning So the issue is that pandas API no longer guarantees symmetric treatment of Series and 1-d numpy arrays (unless explicitly done so by passing Series.values); it depends on the implementation. And on my system at least it is returning a Series object, not float scalar, even when input is 1d. To make the code more robust, two approaches are possible:
Both approaches work fine (I've tested both), though my PR is based on second. |
Oh, wow, my assumption was totally off! I'll see if I can reproduce it... |
I'm having trouble reproducing it with 1D data. Any ideas? Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.0.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: import empyrical as emp
In [4]: pd.__version__
Out[4]: '0.19.2'
In [5]: np.__version__
Out[5]: '1.12.1'
In [6]: emp.__version__
Out[6]: '0.2.2'
In [7]: emp.calmar_ratio(np.array([0.1, -0.2, 0.3, -0.1]))
Out[7]: 26.411425065382151
In [8]: emp.calmar_ratio(pd.Series([0.1, -0.2, 0.3, -0.1]))
Out[8]: 26.411425065382151
In [9]: emp.calmar_ratio(pd.DataFrame(data=[[0.1, -0.2], [0.3, -0.1]]))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-9-0825458a228a> in <module>()
----> 1 emp.calmar_ratio(pd.DataFrame(data=[[0.1, -0.2], [0.3, -0.1]]))
/Users/rich/.virtualenvs/zp35/lib/python3.5/site-packages/empyrical/stats.py in calmar_ratio(returns, period, annualization)
372 return np.nan
373
--> 374 if np.isinf(temp):
375 return np.nan
376
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() Would it be worth making a new environment with zipline's requirements.txt installed to see if that works? |
Hi @richafrank Python 3.5.2 (default, Nov 17 2016, 17:05:23)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.0.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: import empyrical as emp
In [4]: pd.__version__
Out[4]: '0.19.2'
In [5]: np.__version__
Out[5]: '1.12.1'
In [6]: emp.__version__
Out[6]: '0.2.2'
In [7]: data = [0.1, -0.2, 0.3, -0.1]
In [8]: emp.calmar_ratio(np.array(data))
Out[8]: 26.411425065382151
In [9]: emp.calmar_ratio(pd.Series(data))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-9-df3492acd200> in <module>()
----> 1 emp.calmar_ratio(pd.Series(data))
/media/avinash/infotainment/projects/github/mypyfolio/lib/python3.5/site-packages/empyrical/stats.py in calmar_ratio(returns, period, annualization)
363
364 max_dd = max_drawdown(returns=returns)
--> 365 if max_dd < 0:
366 temp = annual_return(
367 returns=returns,
/media/avinash/infotainment/projects/github/mypyfolio/lib/python3.5/site-packages/pandas/core/generic.py in __nonzero__(self)
915 raise ValueError("The truth value of a {0} is ambiguous. "
916 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
--> 917 .format(self.__class__.__name__))
918
919 __bool__ = __nonzero__
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
In [10]: emp.calmar_ratio(pd.Series(data).values)
Out[10]: 26.411425065382151
In [11]: np.nanmin(pd.Series(data))
Out[11]:
0 -0.2
1 -0.2
2 -0.2
3 -0.2
dtype: float6 Python 3.5.2 (default, Nov 17 2016, 17:05:23)
Type "copyright", "credits" or "license" for more information.
IPython 5.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: pd.__version__
Out[3]: '0.12.0'
In [4]: np.__version__
Out[4]: '1.12.1'
In [5]: data = [0.1, -0.2, 0.3, -0.1]
In [6]: np.nanmin(pd.Series(data))
Out[6]: -0.20000000000000001 |
Ok, I believe I've figured out why I wasn't seeing your behavior. I've got bottleneck installed, whose
|
You cracked it! Turns out I'd cloned empyrical and linked it to a virtual environment manually. It is working as expected after installing bottleneck. Closing the PR. Python 3.5.2 (default, Nov 17 2016, 17:05:23)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.0.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: import empyrical as emp
In [4]: pd.__version__
Out[4]: '0.19.2'
In [5]: np.__version__
Out[5]: '1.12.1'
In [6]: data = [0.1, -0.2, 0.3, -0.1]
In [7]: emp.calmar_ratio(pd.Series(data))
Out[7]: 26.411425065382151 |
Awesome! |
To handle the case #43 where object to be returned from
max_drawdown
may be Series/ndarray, invokedmin
on it. If it is already a float scalar thenAttributeError
will be raised and appropriately handled.