list-pairs, list-markets subcommands
This commit is contained in:
parent
4823656028
commit
dbdeab4639
@ -5,7 +5,9 @@ This module contains the argument manager class
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from functools import partial
|
||||||
from typing import List, NamedTuple, Optional
|
from typing import List, NamedTuple, Optional
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
from freqtrade import __version__, constants
|
from freqtrade import __version__, constants
|
||||||
|
|
||||||
@ -255,6 +257,26 @@ AVAILABLE_CLI_OPTIONS = {
|
|||||||
action='store_true',
|
action='store_true',
|
||||||
dest='print_one_column',
|
dest='print_one_column',
|
||||||
),
|
),
|
||||||
|
# List pairs / markets
|
||||||
|
"print_list": Arg(
|
||||||
|
'--print-list',
|
||||||
|
help='Print list of pairs or market symbols. By default data is'
|
||||||
|
'printed in the tabular format.',
|
||||||
|
action='store_true',
|
||||||
|
),
|
||||||
|
"quote_currency": Arg(
|
||||||
|
'--quote-currency',
|
||||||
|
help='Select quote currency.',
|
||||||
|
),
|
||||||
|
"base_currency": Arg(
|
||||||
|
'--base-currency',
|
||||||
|
help='Select base currency.',
|
||||||
|
),
|
||||||
|
"active_only": Arg(
|
||||||
|
'--active-only',
|
||||||
|
help='Print only active pairs or markets.',
|
||||||
|
action='store_true',
|
||||||
|
),
|
||||||
# Common script options
|
# Common script options
|
||||||
"pairs": Arg(
|
"pairs": Arg(
|
||||||
'-p', '--pairs',
|
'-p', '--pairs',
|
||||||
@ -346,9 +368,11 @@ ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "position_stacking", "epochs
|
|||||||
|
|
||||||
ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"]
|
ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"]
|
||||||
|
|
||||||
|
|
||||||
ARGS_LIST_EXCHANGE = ["print_one_column"]
|
ARGS_LIST_EXCHANGE = ["print_one_column"]
|
||||||
|
|
||||||
|
ARGS_LIST_PAIRS = ARGS_COMMON + ["exchange", "print_list", "base_currency", "quote_currency",
|
||||||
|
"active_only"]
|
||||||
|
|
||||||
ARGS_DOWNLOADER = ARGS_COMMON + ["pairs", "pairs_file", "days", "exchange", "timeframes", "erase"]
|
ARGS_DOWNLOADER = ARGS_COMMON + ["pairs", "pairs_file", "days", "exchange", "timeframes", "erase"]
|
||||||
|
|
||||||
ARGS_PLOT_DATAFRAME = (ARGS_COMMON + ARGS_STRATEGY +
|
ARGS_PLOT_DATAFRAME = (ARGS_COMMON + ARGS_STRATEGY +
|
||||||
@ -422,7 +446,7 @@ class Arguments(object):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
from freqtrade.optimize import start_backtesting, start_hyperopt, start_edge
|
from freqtrade.optimize import start_backtesting, start_hyperopt, start_edge
|
||||||
from freqtrade.utils import start_list_exchanges
|
from freqtrade.utils import start_list_exchanges, start_list_pairs
|
||||||
|
|
||||||
subparsers = self.parser.add_subparsers(dest='subparser')
|
subparsers = self.parser.add_subparsers(dest='subparser')
|
||||||
|
|
||||||
@ -449,6 +473,23 @@ class Arguments(object):
|
|||||||
list_exchanges_cmd.set_defaults(func=start_list_exchanges)
|
list_exchanges_cmd.set_defaults(func=start_list_exchanges)
|
||||||
self.build_args(optionlist=ARGS_LIST_EXCHANGE, parser=list_exchanges_cmd)
|
self.build_args(optionlist=ARGS_LIST_EXCHANGE, parser=list_exchanges_cmd)
|
||||||
|
|
||||||
|
# Add list-markets subcommand
|
||||||
|
list_markets_cmd = subparsers.add_parser(
|
||||||
|
'list-markets',
|
||||||
|
help='Print markets on exchange.'
|
||||||
|
)
|
||||||
|
list_markets_cmd.set_defaults(func=partial(start_list_pairs, pairs_only=False))
|
||||||
|
self.build_args(optionlist=ARGS_LIST_PAIRS, parser=list_markets_cmd)
|
||||||
|
|
||||||
|
# Add list-pairs subcommand
|
||||||
|
list_pairs_cmd = subparsers.add_parser(
|
||||||
|
'list-pairs',
|
||||||
|
help='Print pairs on exchange.'
|
||||||
|
)
|
||||||
|
list_pairs_cmd.set_defaults(func=partial(start_list_pairs, pairs_only=True))
|
||||||
|
self.build_args(optionlist=ARGS_LIST_PAIRS, parser=list_pairs_cmd)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_timerange(text: Optional[str]) -> TimeRange:
|
def parse_timerange(text: Optional[str]) -> TimeRange:
|
||||||
"""
|
"""
|
||||||
|
@ -196,6 +196,23 @@ class Exchange(object):
|
|||||||
self._load_markets()
|
self._load_markets()
|
||||||
return self._api.markets
|
return self._api.markets
|
||||||
|
|
||||||
|
def get_markets(self, base_currency: str = None, quote_currency: str = None,
|
||||||
|
pairs_only: bool = False, active_only: bool = False) -> Dict:
|
||||||
|
"""
|
||||||
|
Return exchange ccxt markets, filtered out by base currency and quote currency
|
||||||
|
if this was requested in parameters.
|
||||||
|
"""
|
||||||
|
markets = self.markets
|
||||||
|
if base_currency:
|
||||||
|
markets = {k: v for k, v in markets.items() if v['base'] == base_currency}
|
||||||
|
if quote_currency:
|
||||||
|
markets = {k: v for k, v in markets.items() if v['quote'] == quote_currency}
|
||||||
|
if pairs_only:
|
||||||
|
markets = {k: v for k, v in markets.items() if '/' in v['symbol']}
|
||||||
|
if active_only:
|
||||||
|
markets = {k: v for k, v in markets.items() if v['active']}
|
||||||
|
return markets
|
||||||
|
|
||||||
def klines(self, pair_interval: Tuple[str, str], copy=True) -> DataFrame:
|
def klines(self, pair_interval: Tuple[str, str], copy=True) -> DataFrame:
|
||||||
if pair_interval in self._klines:
|
if pair_interval in self._klines:
|
||||||
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]
|
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]
|
||||||
|
@ -133,3 +133,6 @@ def deep_merge_dicts(source, destination):
|
|||||||
destination[key] = value
|
destination[key] = value
|
||||||
|
|
||||||
return destination
|
return destination
|
||||||
|
|
||||||
|
def plural(num, singular: str, plural: str = None) -> str:
|
||||||
|
return singular if (num == 1 or num == -1) else plural or singular + 's'
|
||||||
|
@ -3,9 +3,12 @@ from argparse import Namespace
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from freqtrade.configuration import Configuration
|
from freqtrade.configuration import Configuration
|
||||||
from freqtrade.exchange import available_exchanges
|
from freqtrade.exchange import available_exchanges, Exchange
|
||||||
|
from freqtrade.misc import plural
|
||||||
from freqtrade.state import RunMode
|
from freqtrade.state import RunMode
|
||||||
|
|
||||||
|
from tabulate import tabulate
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -39,3 +42,49 @@ def start_list_exchanges(args: Namespace) -> None:
|
|||||||
else:
|
else:
|
||||||
print(f"Exchanges supported by ccxt and available for Freqtrade: "
|
print(f"Exchanges supported by ccxt and available for Freqtrade: "
|
||||||
f"{', '.join(available_exchanges())}")
|
f"{', '.join(available_exchanges())}")
|
||||||
|
|
||||||
|
|
||||||
|
def start_list_pairs(args: Namespace, pairs_only: bool = False) -> None:
|
||||||
|
"""
|
||||||
|
Print pairs on the exchange
|
||||||
|
:param args: Cli args from Arguments()
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Initialize configuration
|
||||||
|
config = setup_utils_configuration(args, RunMode.OTHER)
|
||||||
|
|
||||||
|
# Fetch exchange name from args, use bittrex as default exchange
|
||||||
|
config['exchange']['name'] = args.exchange or 'bittrex'
|
||||||
|
|
||||||
|
# Init exchange
|
||||||
|
exchange = Exchange(config)
|
||||||
|
|
||||||
|
logger.debug(f"Exchange markets: {exchange.markets}")
|
||||||
|
|
||||||
|
pairs = exchange.get_markets(base_currency=args.base_currency,
|
||||||
|
quote_currency=args.quote_currency,
|
||||||
|
pairs_only=pairs_only,
|
||||||
|
active_only=args.active_only)
|
||||||
|
|
||||||
|
if args.print_list:
|
||||||
|
# print data as a list
|
||||||
|
print(f"Exchange {exchange.name} has {len(pairs)} " +
|
||||||
|
(plural(len(pairs), "pair" if pairs_only else "market")) +
|
||||||
|
(f" with {args.base_currency} as base currency" if args.base_currency else "") +
|
||||||
|
(" and" if args.base_currency and args.quote_currency else "") +
|
||||||
|
(f" with {args.quote_currency} as quote currency" if args.quote_currency else "") +
|
||||||
|
(f": {sorted(pairs.keys())}" if len(pairs) else "") + ".")
|
||||||
|
else:
|
||||||
|
# # print a table of pairs (markets)
|
||||||
|
# print('{:<15} {:<15} {:<15} {:<15} {:<15}'.format('id', 'symbol', 'base', 'quote', 'active'))
|
||||||
|
#
|
||||||
|
# for (k, v) in pairs.items():
|
||||||
|
# print('{:<15} {:<15} {:<15} {:<15} {:<15}'.format(v['id'], v['symbol'], v['base'], v['quote'], "Yes" if v['active'] else "No"))
|
||||||
|
tabular_data = []
|
||||||
|
for _, v in pairs.items():
|
||||||
|
tabular_data.append([v['id'], v['symbol'], v['base'], v['quote'],
|
||||||
|
"Yes" if v['active'] else "No"])
|
||||||
|
|
||||||
|
headers = ['Id', 'Symbol', 'Base', 'Quote', 'Active']
|
||||||
|
print(tabulate(tabular_data, headers=headers, tablefmt='pipe'))
|
||||||
|
Loading…
Reference in New Issue
Block a user