Merge branch 'develop' into verify_date_on_new_candle_on_get_signal
This commit is contained in:
commit
8bf38443c2
@ -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]:
|
||||||
"""
|
"""
|
||||||
|
@ -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]
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user