Provide pair to _validate_pairs in pairlists

This commit is contained in:
Matthias 2020-12-15 08:36:42 +01:00
parent 39fec25ae0
commit 69901c1314
6 changed files with 25 additions and 20 deletions

View File

@ -49,11 +49,12 @@ class AgeFilter(IPairList):
return (f"{self.name} - Filtering pairs with age less than "
f"{self._min_days_listed} {plural(self._min_days_listed, 'day')}.")
def _validate_pair(self, ticker: Dict) -> bool:
def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool:
"""
Validate age for the ticker
:param pair: Pair that's currently validated
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, False if it should be removed
:return: True if the pair can stay, false if it should be removed
"""
# Check symbol in cache

View File

@ -60,13 +60,14 @@ class IPairList(LoggingMixin, ABC):
-> Please overwrite in subclasses
"""
def _validate_pair(self, ticker) -> bool:
def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool:
"""
Check one pair against Pairlist Handler's specific conditions.
Either implement it in the Pairlist Handler or override the generic
filter_pairlist() method.
:param pair: Pair that's currently validated
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, false if it should be removed
"""
@ -109,7 +110,7 @@ class IPairList(LoggingMixin, ABC):
# Copy list since we're modifying this list
for p in deepcopy(pairlist):
# Filter out assets
if not self._validate_pair(tickers[p]):
if not self._validate_pair(p, tickers[p] if p in tickers else {}):
pairlist.remove(p)
return pairlist

View File

@ -43,19 +43,20 @@ class PrecisionFilter(IPairList):
"""
return f"{self.name} - Filtering untradable pairs."
def _validate_pair(self, ticker: dict) -> bool:
def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool:
"""
Check if pair has enough room to add a stoploss to avoid "unsellable" buys of very
low value pairs.
:param pair: Pair that's currently validated
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, False if it should be removed
:return: True if the pair can stay, false if it should be removed
"""
stop_price = ticker['ask'] * self._stoploss
# Adjust stop-prices to precision
sp = self._exchange.price_to_precision(ticker["symbol"], stop_price)
sp = self._exchange.price_to_precision(pair, stop_price)
stop_gap_price = self._exchange.price_to_precision(ticker["symbol"], stop_price * 0.99)
stop_gap_price = self._exchange.price_to_precision(pair, stop_price * 0.99)
logger.debug(f"{ticker['symbol']} - {sp} : {stop_gap_price}")
if sp <= stop_gap_price:

View File

@ -57,31 +57,32 @@ class PriceFilter(IPairList):
return f"{self.name} - No price filters configured."
def _validate_pair(self, ticker) -> bool:
def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool:
"""
Check if if one price-step (pip) is > than a certain barrier.
:param pair: Pair that's currently validated
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, false if it should be removed
"""
if ticker['last'] is None or ticker['last'] == 0:
self.log_once(f"Removed {ticker['symbol']} from whitelist, because "
self.log_once(f"Removed {pair} from whitelist, because "
"ticker['last'] is empty (Usually no trade in the last 24h).",
logger.info)
return False
# Perform low_price_ratio check.
if self._low_price_ratio != 0:
compare = self._exchange.price_get_one_pip(ticker['symbol'], ticker['last'])
compare = self._exchange.price_get_one_pip(pair, ticker['last'])
changeperc = compare / ticker['last']
if changeperc > self._low_price_ratio:
self.log_once(f"Removed {ticker['symbol']} from whitelist, "
self.log_once(f"Removed {pair} from whitelist, "
f"because 1 unit is {changeperc * 100:.3f}%", logger.info)
return False
# Perform min_price check.
if self._min_price != 0:
if ticker['last'] < self._min_price:
self.log_once(f"Removed {ticker['symbol']} from whitelist, "
self.log_once(f"Removed {pair} from whitelist, "
f"because last price < {self._min_price:.8f}", logger.info)
return False

View File

@ -36,16 +36,17 @@ class SpreadFilter(IPairList):
return (f"{self.name} - Filtering pairs with ask/bid diff above "
f"{self._max_spread_ratio * 100}%.")
def _validate_pair(self, ticker: dict) -> bool:
def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool:
"""
Validate spread for the ticker
:param pair: Pair that's currently validated
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, False if it should be removed
:return: True if the pair can stay, false if it should be removed
"""
if 'bid' in ticker and 'ask' in ticker:
spread = 1 - ticker['bid'] / ticker['ask']
if spread > self._max_spread_ratio:
self.log_once(f"Removed {ticker['symbol']} from whitelist, because spread "
self.log_once(f"Removed {pair} from whitelist, because spread "
f"{spread * 100:.3f}% > {self._max_spread_ratio * 100}%",
logger.info)
return False

View File

@ -42,7 +42,7 @@ class RangeStabilityFilter(IPairList):
If no Pairlist requires tickers, an empty List is passed
as tickers argument to filter_pairlist
"""
return True
return False
def short_desc(self) -> str:
"""
@ -51,13 +51,13 @@ class RangeStabilityFilter(IPairList):
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:
def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool:
"""
Validate trading range
:param pair: Pair that's currently validated
:param ticker: ticker dict as returned from ccxt.load_markets()
:return: True if the pair can stay, False if it should be removed
:return: True if the pair can stay, false if it should be removed
"""
pair = ticker['symbol']
# Check symbol in cache
if pair in self._pair_cache:
return self._pair_cache[pair]