mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-01-20 05:50:36 +00:00
Simplify rangeStability Filter
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
Rate of change pairlist filter
|
||||
"""
|
||||
import logging
|
||||
from copy import deepcopy
|
||||
from datetime import timedelta
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from cachetools import TTLCache
|
||||
from pandas import DataFrame
|
||||
@@ -103,45 +102,55 @@ class RangeStabilityFilter(IPairList):
|
||||
since_ms = dt_ts(dt_floor_day(dt_now()) - timedelta(days=self._days + 1))
|
||||
candles = self._exchange.refresh_ohlcv_with_cache(needed_pairs, since_ms=since_ms)
|
||||
|
||||
if self._enabled:
|
||||
for p in deepcopy(pairlist):
|
||||
daily_candles = candles[(p, '1d', self._def_candletype)] if (
|
||||
p, '1d', self._def_candletype) in candles else None
|
||||
if not self._validate_pair_loc(p, daily_candles):
|
||||
pairlist.remove(p)
|
||||
return pairlist
|
||||
resulting_pairlist: List[str] = []
|
||||
|
||||
def _validate_pair_loc(self, pair: str, daily_candles: Optional[DataFrame]) -> bool:
|
||||
"""
|
||||
Validate trading range
|
||||
:param pair: Pair that's currently validated
|
||||
:param daily_candles: Downloaded daily candles
|
||||
:return: True if the pair can stay, false if it should be removed
|
||||
"""
|
||||
for p in pairlist:
|
||||
daily_candles = candles.get((p, '1d', self._def_candletype), None)
|
||||
|
||||
pct_change = self._calculate_rate_of_change(p, daily_candles)
|
||||
|
||||
if pct_change is not None and self._validate_pair_loc(p, pct_change):
|
||||
resulting_pairlist.append(p)
|
||||
else:
|
||||
self.log_once(f"Removed {p} from whitelist, no candles found.", logger.info)
|
||||
|
||||
return resulting_pairlist
|
||||
|
||||
def _calculate_rate_of_change(self, pair: str, daily_candles: DataFrame) -> float:
|
||||
# Check symbol in cache
|
||||
if (cached_res := self._pair_cache.get(pair, None)) is not None:
|
||||
return cached_res
|
||||
|
||||
result = True
|
||||
if (pct_change := self._pair_cache.get(pair, None)) is not None:
|
||||
return pct_change
|
||||
if daily_candles is not None and not daily_candles.empty:
|
||||
|
||||
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_rate_of_change:
|
||||
self.log_once(f"Removed {pair} from whitelist, because rate of change "
|
||||
f"over {self._days} {plural(self._days, 'day')} is {pct_change:.3f}, "
|
||||
f"which is below the threshold of {self._min_rate_of_change}.",
|
||||
logger.info)
|
||||
result = False
|
||||
if self._max_rate_of_change:
|
||||
if pct_change > self._max_rate_of_change:
|
||||
self.log_once(
|
||||
f"Removed {pair} from whitelist, because rate of change "
|
||||
f"over {self._days} {plural(self._days, 'day')} is {pct_change:.3f}, "
|
||||
f"which is above the threshold of {self._max_rate_of_change}.",
|
||||
logger.info)
|
||||
result = False
|
||||
self._pair_cache[pair] = result
|
||||
self._pair_cache[pair] = pct_change
|
||||
return pct_change
|
||||
else:
|
||||
self.log_once(f"Removed {pair} from whitelist, no candles found.", logger.info)
|
||||
return None
|
||||
|
||||
def _validate_pair_loc(self, pair: str, pct_change: float) -> bool:
|
||||
"""
|
||||
Validate trading range
|
||||
:param pair: Pair that's currently validated
|
||||
:param pct_change: Rate of change
|
||||
:return: True if the pair can stay, false if it should be removed
|
||||
"""
|
||||
|
||||
result = True
|
||||
if pct_change < self._min_rate_of_change:
|
||||
self.log_once(f"Removed {pair} from whitelist, because rate of change "
|
||||
f"over {self._days} {plural(self._days, 'day')} is {pct_change:.3f}, "
|
||||
f"which is below the threshold of {self._min_rate_of_change}.",
|
||||
logger.info)
|
||||
result = False
|
||||
if self._max_rate_of_change:
|
||||
if pct_change > self._max_rate_of_change:
|
||||
self.log_once(
|
||||
f"Removed {pair} from whitelist, because rate of change "
|
||||
f"over {self._days} {plural(self._days, 'day')} is {pct_change:.3f}, "
|
||||
f"which is above the threshold of {self._max_rate_of_change}.",
|
||||
logger.info)
|
||||
result = False
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user