stable/freqtrade/pairlist/PrecisionFilter.py

75 lines
2.8 KiB
Python
Raw Normal View History

2019-10-30 14:59:52 +00:00
import logging
from copy import deepcopy
2020-05-15 01:17:23 +00:00
from typing import Any, Dict, List
2019-10-30 14:59:52 +00:00
2019-11-09 05:55:16 +00:00
from freqtrade.pairlist.IPairList import IPairList
2019-10-30 14:59:52 +00:00
logger = logging.getLogger(__name__)
2019-11-09 05:55:16 +00:00
class PrecisionFilter(IPairList):
2019-10-30 14:59:52 +00:00
2020-05-15 01:17:23 +00:00
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._stoploss = self._config.get('stoploss')
if self._stoploss is not None:
# Precalculate sanitized stoploss value to avoid recalculation for every pair
self._stoploss = 1 - abs(self._stoploss)
@property
def needstickers(self) -> bool:
"""
Boolean property defining if tickers are necessary.
If no Pairlist requries tickers, an empty List is passed
as tickers argument to filter_pairlist
"""
return True
2019-11-09 05:55:16 +00:00
def short_desc(self) -> str:
"""
Short whitelist method description - used for startup-messages
"""
return f"{self.name} - Filtering untradable pairs."
2019-10-30 14:59:52 +00:00
def _validate_precision_filter(self, ticker: dict, stoploss: float) -> bool:
"""
Check if pair has enough room to add a stoploss to avoid "unsellable" buys of very
low value pairs.
:param ticker: ticker dict as returned from ccxt.load_markets()
:param stoploss: stoploss value as set in the configuration
(already cleaned to be 1 - stoploss)
2020-05-15 02:14:06 +00:00
:return: True if the pair can stay, False if it should be removed
2019-10-30 14:59:52 +00:00
"""
2019-11-09 08:07:46 +00:00
stop_price = ticker['ask'] * stoploss
2020-05-15 01:24:18 +00:00
2019-10-30 14:59:52 +00:00
# Adjust stop-prices to precision
sp = self._exchange.price_to_precision(ticker["symbol"], stop_price)
2020-05-15 01:24:18 +00:00
stop_gap_price = self._exchange.price_to_precision(ticker["symbol"], stop_price * 0.99)
2019-10-30 14:59:52 +00:00
logger.debug(f"{ticker['symbol']} - {sp} : {stop_gap_price}")
2020-05-15 01:24:18 +00:00
2019-10-30 14:59:52 +00:00
if sp <= stop_gap_price:
self.log_on_refresh(logger.info,
f"Removed {ticker['symbol']} from whitelist, "
f"because stop price {sp} would be <= stop limit {stop_gap_price}")
2019-10-30 14:59:52 +00:00
return False
2020-05-15 01:24:18 +00:00
2019-10-30 14:59:52 +00:00
return True
2019-11-09 12:40:36 +00:00
def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
2019-10-30 14:59:52 +00:00
"""
2019-11-09 05:55:16 +00:00
Filters and sorts pairlists and assigns and returns them again.
2019-10-30 14:59:52 +00:00
"""
2020-05-15 02:14:06 +00:00
if self._stoploss:
# Copy list since we're modifying this list
for p in deepcopy(pairlist):
ticker = tickers[p]
# Filter out assets which would not allow setting a stoploss
if not self._validate_precision_filter(ticker, self._stoploss):
pairlist.remove(p)
2019-10-30 14:59:52 +00:00
return pairlist