add crossmarketfilter
This commit is contained in:
@@ -4,7 +4,7 @@ Pairlist Handlers define the list of pairs (pairlist) that the bot should trade.
|
||||
|
||||
In your configuration, you can use Static Pairlist (defined by the [`StaticPairList`](#static-pair-list) Pairlist Handler) and Dynamic Pairlist (defined by the [`VolumePairList`](#volume-pair-list) and [`PercentChangePairList`](#percent-change-pair-list) Pairlist Handlers).
|
||||
|
||||
Additionally, [`AgeFilter`](#agefilter), [`DelistFilter`](#delistfilter), [`PrecisionFilter`](#precisionfilter), [`PriceFilter`](#pricefilter), [`ShuffleFilter`](#shufflefilter), [`SpreadFilter`](#spreadfilter) and [`VolatilityFilter`](#volatilityfilter) act as Pairlist Filters, removing certain pairs and/or moving their positions in the pairlist.
|
||||
Additionally, [`AgeFilter`](#agefilter), [`CrossMarketFilter`](#crossmarketfilter), [`DelistFilter`](#delistfilter), [`PrecisionFilter`](#precisionfilter), [`PriceFilter`](#pricefilter), [`ShuffleFilter`](#shufflefilter), [`SpreadFilter`](#spreadfilter) and [`VolatilityFilter`](#volatilityfilter) act as Pairlist Filters, removing certain pairs and/or moving their positions in the pairlist.
|
||||
|
||||
If multiple Pairlist Handlers are used, they are chained and a combination of all Pairlist Handlers forms the resulting pairlist the bot uses for trading and backtesting. Pairlist Handlers are executed in the sequence they are configured. You can define either `StaticPairList`, `VolumePairList`, `ProducerPairList`, `RemotePairList`, `MarketCapPairList` or `PercentChangePairList` as the starting Pairlist Handler.
|
||||
|
||||
@@ -27,6 +27,7 @@ You may also use something like `.*DOWN/BTC` or `.*UP/BTC` to exclude leveraged
|
||||
* [`RemotePairList`](#remotepairlist)
|
||||
* [`MarketCapPairList`](#marketcappairlist)
|
||||
* [`AgeFilter`](#agefilter)
|
||||
* [`CrossMarketFilter`](#crossmarketfilter)
|
||||
* [`DelistFilter`](#delistfilter)
|
||||
* [`FullTradesFilter`](#fulltradesfilter)
|
||||
* [`OffsetFilter`](#offsetfilter)
|
||||
@@ -412,6 +413,12 @@ be caught out buying before the pair has finished dropping in price.
|
||||
|
||||
This filter allows freqtrade to ignore pairs until they have been listed for at least `min_days_listed` days and listed before `max_days_listed`.
|
||||
|
||||
#### CrossMarketFilter
|
||||
|
||||
Filter pairs based of their availability on the opposite market. So for spot pairs, it will be checked against futures market, and vice versa.
|
||||
|
||||
The `mode` setting defines whether the plugin will filters in (whitelist `mode`) or filters out (blacklist `mode`) based of the availability on the opposite market. By default, the plugin will be in whitelist mode.
|
||||
|
||||
#### DelistFilter
|
||||
|
||||
Removes pairs that will be delisted on the exchange maximum `max_days_from_now` days from now (defaults to `0` which remove all future delisted pairs no matter how far from now). Currently this filter only supports following exchanges:
|
||||
|
||||
@@ -62,6 +62,7 @@ AVAILABLE_PAIRLISTS = [
|
||||
"RemotePairList",
|
||||
"MarketCapPairList",
|
||||
"AgeFilter",
|
||||
"CrossMarketFilter",
|
||||
"DelistFilter",
|
||||
"FullTradesFilter",
|
||||
"OffsetFilter",
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
Price pair list filter
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import ccxt.pro as ccxt_pro
|
||||
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.exchange.exchange_types import Tickers
|
||||
from freqtrade.plugins.pairlist.IPairList import IPairList, PairlistParameter, SupportsBacktesting
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CrossMarketFilter(IPairList):
|
||||
supports_backtesting = SupportsBacktesting.BIASED
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._mode: str = self._pairlistconfig.get("mode", "whitelist")
|
||||
self._trading_mode: str = self._config["trading_mode"]
|
||||
self._stake_currency: str = self._config["stake_currency"]
|
||||
self._target_mode = "futures" if self._trading_mode == "spot" else "spot"
|
||||
|
||||
@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
|
||||
"""
|
||||
mode = self._mode
|
||||
target_mode = self._target_mode
|
||||
msg = f"{self.name} - {mode.capitalize()} pairs that exists on {target_mode} market."
|
||||
return msg
|
||||
|
||||
@staticmethod
|
||||
def description() -> str:
|
||||
return "Filter pairs if they exist on another market."
|
||||
|
||||
@staticmethod
|
||||
def available_parameters() -> dict[str, PairlistParameter]:
|
||||
return {
|
||||
"mode": {
|
||||
"type": "option",
|
||||
"default": "whitelist",
|
||||
"options": ["whitelist", "blacklist"],
|
||||
"description": "Mode of operation",
|
||||
"help": "Mode of operation (whitelist/blacklist)",
|
||||
},
|
||||
}
|
||||
|
||||
def get_base_list(self):
|
||||
target_mode = self._target_mode
|
||||
spot_only = True if target_mode == "spot" else False
|
||||
futures_only = True if target_mode == "futures" else False
|
||||
bases = [
|
||||
v.get("base", "")
|
||||
for k, v in self._exchange.get_markets(
|
||||
quote_currencies=[self._stake_currency],
|
||||
tradable_only=False,
|
||||
active_only=True,
|
||||
spot_only=spot_only,
|
||||
futures_only=futures_only,
|
||||
).items()
|
||||
]
|
||||
return bases
|
||||
|
||||
prefixes = ("1000", "1000000", "1M", "K", "M")
|
||||
|
||||
def filter_pairlist(self, pairlist: list[str], tickers: Tickers) -> list[str]:
|
||||
bases = self.get_base_list()
|
||||
is_whitelist_mode = self._mode == "whitelist"
|
||||
whitelisted_pairlist: list[str] = []
|
||||
filtered_pairlist = pairlist.copy()
|
||||
|
||||
for pair in pairlist:
|
||||
base = self._exchange.get_pair_base_currency(pair)
|
||||
found_in_bases = base in bases
|
||||
if not found_in_bases:
|
||||
for prefix in self.prefixes:
|
||||
test_prefix = f"{prefix}{base}"
|
||||
if test_prefix in bases:
|
||||
found_in_bases = True
|
||||
break
|
||||
if found_in_bases:
|
||||
whitelisted_pairlist.append(pair)
|
||||
filtered_pairlist.remove(pair)
|
||||
|
||||
return whitelisted_pairlist if is_whitelist_mode else filtered_pairlist
|
||||
Reference in New Issue
Block a user