Safer exit_tag is not None check

the comparison using `is not None` fails if the column  `exit_tag` is stored with the more efficient dtype `Sparse[string]`. The reason is that none values are stored as np.nan which is a float. This would raise an error when `len` is called at the next condition.

```
2022-01-18 15:18:22,548 - freqtrade - ERROR - Fatal exception!
joblib.externals.loky.process_executor._RemoteTraceback: 
"""
Traceback (most recent call last):
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/externals/loky/process_executor.py", line 436, in _process_worker
    r = call_item()
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/externals/loky/process_executor.py", line 288, in __call__
    return self.fn(*self.args, **self.kwargs)
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/_parallel_backends.py", line 595, in __call__
    return self.func(*args, **kwargs)
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/parallel.py", line 262, in __call__
    return [func(*args, **kwargs)
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/parallel.py", line 262, in <listcomp>
    return [func(*args, **kwargs)
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/externals/loky/cloudpickle_wrapper.py", line 38, in __call__
    return self._obj(*args, **kwargs)
  File "/freqtrade/freqtrade/optimize/hyperopt.py", line 317, in generate_optimizer
    bt_results = self.backtesting.backtest(
  File "/freqtrade/freqtrade/optimize/backtesting.py", line 658, in backtest
    trade_entry = self._get_sell_trade_entry(trade, row)
  File "/freqtrade/freqtrade/optimize/backtesting.py", line 461, in _get_sell_trade_entry
    return self._get_sell_trade_entry_for_candle(trade, sell_row)
  File "/freqtrade/freqtrade/optimize/backtesting.py", line 426, in _get_sell_trade_entry_for_candle
    and len(sell_row[EXIT_TAG_IDX]) > 0
TypeError: object of type 'float' has no len()
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/freqtrade/freqtrade/main.py", line 37, in main
    return_code = args['func'](args)
  File "/freqtrade/freqtrade/commands/optimize_commands.py", line 103, in start_hyperopt
    hyperopt.start()
  File "/freqtrade/freqtrade/optimize/hyperopt.py", line 482, in start
    f_val = self.run_optimizer_parallel(parallel, asked, i)
  File "/freqtrade/freqtrade/optimize/hyperopt.py", line 396, in run_optimizer_parallel
    return parallel(delayed(
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/parallel.py", line 1056, in __call__
    self.retrieve()
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/parallel.py", line 935, in retrieve
    self._output.extend(job.get(timeout=self.timeout))
  File "/home/ftuser/.local/lib/python3.9/site-packages/joblib/_parallel_backends.py", line 542, in wrap_future_result
    return future.result(timeout=timeout)
  File "/usr/local/lib/python3.9/concurrent/futures/_base.py", line 445, in result
    return self.__get_result()
  File "/usr/local/lib/python3.9/concurrent/futures/_base.py", line 390, in __get_result
    raise self._exception
TypeError: object of type 'float' has no len()
ERROR: 1
```
This commit is contained in:
Italo 2022-01-18 15:29:59 +00:00 committed by GitHub
parent 301b2e8a0f
commit 5f1235a031
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,7 +9,7 @@ from copy import deepcopy
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
from pandas import DataFrame from pandas import DataFrame, notna
from freqtrade.configuration import TimeRange, validate_config_consistency from freqtrade.configuration import TimeRange, validate_config_consistency
from freqtrade.constants import DATETIME_PRINT_FORMAT from freqtrade.constants import DATETIME_PRINT_FORMAT
@ -420,7 +420,7 @@ class Backtesting:
# sell_row has the length for an exit tag column # sell_row has the length for an exit tag column
if( if(
len(sell_row) > EXIT_TAG_IDX len(sell_row) > EXIT_TAG_IDX
and sell_row[EXIT_TAG_IDX] is not None and notna(sell_row[EXIT_TAG_IDX])
and len(sell_row[EXIT_TAG_IDX]) > 0 and len(sell_row[EXIT_TAG_IDX]) > 0
): ):
trade.sell_reason = sell_row[EXIT_TAG_IDX] trade.sell_reason = sell_row[EXIT_TAG_IDX]