stable/freqtrade/pairlist/IPairList.py
2019-10-30 15:59:52 +01:00

114 lines
3.9 KiB
Python

"""
Static List provider
Provides lists as configured in config.json
"""
import logging
from abc import ABC, abstractmethod
from typing import Dict, List
from freqtrade.exchange import market_is_active
from freqtrade.pairlist.IPairListFilter import IPairListFilter
from freqtrade.resolvers.pairlistfilter_resolver import PairListFilterResolver
logger = logging.getLogger(__name__)
class IPairList(ABC):
def __init__(self, freqtrade, config: dict) -> None:
self._freqtrade = freqtrade
self._config = config
self._whitelist = self._config['exchange']['pair_whitelist']
self._blacklist = self._config['exchange'].get('pair_blacklist', [])
self._filters = self._config.get('pairlist', {}).get('filters', {})
self._pairlistfilters: List[IPairListFilter] = []
for pl_filter in self._filters.keys():
self._pairlistfilters.append(
PairListFilterResolver(pl_filter, freqtrade, self._config).pairlistfilter
)
@property
def name(self) -> str:
"""
Gets name of the class
-> no need to overwrite in subclasses
"""
return self.__class__.__name__
@property
def whitelist(self) -> List[str]:
"""
Has the current whitelist
-> no need to overwrite in subclasses
"""
return self._whitelist
@property
def blacklist(self) -> List[str]:
"""
Has the current blacklist
-> no need to overwrite in subclasses
"""
return self._blacklist
@abstractmethod
def short_desc(self) -> str:
"""
Short whitelist method description - used for startup-messages
-> Please overwrite in subclasses
"""
@abstractmethod
def refresh_pairlist(self) -> None:
"""
Refreshes pairlists and assigns them to self._whitelist and self._blacklist respectively
-> Please overwrite in subclasses
"""
def validate_whitelist(self, pairlist: List[str],
tickers: List[Dict] = []) -> List[str]:
"""
Validate pairlist against active markets and blacklist.
Run PairlistFilters if these are configured.
"""
pairlist = self._whitelist_for_active_markets(pairlist)
if not tickers:
# Refresh tickers if they are not used by the parent Pairlist
tickers = self._freqtrade.exchange.get_tickers()
for pl_filter in self._pairlistfilters:
pairlist = pl_filter.filter_pairlist(pairlist, tickers)
return pairlist
def _whitelist_for_active_markets(self, whitelist: List[str]) -> List[str]:
"""
Check available markets and remove pair from whitelist if necessary
:param whitelist: the sorted list of pairs the user might want to trade
:return: the list of pairs the user wants to trade without those unavailable or
black_listed
"""
markets = self._freqtrade.exchange.markets
sanitized_whitelist: List[str] = []
for pair in whitelist:
# pair is not in the generated dynamic market, or in the blacklist ... ignore it
if (pair in self.blacklist or pair not in markets
or not pair.endswith(self._config['stake_currency'])):
logger.warning(f"Pair {pair} is not compatible with exchange "
f"{self._freqtrade.exchange.name} or contained in "
f"your blacklist. Removing it from whitelist..")
continue
# Check if market is active
market = markets[pair]
if not market_is_active(market):
logger.info(f"Ignoring {pair} from whitelist. Market is not active.")
continue
if pair not in sanitized_whitelist:
sanitized_whitelist.append(pair)
# We need to remove pairs that are unknown
return sanitized_whitelist