Update list-markets to work for futures/margin as well

This commit is contained in:
Matthias 2021-11-01 08:40:55 +01:00
parent 8990097d6f
commit 3fac5c5bcd
3 changed files with 38 additions and 29 deletions

View File

@ -129,10 +129,9 @@ def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None:
quote_currencies = args.get('quote_currencies', []) quote_currencies = args.get('quote_currencies', [])
try: try:
# TODO-lev: Add leverage amount to get markets that support a certain leverage
pairs = exchange.get_markets(base_currencies=base_currencies, pairs = exchange.get_markets(base_currencies=base_currencies,
quote_currencies=quote_currencies, quote_currencies=quote_currencies,
pairs_only=pairs_only, tradable_only=pairs_only,
active_only=active_only) active_only=active_only)
# Sort the pairs/markets by symbol # Sort the pairs/markets by symbol
pairs = dict(sorted(pairs.items())) pairs = dict(sorted(pairs.items()))
@ -152,15 +151,19 @@ def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None:
if quote_currencies else "")) if quote_currencies else ""))
headers = ["Id", "Symbol", "Base", "Quote", "Active", headers = ["Id", "Symbol", "Base", "Quote", "Active",
*(['Is pair'] if not pairs_only else [])] "Spot", "Margin", "Future", "Leverage"]
tabular_data = [] tabular_data = [{
for _, v in pairs.items(): 'Id': v['id'],
tabular_data.append({'Id': v['id'], 'Symbol': v['symbol'], 'Symbol': v['symbol'],
'Base': v['base'], 'Quote': v['quote'], 'Base': v['base'],
'Active': market_is_active(v), 'Quote': v['quote'],
**({'Is pair': exchange.market_is_tradable(v)} 'Active': market_is_active(v),
if not pairs_only else {})}) 'Spot': 'Spot' if exchange.market_is_spot(v) else '',
'Margin': 'Margin' if exchange.market_is_margin(v) else '',
'Future': 'Future' if exchange.market_is_future(v) else '',
'Leverage': exchange.get_max_leverage(v['symbol'], 20)
} for _, v in pairs.items()]
if (args.get('print_one_column', False) or if (args.get('print_one_column', False) or
args.get('list_pairs_print_json', False) or args.get('list_pairs_print_json', False) or

View File

@ -280,7 +280,9 @@ class Exchange:
timeframe, self._ft_has.get('ohlcv_candle_limit'))) timeframe, self._ft_has.get('ohlcv_candle_limit')))
def get_markets(self, base_currencies: List[str] = None, quote_currencies: List[str] = None, def get_markets(self, base_currencies: List[str] = None, quote_currencies: List[str] = None,
pairs_only: bool = False, active_only: bool = False) -> Dict[str, Any]: spot_only: bool = False, margin_only: bool = False, futures_only: bool = False,
tradable_only: bool = True,
active_only: bool = False) -> Dict[str, Any]:
""" """
Return exchange ccxt markets, filtered out by base currency and quote currency Return exchange ccxt markets, filtered out by base currency and quote currency
if this was requested in parameters. if this was requested in parameters.
@ -295,8 +297,14 @@ class Exchange:
markets = {k: v for k, v in markets.items() if v['base'] in base_currencies} markets = {k: v for k, v in markets.items() if v['base'] in base_currencies}
if quote_currencies: if quote_currencies:
markets = {k: v for k, v in markets.items() if v['quote'] in quote_currencies} markets = {k: v for k, v in markets.items() if v['quote'] in quote_currencies}
if pairs_only: if tradable_only:
markets = {k: v for k, v in markets.items() if self.market_is_tradable(v)} markets = {k: v for k, v in markets.items() if self.market_is_tradable(v)}
if spot_only:
markets = {k: v for k, v in markets.items() if self.market_is_spot(v)}
if margin_only:
markets = {k: v for k, v in markets.items() if self.market_is_margin(v)}
if futures_only:
markets = {k: v for k, v in markets.items() if self.market_is_future(v)}
if active_only: if active_only:
markets = {k: v for k, v in markets.items() if market_is_active(v)} markets = {k: v for k, v in markets.items() if market_is_active(v)}
return markets return markets
@ -320,18 +328,25 @@ class Exchange:
""" """
return self.markets.get(pair, {}).get('base', '') return self.markets.get(pair, {}).get('base', '')
def market_is_future(self, market: Dict[str, Any]) -> bool:
return market.get('future', False) is True
def market_is_spot(self, market: Dict[str, Any]) -> bool:
return market.get('spot', False) is True
def market_is_margin(self, market: Dict[str, Any]) -> bool:
return market.get('margin', False) is True
def market_is_tradable(self, market: Dict[str, Any]) -> bool: def market_is_tradable(self, market: Dict[str, Any]) -> bool:
""" """
Check if the market symbol is tradable by Freqtrade. Check if the market symbol is tradable by Freqtrade.
By default, checks if it's splittable by `/` and both sides correspond to base / quote Ensures that Configured mode aligns to
""" """
symbol_parts = market['symbol'].split('/') return (
return (len(symbol_parts) == 2 and (self.trading_mode == TradingMode.SPOT and self.market_is_spot(market))
len(symbol_parts[0]) > 0 and or (self.trading_mode == TradingMode.MARGIN and self.market_is_margin(market))
len(symbol_parts[1]) > 0 and or (self.trading_mode == TradingMode.FUTURES and self.market_is_future(market))
symbol_parts[0] == market.get('base') and )
symbol_parts[1] == market.get('quote')
)
def klines(self, pair_interval: Tuple[str, str], copy: bool = True) -> DataFrame: def klines(self, pair_interval: Tuple[str, str], copy: bool = True) -> DataFrame:
if pair_interval in self._klines: if pair_interval in self._klines:

View File

@ -29,15 +29,6 @@ class Ftx(Exchange):
# (TradingMode.FUTURES, Collateral.CROSS) # TODO-lev: Uncomment once supported # (TradingMode.FUTURES, Collateral.CROSS) # TODO-lev: Uncomment once supported
] ]
def market_is_tradable(self, market: Dict[str, Any]) -> bool:
"""
Check if the market symbol is tradable by Freqtrade.
Default checks + check if pair is spot pair (no futures trading yet).
"""
parent_check = super().market_is_tradable(market)
return (parent_check and
market.get('spot', False) is True)
def stoploss_adjust(self, stop_loss: float, order: Dict, side: str) -> bool: def stoploss_adjust(self, stop_loss: float, order: Dict, side: str) -> bool:
""" """