Renamd volatilityFilter to RangeStabilityFilter

This commit is contained in:
Matthias 2020-11-22 19:47:27 +01:00
parent 29c6a9263d
commit 8f1d2ff070
5 changed files with 41 additions and 41 deletions

View File

@ -69,8 +69,8 @@
{"method": "PriceFilter", "low_price_ratio": 0.01, "min_price": 0.00000010},
{"method": "SpreadFilter", "max_spread_ratio": 0.005},
{
"method": "VolatilityFilter",
"volatility_over_days": 10,
"method": "RangeStabilityFilter",
"lookback_days": 10,
"min_volatility": 0.01,
"refresh_period": 1440
}

View File

@ -19,7 +19,7 @@ Inactive markets are always removed from the resulting pairlist. Explicitly blac
* [`PriceFilter`](#pricefilter)
* [`ShuffleFilter`](#shufflefilter)
* [`SpreadFilter`](#spreadfilter)
* [`VolatilityFilter`](#volatilityfilter)
* [`RangeStabilityFilter`](#rangestabilityfilter)
!!! Tip "Testing pairlists"
Pairlist configurations can be quite tricky to get right. Best use the [`test-pairlist`](utils.md#test-pairlist) utility sub-command to test your configuration quickly.
@ -119,26 +119,26 @@ Example:
If `DOGE/BTC` maximum bid is 0.00000026 and minimum ask is 0.00000027, the ratio is calculated as: `1 - bid/ask ~= 0.037` which is `> 0.005` and this pair will be filtered out.
#### VolatilityFilter
#### RangeStabilityFilter
Removes pairs where the difference between lowest low and highest high over `volatility_over_days` days is below `min_volatility`. Since this is a filter that requires additional data, the results are cached for `refresh_period`.
Removes pairs where the difference between lowest low and highest high over `lookback_days` days is below `min_rate_of_change`. Since this is a filter that requires additional data, the results are cached for `refresh_period`.
In the below example:
If volatility over the last 10 days is <1%, remove the pair from the whitelist.
If the trading range over the last 10 days is <1%, remove the pair from the whitelist.
```json
"pairlists": [
{
"method": "VolatilityFilter",
"volatility_over_days": 10,
"min_volatility": 0.01,
"method": "RangeStabilityFilter",
"lookback_days": 10,
"min_rate_of_change": 0.01,
"refresh_period": 1440
}
]
```
!!! Tip
This Filter can be used to automatically remove stable coin pairs, which have a very low volatility, and are therefore extremely difficult to trade with profit.
This Filter can be used to automatically remove stable coin pairs, which have a very low trading range, and are therefore extremely difficult to trade with profit.
### Full example of Pairlist Handlers
@ -160,9 +160,9 @@ The below example blacklists `BNB/BTC`, uses `VolumePairList` with `20` assets,
{"method": "PriceFilter", "low_price_ratio": 0.01},
{"method": "SpreadFilter", "max_spread_ratio": 0.005},
{
"method": "VolatilityFilter",
"volatility_over_days": 10,
"min_volatility": 0.01,
"method": "RangeStabilityFilter",
"lookback_days": 10,
"min_rate_of_change": 0.01,
"refresh_period": 1440
},
{"method": "ShuffleFilter", "seed": 42}

View File

@ -25,7 +25,7 @@ HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss',
'SortinoHyperOptLoss', 'SortinoHyperOptLossDaily']
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
'AgeFilter', 'PrecisionFilter', 'PriceFilter',
'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter']
'RangeStabilityFilter', 'ShuffleFilter', 'SpreadFilter']
AVAILABLE_DATAHANDLERS = ['json', 'jsongz', 'hdf5']
DRY_RUN_WALLET = 1000
DATETIME_PRINT_FORMAT = '%Y-%m-%d %H:%M:%S'

View File

@ -15,23 +15,23 @@ from freqtrade.pairlist.IPairList import IPairList
logger = logging.getLogger(__name__)
class VolatilityFilter(IPairList):
class RangeStabilityFilter(IPairList):
def __init__(self, exchange, pairlistmanager,
config: Dict[str, Any], pairlistconfig: Dict[str, Any],
pairlist_pos: int) -> None:
super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
self._days = pairlistconfig.get('volatility_over_days', 10)
self._min_volatility = pairlistconfig.get('min_volatility', 0.01)
self._days = pairlistconfig.get('lookback_days', 10)
self._min_rate_of_change = pairlistconfig.get('min_rate_of_change', 0.01)
self._refresh_period = pairlistconfig.get('refresh_period', 1440)
self._pair_cache: TTLCache = TTLCache(maxsize=100, ttl=self._refresh_period)
if self._days < 1:
raise OperationalException("VolatilityFilter requires volatility_over_days to be >= 1")
raise OperationalException("RangeStabilityFilter requires lookback_days to be >= 1")
if self._days > exchange.ohlcv_candle_limit:
raise OperationalException("VolatilityFilter requires volatility_over_days to not "
raise OperationalException("RangeStabilityFilter requires lookback_days to not "
"exceed exchange max request size "
f"({exchange.ohlcv_candle_limit})")
@ -48,12 +48,12 @@ class VolatilityFilter(IPairList):
"""
Short whitelist method description - used for startup-messages
"""
return (f"{self.name} - Filtering pairs with volatility below {self._min_volatility} "
f"over the last {plural(self._days, 'day')}.")
return (f"{self.name} - Filtering pairs with rate of change below "
f"{self._min_rate_of_change} over the last {plural(self._days, 'day')}.")
def _validate_pair(self, ticker: Dict) -> bool:
"""
Validate volatility
Validate trading range
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, False if it should be removed
"""
@ -75,14 +75,14 @@ class VolatilityFilter(IPairList):
highest_high = daily_candles['high'].max()
lowest_low = daily_candles['low'].min()
pct_change = ((highest_high - lowest_low) / lowest_low) if lowest_low > 0 else 0
if pct_change >= self._min_volatility:
if pct_change >= self._min_rate_of_change:
result = True
else:
self.log_on_refresh(logger.info,
f"Removed {pair} from whitelist, "
f"because volatility over {plural(self._days, 'day')} is "
f"because rate of change over {plural(self._days, 'day')} is "
f"{pct_change:.3f}, which is below the "
f"threshold of {self._min_volatility}.")
f"threshold of {self._min_rate_of_change}.")
result = False
self._pair_cache[pair] = result

View File

@ -341,8 +341,8 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
{"method": "PriceFilter", "low_price_ratio": 0.02}],
"USDT", ['ETH/USDT', 'NANO/USDT']),
([{"method": "StaticPairList"},
{"method": "VolatilityFilter", "volatility_over_days": 10,
"min_volatility": 0.01, "refresh_period": 1440}],
{"method": "RangeStabilityFilter", "lookback_days": 10,
"min_rate_of_change": 0.01, "refresh_period": 1440}],
"BTC", ['ETH/BTC', 'TKN/BTC', 'HOT/BTC']),
])
def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, tickers,
@ -586,9 +586,9 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o
assert freqtrade.exchange.get_historic_ohlcv.call_count == previous_call_count
def test_volatilityfilter_checks(mocker, default_conf, markets, tickers):
def test_rangestabilityfilter_checks(mocker, default_conf, markets, tickers):
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'VolatilityFilter', 'volatility_over_days': 99999}]
{'method': 'RangeStabilityFilter', 'lookback_days': 99999}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets),
@ -597,27 +597,27 @@ def test_volatilityfilter_checks(mocker, default_conf, markets, tickers):
)
with pytest.raises(OperationalException,
match=r'VolatilityFilter requires volatility_over_days to not exceed '
match=r'RangeStabilityFilter requires lookback_days to not exceed '
r'exchange max request size \([0-9]+\)'):
get_patched_freqtradebot(mocker, default_conf)
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'VolatilityFilter', 'volatility_over_days': 0}]
{'method': 'RangeStabilityFilter', 'lookback_days': 0}]
with pytest.raises(OperationalException,
match='VolatilityFilter requires volatility_over_days to be >= 1'):
match='RangeStabilityFilter requires lookback_days to be >= 1'):
get_patched_freqtradebot(mocker, default_conf)
@pytest.mark.parametrize('min_volatility,expected_length', [
@pytest.mark.parametrize('min_rate_of_change,expected_length', [
(0.01, 5),
(0.05, 0), # Setting volatility to 5% removes all pairs from the whitelist.
(0.05, 0), # Setting rate_of_change to 5% removes all pairs from the whitelist.
])
def test_volatilityfilter_caching(mocker, markets, default_conf, tickers, ohlcv_history_list,
min_volatility, expected_length):
def test_rangestabilityfilter_caching(mocker, markets, default_conf, tickers, ohlcv_history_list,
min_rate_of_change, expected_length):
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'VolatilityFilter', 'volatility_over_days': 2,
'min_volatility': min_volatility}]
{'method': 'RangeStabilityFilter', 'lookback_days': 2,
'min_rate_of_change': min_rate_of_change}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets),
@ -677,9 +677,9 @@ def test_volatilityfilter_caching(mocker, markets, default_conf, tickers, ohlcv_
None,
"PriceFilter requires max_price to be >= 0"
), # OperationalException expected
({"method": "VolatilityFilter", "volatility_over_days": 10, "min_volatility": 0.01},
"[{'VolatilityFilter': 'VolatilityFilter - Filtering pairs with volatility below 0.01 "
"over the last days.'}]",
({"method": "RangeStabilityFilter", "lookback_days": 10, "min_rate_of_change": 0.01},
"[{'RangeStabilityFilter': 'RangeStabilityFilter - Filtering pairs with rate of change below "
"0.01 over the last days.'}]",
None
),
])