PercentegeRangeFilter added and constants.py updated
This commit is contained in:
parent
58b77bd15f
commit
893bc7a379
@ -27,7 +27,7 @@ HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss',
|
|||||||
'SortinoHyperOptLoss', 'SortinoHyperOptLossDaily',
|
'SortinoHyperOptLoss', 'SortinoHyperOptLossDaily',
|
||||||
'CalmarHyperOptLoss',
|
'CalmarHyperOptLoss',
|
||||||
'MaxDrawDownHyperOptLoss']
|
'MaxDrawDownHyperOptLoss']
|
||||||
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
|
AVAILABLE_PAIRLISTS = [ 'PercentegeRangeFilter', 'StaticPairList', 'VolumePairList',
|
||||||
'AgeFilter', 'OffsetFilter', 'PerformanceFilter',
|
'AgeFilter', 'OffsetFilter', 'PerformanceFilter',
|
||||||
'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter',
|
'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter',
|
||||||
'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter']
|
'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter']
|
||||||
|
149
freqtrade/plugins/pairlist/PercentegeRangeFilter.py
Normal file
149
freqtrade/plugins/pairlist/PercentegeRangeFilter.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import logging
|
||||||
|
from copy import deepcopy
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
from freqtrade.plugins.pairlist.IPairList import IPairList
|
||||||
|
|
||||||
|
import ccxt
|
||||||
|
from freqtrade.exceptions import OperationalException
|
||||||
|
|
||||||
|
"""
|
||||||
|
__author__ = kunthar@gmail.com
|
||||||
|
__license__ = "GPL3"
|
||||||
|
__version__ = "1.0.1"
|
||||||
|
|
||||||
|
Motivation: When you need to pull a definitive price range for pairs between certain
|
||||||
|
percentage ratios. Pairs can be selected to whatever percentage range needed by your strat.
|
||||||
|
|
||||||
|
Yes yes, docker image is also built. Please see here for pull
|
||||||
|
instructions and image details:
|
||||||
|
https://hub.docker.com/u/kunthar
|
||||||
|
|
||||||
|
How to use this filter.
|
||||||
|
1. Add below code under "pairlists": section in your config file:
|
||||||
|
Example:
|
||||||
|
|
||||||
|
{"method": "PercentegeRangeFilter",
|
||||||
|
"min_price_change": -1,
|
||||||
|
"max_price_change": 2
|
||||||
|
},
|
||||||
|
|
||||||
|
2. Add this filter definition to freqtrade/constants.py
|
||||||
|
AVAILABLE_PAIRLISTS = [ 'PercentegeRangeFilter', ...
|
||||||
|
|
||||||
|
Todo:
|
||||||
|
* More exchanges will be implemented in time.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Supported Exchanges listed below. You should implement your exchange,
|
||||||
|
# if it is not exist in the list!
|
||||||
|
exchange_name_list = ["binance", "kucoin", "gateio"]
|
||||||
|
|
||||||
|
|
||||||
|
class PercentegeRangeFilter(IPairList):
|
||||||
|
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)
|
||||||
|
exchange.close()
|
||||||
|
self._allow_inactive = self._pairlistconfig.get("allow_inactive", False)
|
||||||
|
|
||||||
|
self._min_price_change = pairlistconfig.get("min_price_change", None)
|
||||||
|
self._max_price_change = pairlistconfig.get("max_price_change", None)
|
||||||
|
self._exchange_name = config["exchange"]["name"]
|
||||||
|
self.stake_currency = config["stake_currency"]
|
||||||
|
|
||||||
|
if self._min_price_change is None:
|
||||||
|
raise OperationalException(
|
||||||
|
"PercentageRangeFilter requires min_price_change is not NULL. Please check config file!"
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._max_price_change is None:
|
||||||
|
raise OperationalException(
|
||||||
|
"PercentageRangeFilter requires max_price_change is not NULL. Please check config file!"
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._exchange_name not in exchange_name_list:
|
||||||
|
raise OperationalException(
|
||||||
|
"PercentageRangeFilter warning. This exchange is not implemented. Please check config file!"
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def needstickers(self) -> bool:
|
||||||
|
"""
|
||||||
|
Boolean property defining if tickers are necessary.
|
||||||
|
If no Pairlist requires tickers, an empty Dict is passed
|
||||||
|
as tickers argument to filter_pairlist
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def short_desc(self) -> str:
|
||||||
|
"""
|
||||||
|
Short whitelist method description - used for startup-messages
|
||||||
|
-> Please overwrite in subclasses
|
||||||
|
"""
|
||||||
|
|
||||||
|
return f"{self.name} - Filtering pairs between >>> {self._min_price_change} <----> {self._max_price_change}"
|
||||||
|
|
||||||
|
def gen_pairlist(self, tickers: Dict) -> List[str]:
|
||||||
|
|
||||||
|
if self._exchange_name == "binance":
|
||||||
|
_exchange = ccxt.binance()
|
||||||
|
_percentageHandler = "priceChangePercent"
|
||||||
|
|
||||||
|
if self._exchange_name == "kucoin":
|
||||||
|
_exchange = ccxt.kucoin()
|
||||||
|
_percentageHandler = "changeRate"
|
||||||
|
|
||||||
|
if self._exchange_name == "gateio":
|
||||||
|
_exchange = ccxt.gateio()
|
||||||
|
_percentageHandler = "change_percentage"
|
||||||
|
|
||||||
|
# price range from config shouldn't be empty
|
||||||
|
minPrice = self._min_price_change
|
||||||
|
maxPrice = self._max_price_change
|
||||||
|
|
||||||
|
pair_list = []
|
||||||
|
|
||||||
|
if _exchange.has["fetchTickers"]:
|
||||||
|
|
||||||
|
temp_res = _exchange.fetch_tickers()
|
||||||
|
|
||||||
|
for key in temp_res.keys():
|
||||||
|
if str(key).endswith(self.stake_currency):
|
||||||
|
_temp = temp_res.get(key)
|
||||||
|
_tmpPriceChange = float(_temp["info"][_percentageHandler])
|
||||||
|
|
||||||
|
if _tmpPriceChange > minPrice and _tmpPriceChange < maxPrice:
|
||||||
|
pair_list.append(key)
|
||||||
|
|
||||||
|
return pair_list
|
||||||
|
|
||||||
|
def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
|
||||||
|
"""
|
||||||
|
Filters and sorts pairlist and returns the whitelist again.
|
||||||
|
Called on each bot iteration - please use internal caching if necessary
|
||||||
|
:param pairlist: pairlist to filter or sort
|
||||||
|
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
|
||||||
|
:return: new whitelist
|
||||||
|
"""
|
||||||
|
pairlist_ = deepcopy(pairlist)
|
||||||
|
for pair in self._config["exchange"]["pair_whitelist"]:
|
||||||
|
if pair not in pairlist_:
|
||||||
|
pairlist_.append(pair)
|
||||||
|
|
||||||
|
pairs = self.verify_blacklist(pairlist_)
|
||||||
|
|
||||||
|
# Limit pairlist to the requested number of pairs
|
||||||
|
pairs = pairs[: self._number_pairs]
|
||||||
|
|
||||||
|
return pairs
|
Loading…
Reference in New Issue
Block a user