Merge branch 'develop' into verify_date_on_new_candle_on_get_signal

This commit is contained in:
hroff-1902 2020-05-20 14:05:21 +03:00 committed by GitHub
commit 8bf38443c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 36 deletions

View File

@ -3,7 +3,6 @@ PairList Handler base class
""" """
import logging import logging
from abc import ABC, abstractmethod, abstractproperty from abc import ABC, abstractmethod, abstractproperty
from copy import deepcopy
from typing import Any, Dict, List from typing import Any, Dict, List
from cachetools import TTLCache, cached from cachetools import TTLCache, cached
@ -87,38 +86,14 @@ class IPairList(ABC):
:return: new whitelist :return: new whitelist
""" """
@staticmethod def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]:
def verify_blacklist(pairlist: List[str], blacklist: List[str],
aswarning: bool) -> List[str]:
"""
Verify and remove items from pairlist - returning a filtered pairlist.
Logs a warning or info depending on `aswarning`.
Pairlist Handlers explicitly using this method shall use `aswarning=False`!
:param pairlist: Pairlist to validate
:param blacklist: Blacklist to validate pairlist against
:param aswarning: Log message as Warning or Info
:return: pairlist - blacklisted pairs
"""
for pair in deepcopy(pairlist):
if pair in blacklist:
if aswarning:
logger.warning(f"Pair {pair} in your blacklist. Removing it from whitelist...")
else:
logger.info(f"Pair {pair} in your blacklist. Removing it from whitelist...")
pairlist.remove(pair)
return pairlist
def _verify_blacklist(self, pairlist: List[str], aswarning: bool = True) -> List[str]:
""" """
Proxy method to verify_blacklist for easy access for child classes. Proxy method to verify_blacklist for easy access for child classes.
Logs a warning or info depending on `aswarning`.
Pairlists explicitly using this method shall use aswarning=False!
:param pairlist: Pairlist to validate :param pairlist: Pairlist to validate
:param aswarning: Log message as Warning or info. :param logmethod: Function that'll be called, `logger.info` or `logger.warning`.
:return: pairlist - blacklisted pairs :return: pairlist - blacklisted pairs
""" """
return IPairList.verify_blacklist(pairlist, self._pairlistmanager.blacklist, return self._pairlistmanager.verify_blacklist(pairlist, logmethod)
aswarning=aswarning)
def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]: def _whitelist_for_active_markets(self, pairlist: List[str]) -> List[str]:
""" """

View File

@ -115,7 +115,7 @@ class VolumePairList(IPairList):
# Validate whitelist to only have active market pairs # Validate whitelist to only have active market pairs
pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers]) pairs = self._whitelist_for_active_markets([s['symbol'] for s in sorted_tickers])
pairs = self._verify_blacklist(pairs, aswarning=False) pairs = self.verify_blacklist(pairs, logger.info)
# Limit pairlist to the requested number of pairs # Limit pairlist to the requested number of pairs
pairs = pairs[:self._number_pairs] pairs = pairs[:self._number_pairs]

View File

@ -93,7 +93,7 @@ class PairListManager():
# Validation against blacklist happens after the chain of Pairlist Handlers # Validation against blacklist happens after the chain of Pairlist Handlers
# to ensure blacklist is respected. # to ensure blacklist is respected.
pairlist = IPairList.verify_blacklist(pairlist, self.blacklist, True) pairlist = self.verify_blacklist(pairlist, logger.warning)
self._whitelist = pairlist self._whitelist = pairlist
@ -110,6 +110,22 @@ class PairListManager():
return pairlist return pairlist
def verify_blacklist(self, pairlist: List[str], logmethod) -> List[str]:
"""
Verify and remove items from pairlist - returning a filtered pairlist.
Logs a warning or info depending on `aswarning`.
Pairlist Handlers explicitly using this method shall use
`logmethod=logger.info` to avoid spamming with warning messages
:param pairlist: Pairlist to validate
:param logmethod: Function that'll be called, `logger.info` or `logger.warning`.
:return: pairlist - blacklisted pairs
"""
for pair in deepcopy(pairlist):
if pair in self._blacklist:
logmethod(f"Pair {pair} in your blacklist. Removing it from whitelist...")
pairlist.remove(pair)
return pairlist
def create_pair_list(self, pairs: List[str], timeframe: str = None) -> ListPairsWithTimeframes: def create_pair_list(self, pairs: List[str], timeframe: str = None) -> ListPairsWithTimeframes:
""" """
Create list of pair tuples with (pair, ticker_interval) Create list of pair tuples with (pair, ticker_interval)

View File

@ -310,7 +310,6 @@ class IStrategy(ABC):
logger.warning('Empty candle (OHLCV) data for pair %s', pair) logger.warning('Empty candle (OHLCV) data for pair %s', pair)
return False, False return False, False
latest_date = dataframe['date'].max()
try: try:
df_len, df_close, df_date = self.preserve_df(dataframe) df_len, df_close, df_date = self.preserve_df(dataframe)
dataframe = strategy_safe_wrapper( dataframe = strategy_safe_wrapper(
@ -326,25 +325,25 @@ class IStrategy(ABC):
logger.warning('Empty dataframe for pair %s', pair) logger.warning('Empty dataframe for pair %s', pair)
return False, False return False, False
latest_date = dataframe['date'].max()
latest = dataframe.loc[dataframe['date'] == latest_date].iloc[-1] latest = dataframe.loc[dataframe['date'] == latest_date].iloc[-1]
signal_date = arrow.get(latest['date'])
interval_minutes = timeframe_to_minutes(interval) interval_minutes = timeframe_to_minutes(interval)
# Check if dataframe is out of date # Check if dataframe is out of date
offset = self.config.get('exchange', {}).get('outdated_offset', 5) offset = self.config.get('exchange', {}).get('outdated_offset', 5)
if signal_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + offset))): if latest_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + offset))):
logger.warning( logger.warning(
'Outdated history for pair %s. Last tick is %s minutes old', 'Outdated history for pair %s. Last tick is %s minutes old',
pair, pair,
int((arrow.utcnow() - signal_date).total_seconds() // 60) int((arrow.utcnow() - latest_date).total_seconds() // 60)
) )
return False, False return False, False
# Check if dataframe has new candle # Check if dataframe has new candle
if (arrow.utcnow() - signal_date).total_seconds() // 60 >= interval_minutes: if (arrow.utcnow() - latest_date).total_seconds() // 60 >= interval_minutes:
logger.warning('Old candle for pair %s. Last candle is %s minutes old', logger.warning('Old candle for pair %s. Last candle is %s minutes old',
pair, int((arrow.utcnow() - signal_date).total_seconds() // 60)) pair, int((arrow.utcnow() - latest_date).total_seconds() // 60))
return False, False return False, False
(buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1 (buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1