Repository: freqtrade/freqtrade

Issue:
cross_above problem with shift
<!-- 
Have you searched for similar issues before posting it?
Did you have a VERY good look at the [documentation](https://www.freqtrade.io/en/latest/) and are sure that the question is not explained there

Please do not use the question template to report bugs or to request new features.
-->

## Describe your environment

  * Operating system: Ubuntu 
  * Python Version: Python 3.8.2 (`python -V`)
  * CCXT version: ccxt==1.33.52 (`pip freeze | grep ccxt`)
  * Freqtrade Version: freqtrade develop-21f4aba4 (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
  
## Your question

Hello, 
I am having a problem with the cross_above function in qtpylib. I am trying to optimize one strategy but as soon as I run it I receive the following exception:

Traceback (most recent call last):
  File "/home/trademad/freqtrade/.env/lib/python3.8/site-packages/joblib/externals/loky/process_executor.py", line 431, in _process_worker
    r = call_item()
  File "/home/trademad/freqtrade/.env/lib/python3.8/site-packages/joblib/externals/loky/process_executor.py", line 285, in __call__
    return self.fn(*self.args, **self.kwargs)
  File "/home/trademad/freqtrade/.env/lib/python3.8/site-packages/joblib/_parallel_backends.py", line 595, in __call__
    return self.func(*args, **kwargs)
  File "/home/trademad/freqtrade/.env/lib/python3.8/site-packages/joblib/parallel.py", line 252, in __call__
    return [func(*args, **kwargs)
  File "/home/trademad/freqtrade/.env/lib/python3.8/site-packages/joblib/parallel.py", line 252, in <listcomp>
    return [func(*args, **kwargs)
  File "/home/trademad/freqtrade/.env/lib/python3.8/site-packages/joblib/externals/loky/cloudpickle_wrapper.py", line 38, in __call__
    return self._obj(*args, **kwargs)
  File "/home/trademad/freqtrade/freqtrade/optimize/hyperopt.py", line 532, in generate_optimizer
    backtesting_results = self.backtesting.backtest(
  File "/home/trademad/freqtrade/freqtrade/optimize/backtesting.py", line 312, in backtest
    data: Dict = self._get_ohlcv_as_lists(processed)
  File "/home/trademad/freqtrade/freqtrade/optimize/backtesting.py", line 164, in _get_ohlcv_as_lists
    self.strategy.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy()
  File "/home/trademad/freqtrade/user_data/hyperopts/bbrsi_opt_v01.py", line 61, in populate_buy_trend
    conditions.append(qtpylib.crossed_above(dataframe['rsi'], params['rsi-value']))
  File "/home/trademad/freqtrade/freqtrade/vendor/qtpylib/indicators.py", line 243, in crossed_above
    return crossed(series1, series2, "above")
  File "/home/trademad/freqtrade/freqtrade/vendor/qtpylib/indicators.py", line 230, in crossed
    series1.shift(1) <= series2.shift(1)))
AttributeError: 'numpy.int64' object has no attribute 'shift'

Could it be a problem with pandas in the latest version?
thanks

*Ask the question you have not been able to find an answer in our [Documentation](https://www.freqtrade.io/en/latest/)*



Discussion:
no, the problem is that a numpy.int64 is not really a integer, but it's "it's own" type.

``` python
In [1]: import numpy as np

In [2]: x = np.int64(111)                                                                                                              

In [3]: type(x)                                                                                                                        
Out[3]: numpy.int64

In [4]: isinstance(x, int)                                                                                                             
Out[4]: False

```

you should be able to get around this by using `qtpylib.crossed_above(dataframe['rsi'], int(params['rsi-value']))`


I'll however also fix it in the indicators library ... 

Resolving patch:
diff --git a/freqtrade/vendor/qtpylib/indicators.py b/freqtrade/vendor/qtpylib/indicators.py
--- a/freqtrade/vendor/qtpylib/indicators.py
+++ b/freqtrade/vendor/qtpylib/indicators.py
@@ -222,7 +222,7 @@ def crossed(series1, series2, direction=None):
     if isinstance(series1, np.ndarray):
         series1 = pd.Series(series1)
 
-    if isinstance(series2, (float, int, np.ndarray)):
+    if isinstance(series2, (float, int, np.ndarray, np.integer, np.floating)):
         series2 = pd.Series(index=series1.index, data=series2)
 
     if direction is None or direction == "above":


Test patch:
diff --git a/tests/test_indicators.py b/tests/test_indicators.py
new file mode 100644
--- /dev/null
+++ b/tests/test_indicators.py
@@ -0,0 +1,18 @@
+import freqtrade.vendor.qtpylib.indicators as qtpylib
+import numpy as np
+import pandas as pd
+
+
+def test_crossed_numpy_types():
+    """
+    This test is only present since this method currently diverges from the qtpylib implementation.
+    And we must ensure to not break this again once we update from the original source.
+    """
+    series = pd.Series([56, 97, 19, 76, 65, 25, 87, 91, 79, 79])
+    expected_result = pd.Series([False, True, False, True, False, False, True, False, False, False])
+
+    assert qtpylib.crossed_above(series, 60).equals(expected_result)
+    assert qtpylib.crossed_above(series, 60.0).equals(expected_result)
+    assert qtpylib.crossed_above(series, np.int32(60)).equals(expected_result)
+    assert qtpylib.crossed_above(series, np.int64(60)).equals(expected_result)
+    assert qtpylib.crossed_above(series, np.float64(60.0)).equals(expected_result)
diff --git a/tests/test_talib.py b/tests/test_talib.py
--- a/tests/test_talib.py
+++ b/tests/test_talib.py
@@ -1,5 +1,3 @@
-
-
 import talib.abstract as ta
 import pandas as pd