VolatilityFilter resolves freqtrade/freqtrade#4650
This commit is contained in:
parent
1733e24062
commit
187cf6dcd5
@ -67,7 +67,7 @@ class VolatilityFilter(IPairList):
|
|||||||
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
|
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
|
||||||
:return: new allowlist
|
:return: new allowlist
|
||||||
"""
|
"""
|
||||||
needed_pairs = [(p, '1h') for p in pairlist if p not in self._pair_cache]
|
needed_pairs = [(p, '1d') for p in pairlist if p not in self._pair_cache]
|
||||||
|
|
||||||
since_ms = int(arrow.utcnow()
|
since_ms = int(arrow.utcnow()
|
||||||
.floor('day')
|
.floor('day')
|
||||||
@ -81,7 +81,7 @@ class VolatilityFilter(IPairList):
|
|||||||
|
|
||||||
if self._enabled:
|
if self._enabled:
|
||||||
for p in deepcopy(pairlist):
|
for p in deepcopy(pairlist):
|
||||||
daily_candles = candles[(p, '1h')] if (p, '1h') in candles else None
|
daily_candles = candles[(p, '1d')] if (p, '1d') in candles else None
|
||||||
if not self._validate_pair_loc(p, daily_candles):
|
if not self._validate_pair_loc(p, daily_candles):
|
||||||
pairlist.remove(p)
|
pairlist.remove(p)
|
||||||
return pairlist
|
return pairlist
|
||||||
@ -102,7 +102,7 @@ class VolatilityFilter(IPairList):
|
|||||||
returns = (np.log(daily_candles.close / daily_candles.close.shift(-1)))
|
returns = (np.log(daily_candles.close / daily_candles.close.shift(-1)))
|
||||||
returns.fillna(0, inplace=True)
|
returns.fillna(0, inplace=True)
|
||||||
|
|
||||||
volatility_series = returns.rolling(window=self._days*24).std()*np.sqrt(self._days*24)
|
volatility_series = returns.rolling(window=self._days).std()*np.sqrt(self._days)
|
||||||
volatility_avg = volatility_series.mean()
|
volatility_avg = volatility_series.mean()
|
||||||
|
|
||||||
if self._min_volatility <= volatility_avg <= self._max_volatility:
|
if self._min_volatility <= volatility_avg <= self._max_volatility:
|
||||||
|
@ -407,6 +407,10 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
|
|||||||
{"method": "RangeStabilityFilter", "lookback_days": 10,
|
{"method": "RangeStabilityFilter", "lookback_days": 10,
|
||||||
"min_rate_of_change": 0.01, "refresh_period": 1440}],
|
"min_rate_of_change": 0.01, "refresh_period": 1440}],
|
||||||
"BTC", ['ETH/BTC', 'TKN/BTC', 'HOT/BTC']),
|
"BTC", ['ETH/BTC', 'TKN/BTC', 'HOT/BTC']),
|
||||||
|
([{"method": "StaticPairList"},
|
||||||
|
{"method": "VolatilityFilter", "lookback_days": 3,
|
||||||
|
"min_volatility": 0.002, "max_volatility": 0.004, "refresh_period": 1440}],
|
||||||
|
"BTC", ['ETH/BTC', 'TKN/BTC'])
|
||||||
])
|
])
|
||||||
def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, tickers,
|
def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, tickers,
|
||||||
ohlcv_history, pairlists, base_currency,
|
ohlcv_history, pairlists, base_currency,
|
||||||
@ -414,14 +418,20 @@ def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, t
|
|||||||
whitelist_conf['pairlists'] = pairlists
|
whitelist_conf['pairlists'] = pairlists
|
||||||
whitelist_conf['stake_currency'] = base_currency
|
whitelist_conf['stake_currency'] = base_currency
|
||||||
|
|
||||||
|
ohlcv_history_high_vola = ohlcv_history.copy()
|
||||||
|
ohlcv_history_high_vola.loc[ohlcv_history_high_vola.index==1, 'close'] = 0.00090
|
||||||
|
|
||||||
ohlcv_data = {
|
ohlcv_data = {
|
||||||
('ETH/BTC', '1d'): ohlcv_history,
|
('ETH/BTC', '1d'): ohlcv_history,
|
||||||
('TKN/BTC', '1d'): ohlcv_history,
|
('TKN/BTC', '1d'): ohlcv_history,
|
||||||
('LTC/BTC', '1d'): ohlcv_history,
|
('LTC/BTC', '1d'): ohlcv_history,
|
||||||
('XRP/BTC', '1d'): ohlcv_history,
|
('XRP/BTC', '1d'): ohlcv_history,
|
||||||
('HOT/BTC', '1d'): ohlcv_history,
|
('HOT/BTC', '1d'): ohlcv_history_high_vola,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
|
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
|
||||||
|
|
||||||
if whitelist_result == 'static_in_the_middle':
|
if whitelist_result == 'static_in_the_middle':
|
||||||
@ -487,7 +497,8 @@ def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, t
|
|||||||
assert log_has(logmsg, caplog)
|
assert log_has(logmsg, caplog)
|
||||||
else:
|
else:
|
||||||
assert not log_has(logmsg, caplog)
|
assert not log_has(logmsg, caplog)
|
||||||
|
if pairlist["method"] == 'VolatilityFilter':
|
||||||
|
assert log_has_re(r'^Removed .* from whitelist, because volatility.*$', caplog)
|
||||||
|
|
||||||
def test_PrecisionFilter_error(mocker, whitelist_conf) -> None:
|
def test_PrecisionFilter_error(mocker, whitelist_conf) -> None:
|
||||||
whitelist_conf['pairlists'] = [{"method": "StaticPairList"}, {"method": "PrecisionFilter"}]
|
whitelist_conf['pairlists'] = [{"method": "StaticPairList"}, {"method": "PrecisionFilter"}]
|
||||||
|
Loading…
Reference in New Issue
Block a user