Add list-pairs and list-markets subcommands
This commit is contained in:
parent
31389b38f1
commit
7cf7982565
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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]
|
||||
|
@ -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'
|
||||
|
@ -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'))
|
||||
|
Loading…
Reference in New Issue
Block a user