Merge pull request #2973 from freqtrade/support_non_pairs

Support non pairs
This commit is contained in:
hroff-1902
2020-02-26 12:20:45 +03:00
committed by GitHub
14 changed files with 150 additions and 67 deletions

View File

@@ -150,15 +150,3 @@ def _validate_whitelist(conf: Dict[str, Any]) -> None:
if (pl.get('method') == 'StaticPairList'
and not conf.get('exchange', {}).get('pair_whitelist')):
raise OperationalException("StaticPairList requires pair_whitelist to be set.")
if pl.get('method') == 'StaticPairList':
stake = conf['stake_currency']
invalid_pairs = []
for pair in conf['exchange'].get('pair_whitelist'):
if not pair.endswith(f'/{stake}'):
invalid_pairs.append(pair)
if invalid_pairs:
raise OperationalException(
f"Stake-currency '{stake}' not compatible with pair-whitelist. "
f"Please remove the following pairs: {invalid_pairs}")

View File

@@ -251,7 +251,6 @@ CONF_SCHEMA = {
'type': 'array',
'items': {
'type': 'string',
'pattern': '^[0-9A-Z]+/[0-9A-Z]+$'
},
'uniqueItems': True
},
@@ -259,7 +258,6 @@ CONF_SCHEMA = {
'type': 'array',
'items': {
'type': 'string',
'pattern': '^[0-9A-Z]+/[0-9A-Z]+$'
},
'uniqueItems': True
},

View File

@@ -226,6 +226,18 @@ class Exchange:
markets = self.markets
return sorted(set([x['quote'] for _, x in markets.items()]))
def get_pair_quote_currency(self, pair: str) -> str:
"""
Return a pair's quote currency
"""
return self.markets.get(pair, {}).get('quote', '')
def get_pair_base_currency(self, pair: str) -> str:
"""
Return a pair's quote currency
"""
return self.markets.get(pair, {}).get('base', '')
def klines(self, pair_interval: Tuple[str, str], copy: bool = True) -> DataFrame:
if pair_interval in self._klines:
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]
@@ -298,7 +310,7 @@ class Exchange:
if not self.markets:
logger.warning('Unable to validate pairs (assuming they are correct).')
return
invalid_pairs = []
for pair in pairs:
# Note: ccxt has BaseCurrency/QuoteCurrency format for pairs
# TODO: add a support for having coins in BTC/USDT format
@@ -320,6 +332,12 @@ class Exchange:
logger.warning(f"Pair {pair} is restricted for some users on this exchange."
f"Please check if you are impacted by this restriction "
f"on the exchange and eventually remove {pair} from your whitelist.")
if not self.get_pair_quote_currency(pair) == self._config['stake_currency']:
invalid_pairs.append(pair)
if invalid_pairs:
raise OperationalException(
f"Stake-currency '{self._config['stake_currency']}' not compatible with "
f"pair-whitelist. Please remove the following pairs: {invalid_pairs}")
def get_valid_pair_combination(self, curr_1: str, curr_2: str) -> str:
"""

View File

@@ -960,8 +960,8 @@ class FreqtradeBot:
"""
# Update wallets to ensure amounts tied up in a stoploss is now free!
self.wallets.update()
wallet_amount = self.wallets.get_free(pair.split('/')[0])
trade_base_currency = self.exchange.get_pair_base_currency(pair)
wallet_amount = self.wallets.get_free(trade_base_currency)
logger.debug(f"{pair} - Wallet: {wallet_amount} - Trade-amount: {amount}")
if wallet_amount >= amount:
return amount
@@ -1147,12 +1147,13 @@ class FreqtradeBot:
if trade.fee_open == 0 or order['status'] == 'open':
return order_amount
trade_base_currency = self.exchange.get_pair_base_currency(trade.pair)
# use fee from order-dict if possible
if ('fee' in order and order['fee'] is not None and
(order['fee'].keys() >= {'currency', 'cost'})):
if (order['fee']['currency'] is not None and
order['fee']['cost'] is not None and
trade.pair.startswith(order['fee']['currency'])):
trade_base_currency == order['fee']['currency']):
new_amount = order_amount - order['fee']['cost']
logger.info("Applying fee on amount for %s (from %s to %s) from Order",
trade, order['amount'], new_amount)
@@ -1174,7 +1175,7 @@ class FreqtradeBot:
# only applies if fee is in quote currency!
if (exectrade['fee']['currency'] is not None and
exectrade['fee']['cost'] is not None and
trade.pair.startswith(exectrade['fee']['currency'])):
trade_base_currency == exectrade['fee']['currency']):
fee_abs += exectrade['fee']['cost']
if not isclose(amount, order_amount, abs_tol=constants.MATH_CLOSE_PREC):

View File

@@ -99,7 +99,8 @@ class IPairList(ABC):
logger.warning(f"Pair {pair} is not compatible with exchange "
f"{self._exchange.name}. Removing it from whitelist..")
continue
if not pair.endswith(self._config['stake_currency']):
if self._exchange.get_pair_quote_currency(pair) != self._config['stake_currency']:
logger.warning(f"Pair {pair} is not compatible with your stake currency "
f"{self._config['stake_currency']}. Removing it from whitelist..")
continue

View File

@@ -91,9 +91,9 @@ class VolumePairList(IPairList):
if self._pairlist_pos == 0:
# If VolumePairList is the first in the list, use fresh pairlist
# check length so that we make sure that '/' is actually in the string
# Check if pair quote currency equals to the stake currency.
filtered_tickers = [v for k, v in tickers.items()
if (len(k.split('/')) == 2 and k.split('/')[1] == base_currency
if (self._exchange.get_pair_quote_currency(k) == base_currency
and v[key] is not None)]
else:
# If other pairlist is in front, use the incomming pairlist.

View File

@@ -460,9 +460,9 @@ class RPC:
if self._freqtrade.state != State.RUNNING:
raise RPCException('trader is not running')
# Check pair is in stake currency
# Check if pair quote currency equals to the stake currency.
stake_currency = self._freqtrade.config.get('stake_currency')
if not pair.endswith(stake_currency):
if not self._freqtrade.exchange.get_pair_quote_currency(pair) == stake_currency:
raise RPCException(
f'Wrong pair selected. Please pairs with stake {stake_currency} pairs only')
# check if valid pair
@@ -517,7 +517,7 @@ class RPC:
if add:
stake_currency = self._freqtrade.config.get('stake_currency')
for pair in add:
if (pair.endswith(stake_currency)
if (self._freqtrade.exchange.get_pair_quote_currency(pair) == stake_currency
and pair not in self._freqtrade.pairlists.blacklist):
self._freqtrade.pairlists.blacklist.append(pair)

View File

@@ -74,7 +74,7 @@ class Wallets:
)
for trade in open_trades:
curr = trade.pair.split('/')[0]
curr = self._exchange.get_pair_base_currency(trade.pair)
_wallets[curr] = Wallet(
curr,
trade.amount,