Simplify rangeStability Filter
This commit is contained in:
@@ -2,9 +2,8 @@
|
|||||||
Rate of change pairlist filter
|
Rate of change pairlist filter
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from copy import deepcopy
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
from cachetools import TTLCache
|
from cachetools import TTLCache
|
||||||
from pandas import DataFrame
|
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))
|
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)
|
candles = self._exchange.refresh_ohlcv_with_cache(needed_pairs, since_ms=since_ms)
|
||||||
|
|
||||||
if self._enabled:
|
resulting_pairlist: List[str] = []
|
||||||
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
|
|
||||||
|
|
||||||
def _validate_pair_loc(self, pair: str, daily_candles: Optional[DataFrame]) -> bool:
|
for p in pairlist:
|
||||||
"""
|
daily_candles = candles.get((p, '1d', self._def_candletype), None)
|
||||||
Validate trading range
|
|
||||||
:param pair: Pair that's currently validated
|
pct_change = self._calculate_rate_of_change(p, daily_candles)
|
||||||
:param daily_candles: Downloaded daily candles
|
|
||||||
:return: True if the pair can stay, false if it should be removed
|
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
|
# Check symbol in cache
|
||||||
if (cached_res := self._pair_cache.get(pair, None)) is not None:
|
if (pct_change := self._pair_cache.get(pair, None)) is not None:
|
||||||
return cached_res
|
return pct_change
|
||||||
|
|
||||||
result = True
|
|
||||||
if daily_candles is not None and not daily_candles.empty:
|
if daily_candles is not None and not daily_candles.empty:
|
||||||
|
|
||||||
highest_high = daily_candles['high'].max()
|
highest_high = daily_candles['high'].max()
|
||||||
lowest_low = daily_candles['low'].min()
|
lowest_low = daily_candles['low'].min()
|
||||||
pct_change = ((highest_high - lowest_low) / lowest_low) if lowest_low > 0 else 0
|
pct_change = ((highest_high - lowest_low) / lowest_low) if lowest_low > 0 else 0
|
||||||
if pct_change < self._min_rate_of_change:
|
self._pair_cache[pair] = pct_change
|
||||||
self.log_once(f"Removed {pair} from whitelist, because rate of change "
|
return pct_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
|
|
||||||
else:
|
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
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user