Migrate download-script logic to utils.py
This commit is contained in:
parent
91886120a7
commit
05deb9e09b
@ -30,7 +30,7 @@ ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"]
|
|||||||
|
|
||||||
ARGS_LIST_EXCHANGES = ["print_one_column"]
|
ARGS_LIST_EXCHANGES = ["print_one_column"]
|
||||||
|
|
||||||
ARGS_DOWNLOADER = ARGS_COMMON + ["pairs", "pairs_file", "days", "exchange", "timeframes", "erase"]
|
ARGS_DOWNLOADER = ["pairs", "pairs_file", "days", "exchange", "timeframes", "erase"]
|
||||||
|
|
||||||
ARGS_PLOT_DATAFRAME = (ARGS_COMMON + ARGS_STRATEGY +
|
ARGS_PLOT_DATAFRAME = (ARGS_COMMON + ARGS_STRATEGY +
|
||||||
["pairs", "indicators1", "indicators2", "plot_limit", "db_url",
|
["pairs", "indicators1", "indicators2", "plot_limit", "db_url",
|
||||||
@ -40,6 +40,8 @@ ARGS_PLOT_DATAFRAME = (ARGS_COMMON + ARGS_STRATEGY +
|
|||||||
ARGS_PLOT_PROFIT = (ARGS_COMMON + ARGS_STRATEGY +
|
ARGS_PLOT_PROFIT = (ARGS_COMMON + ARGS_STRATEGY +
|
||||||
["pairs", "timerange", "export", "exportfilename", "db_url", "trade_source"])
|
["pairs", "timerange", "export", "exportfilename", "db_url", "trade_source"])
|
||||||
|
|
||||||
|
NO_CONF_REQURIED = ["start_download_data"]
|
||||||
|
|
||||||
|
|
||||||
class Arguments(object):
|
class Arguments(object):
|
||||||
"""
|
"""
|
||||||
@ -75,7 +77,10 @@ class Arguments(object):
|
|||||||
|
|
||||||
# Workaround issue in argparse with action='append' and default value
|
# Workaround issue in argparse with action='append' and default value
|
||||||
# (see https://bugs.python.org/issue16399)
|
# (see https://bugs.python.org/issue16399)
|
||||||
if not self._no_default_config and parsed_arg.config is None:
|
# Allow no-config for certain commands (like downloading / plotting)
|
||||||
|
if (not self._no_default_config and parsed_arg.config is None
|
||||||
|
and not (hasattr(parsed_arg, 'func')
|
||||||
|
and parsed_arg.func.__name__ in NO_CONF_REQURIED)):
|
||||||
parsed_arg.config = [constants.DEFAULT_CONFIG]
|
parsed_arg.config = [constants.DEFAULT_CONFIG]
|
||||||
|
|
||||||
return parsed_arg
|
return parsed_arg
|
||||||
@ -93,7 +98,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_download_data, start_list_exchanges
|
||||||
|
|
||||||
subparsers = self.parser.add_subparsers(dest='subparser')
|
subparsers = self.parser.add_subparsers(dest='subparser')
|
||||||
|
|
||||||
@ -119,3 +124,11 @@ 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_EXCHANGES, parser=list_exchanges_cmd)
|
self._build_args(optionlist=ARGS_LIST_EXCHANGES, parser=list_exchanges_cmd)
|
||||||
|
|
||||||
|
# Add download-data subcommand
|
||||||
|
download_data_cmd = subparsers.add_parser(
|
||||||
|
'download-data',
|
||||||
|
help='Download backtesting data.'
|
||||||
|
)
|
||||||
|
download_data_cmd.set_defaults(func=start_download_data)
|
||||||
|
self._build_args(optionlist=ARGS_DOWNLOADER, parser=download_data_cmd)
|
||||||
|
@ -50,10 +50,10 @@ def test_parse_args_verbose() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_common_scripts_options() -> None:
|
def test_common_scripts_options() -> None:
|
||||||
arguments = Arguments(['-p', 'ETH/BTC'], '')
|
args = Arguments(['download-data', '-p', 'ETH/BTC', 'XRP/BTC'], '').get_parsed_arg()
|
||||||
arguments._build_args(ARGS_DOWNLOADER)
|
|
||||||
args = arguments._parse_args()
|
assert args.pairs == ['ETH/BTC', 'XRP/BTC']
|
||||||
assert args.pairs == 'ETH/BTC'
|
assert hasattr(args, "func")
|
||||||
|
|
||||||
|
|
||||||
def test_parse_args_version() -> None:
|
def test_parse_args_version() -> None:
|
||||||
@ -135,14 +135,14 @@ def test_parse_args_hyperopt_custom() -> None:
|
|||||||
|
|
||||||
def test_download_data_options() -> None:
|
def test_download_data_options() -> None:
|
||||||
args = [
|
args = [
|
||||||
'--pairs-file', 'file_with_pairs',
|
|
||||||
'--datadir', 'datadir/directory',
|
'--datadir', 'datadir/directory',
|
||||||
|
'download-data',
|
||||||
|
'--pairs-file', 'file_with_pairs',
|
||||||
'--days', '30',
|
'--days', '30',
|
||||||
'--exchange', 'binance'
|
'--exchange', 'binance'
|
||||||
]
|
]
|
||||||
arguments = Arguments(args, '')
|
args = Arguments(args, '').get_parsed_arg()
|
||||||
arguments._build_args(ARGS_DOWNLOADER)
|
|
||||||
args = arguments._parse_args()
|
|
||||||
assert args.pairs_file == 'file_with_pairs'
|
assert args.pairs_file == 'file_with_pairs'
|
||||||
assert args.datadir == 'datadir/directory'
|
assert args.datadir == 'datadir/directory'
|
||||||
assert args.days == 30
|
assert args.days == 30
|
||||||
@ -162,7 +162,7 @@ def test_plot_dataframe_options() -> None:
|
|||||||
assert pargs.indicators1 == "sma10,sma100"
|
assert pargs.indicators1 == "sma10,sma100"
|
||||||
assert pargs.indicators2 == "macd,fastd,fastk"
|
assert pargs.indicators2 == "macd,fastd,fastk"
|
||||||
assert pargs.plot_limit == 30
|
assert pargs.plot_limit == 30
|
||||||
assert pargs.pairs == "UNITTEST/BTC"
|
assert pargs.pairs == ["UNITTEST/BTC"]
|
||||||
|
|
||||||
|
|
||||||
def test_check_int_positive() -> None:
|
def test_check_int_positive() -> None:
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from freqtrade.configuration import Configuration
|
import arrow
|
||||||
from freqtrade.exchange import available_exchanges
|
|
||||||
from freqtrade.state import RunMode
|
|
||||||
|
|
||||||
|
from freqtrade.configuration import Configuration, TimeRange
|
||||||
|
from freqtrade.data.history import download_pair_history
|
||||||
|
from freqtrade.exchange import available_exchanges
|
||||||
|
from freqtrade.resolvers import ExchangeResolver
|
||||||
|
from freqtrade.state import RunMode
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -17,7 +22,7 @@ def setup_utils_configuration(args: Namespace, method: RunMode) -> Dict[str, Any
|
|||||||
:return: Configuration
|
:return: Configuration
|
||||||
"""
|
"""
|
||||||
configuration = Configuration(args, method)
|
configuration = Configuration(args, method)
|
||||||
config = configuration.load_config()
|
config = configuration.get_config()
|
||||||
|
|
||||||
config['exchange']['dry_run'] = True
|
config['exchange']['dry_run'] = True
|
||||||
# Ensure we do not use Exchange credentials
|
# Ensure we do not use Exchange credentials
|
||||||
@ -39,3 +44,56 @@ 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_download_data(args: Namespace) -> None:
|
||||||
|
"""
|
||||||
|
Download data based
|
||||||
|
"""
|
||||||
|
config = setup_utils_configuration(args, RunMode.OTHER)
|
||||||
|
|
||||||
|
timerange = TimeRange()
|
||||||
|
if 'days' in config:
|
||||||
|
time_since = arrow.utcnow().shift(days=-config['days']).strftime("%Y%m%d")
|
||||||
|
timerange = TimeRange.parse_timerange(f'{time_since}-')
|
||||||
|
|
||||||
|
dl_path = Path(config['datadir'])
|
||||||
|
logger.info(f'About to download pairs: {config["pairs"]}, '
|
||||||
|
f'intervals: {config["timeframes"]} to {dl_path}')
|
||||||
|
|
||||||
|
pairs_not_available = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Init exchange
|
||||||
|
exchange = ExchangeResolver(config['exchange']['name'], config).exchange
|
||||||
|
|
||||||
|
for pair in config["pairs"]:
|
||||||
|
if pair not in exchange._api.markets:
|
||||||
|
pairs_not_available.append(pair)
|
||||||
|
logger.info(f"Skipping pair {pair}...")
|
||||||
|
continue
|
||||||
|
for ticker_interval in config["timeframes"]:
|
||||||
|
pair_print = pair.replace('/', '_')
|
||||||
|
filename = f'{pair_print}-{ticker_interval}.json'
|
||||||
|
dl_file = dl_path.joinpath(filename)
|
||||||
|
if args.erase and dl_file.exists():
|
||||||
|
logger.info(
|
||||||
|
f'Deleting existing data for pair {pair}, interval {ticker_interval}.')
|
||||||
|
dl_file.unlink()
|
||||||
|
|
||||||
|
logger.info(f'Downloading pair {pair}, interval {ticker_interval}.')
|
||||||
|
download_pair_history(datadir=dl_path, exchange=exchange,
|
||||||
|
pair=pair, ticker_interval=str(ticker_interval),
|
||||||
|
timerange=timerange)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit("SIGINT received, aborting ...")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if pairs_not_available:
|
||||||
|
logger.info(
|
||||||
|
f"Pairs [{','.join(pairs_not_available)}] not available "
|
||||||
|
f"on exchange {config['exchange']['name']}.")
|
||||||
|
|
||||||
|
# configuration.resolve_pairs_list()
|
||||||
|
print(config)
|
||||||
|
Loading…
Reference in New Issue
Block a user