Add list-pairs and list-markets subcommands

This commit is contained in:
hroff-1902 2019-10-13 13:12:20 +03:00
parent 31389b38f1
commit 7cf7982565
5 changed files with 108 additions and 2 deletions

View File

@ -2,6 +2,7 @@
This module contains the argument manager class
"""
import argparse
from functools import partial
from pathlib import Path
from typing import Any, Dict, List, Optional
@ -33,6 +34,8 @@ ARGS_LIST_EXCHANGES = ["print_one_column", "list_exchanges_all"]
ARGS_LIST_TIMEFRAMES = ["exchange", "print_one_column"]
ARGS_LIST_PAIRS = ["exchange", "print_list", "base_currency", "quote_currency", "active_only"]
ARGS_CREATE_USERDIR = ["user_data_dir"]
ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "exchange", "timeframes", "erase"]
@ -43,7 +46,8 @@ ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit", "db_
ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url",
"trade_source", "ticker_interval"]
NO_CONF_REQURIED = ["download-data", "list-timeframes", "plot-dataframe", "plot-profit"]
NO_CONF_REQURIED = ["download-data", "list-timeframes", "list-markets", "list-pairs",
"plot-dataframe", "plot-profit"]
NO_CONF_ALLOWED = ["create-userdir", "list-exchanges"]
@ -106,7 +110,8 @@ class Arguments:
"""
from freqtrade.optimize import start_backtesting, start_hyperopt, start_edge
from freqtrade.utils import (start_create_userdir, start_download_data,
start_list_exchanges, start_list_timeframes)
start_list_exchanges, start_list_timeframes,
start_list_pairs)
subparsers = self.parser.add_subparsers(dest='subparser')
@ -147,6 +152,22 @@ class Arguments:
list_timeframes_cmd.set_defaults(func=start_list_timeframes)
self._build_args(optionlist=ARGS_LIST_TIMEFRAMES, parser=list_timeframes_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)
# Add download-data subcommand
download_data_cmd = subparsers.add_parser(
'download-data',

View File

@ -255,6 +255,26 @@ AVAILABLE_CLI_OPTIONS = {
help='Print all exchanges known to the ccxt library.',
action='store_true',
),
# 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',
),
# Script options
"pairs": Arg(
'-p', '--pairs',

View File

@ -280,6 +280,25 @@ class Exchange:
self._load_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.
TODO: consider moving it to the Dataprovider
"""
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:
if pair_interval in self._klines:
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]

View File

@ -121,3 +121,7 @@ def round_dict(d, n):
Rounds float values in the dict to n digits after the decimal point.
"""
return {k: (round(v, n) if isinstance(v, float) else v) for k, v in d.items()}
def plural(num, singular: str, plural: str = None) -> str:
return singular if (num == 1 or num == -1) else plural or singular + 's'

View File

@ -4,12 +4,14 @@ from pathlib import Path
from typing import Any, Dict, List
import arrow
from tabulate import tabulate
from freqtrade import OperationalException
from freqtrade.configuration import Configuration, TimeRange
from freqtrade.configuration.directory_operations import create_userdata_dir
from freqtrade.data.history import refresh_backtest_ohlcv_data
from freqtrade.exchange import available_exchanges, ccxt_exchanges
from freqtrade.misc import plural
from freqtrade.resolvers import ExchangeResolver
from freqtrade.state import RunMode
@ -117,3 +119,43 @@ def start_list_timeframes(args: Dict[str, Any]) -> None:
else:
print(f"Timeframes available for the exchange `{config['exchange']['name']}`: "
f"{', '.join(exchange.timeframes)}")
def start_list_pairs(args: Dict[str, Any], pairs_only: bool = False) -> None:
"""
Print pairs on the exchange
:param args: Cli args from Arguments()
:param pairs_only: if True print only pairs, otherwise print all instruments (markets)
:return: None
"""
config = setup_utils_configuration(args, RunMode.OTHER)
# Init exchange
exchange = ExchangeResolver(config['exchange']['name'], config).exchange
active_only = args.get('active_only', False)
base_currency = args.get('base_currency', '')
quote_currency = args.get('quote_currency', '')
pairs = exchange.get_markets(base_currency=base_currency,
quote_currency=quote_currency,
pairs_only=pairs_only,
active_only=active_only)
if args.get('print_list', False):
# print data as a list
print(f"Exchange {exchange.name} has {len(pairs)} " +
(plural(len(pairs), "pair" if pairs_only else "market")) +
(f" with {base_currency} as base currency" if base_currency else "") +
(" and" if base_currency and quote_currency else "") +
(f" with {quote_currency} as quote currency" if quote_currency else "") +
(f": {sorted(pairs.keys())}" if len(pairs) else "") + ".")
else:
# print data as a table
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'))