Copy templates when creating userdir
This commit is contained in:
parent
258d4bd6ae
commit
fd45ebd0e9
@ -1,8 +1,10 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
|
from freqtrade.constants import USER_DATA_FILES
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -48,3 +50,22 @@ def create_userdata_dir(directory: str, create_dir=False) -> Path:
|
|||||||
if not subfolder.is_dir():
|
if not subfolder.is_dir():
|
||||||
subfolder.mkdir(parents=False)
|
subfolder.mkdir(parents=False)
|
||||||
return folder
|
return folder
|
||||||
|
|
||||||
|
|
||||||
|
def copy_sample_files(directory: Path) -> None:
|
||||||
|
"""
|
||||||
|
Copy files from templates to User data directory.
|
||||||
|
:param directory: Directory to copy data to
|
||||||
|
"""
|
||||||
|
if not directory.is_dir():
|
||||||
|
raise OperationalException(f"Directory `{directory}` does not exist.")
|
||||||
|
sourcedir = Path(__file__).parents[1] / "templates"
|
||||||
|
for source, target in USER_DATA_FILES.items():
|
||||||
|
targetdir = directory / target
|
||||||
|
if not targetdir.is_dir():
|
||||||
|
raise OperationalException(f"Directory `{targetdir}` does not exist.")
|
||||||
|
targetfile = targetdir / source
|
||||||
|
if targetfile.exists():
|
||||||
|
logger.warning(f"File `{targetfile}` exists already, not deploying sample file.")
|
||||||
|
continue
|
||||||
|
shutil.copy(str(sourcedir / source), str(targetfile))
|
||||||
|
@ -22,6 +22,14 @@ AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', 'PrecisionFilter', 'P
|
|||||||
DRY_RUN_WALLET = 999.9
|
DRY_RUN_WALLET = 999.9
|
||||||
MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons
|
MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons
|
||||||
|
|
||||||
|
# Soure files with destination directories
|
||||||
|
USER_DATA_FILES = {
|
||||||
|
'sample_strategy.py': 'strategies',
|
||||||
|
'sample_hyperopt_advanced.py': 'hyperopts',
|
||||||
|
'sample_hyperopt_loss.py': 'hyperopts',
|
||||||
|
'sample_hyperopt.py': 'hyperopts',
|
||||||
|
}
|
||||||
|
|
||||||
TIMEFRAMES = [
|
TIMEFRAMES = [
|
||||||
'1m', '3m', '5m', '15m', '30m',
|
'1m', '3m', '5m', '15m', '30m',
|
||||||
'1h', '2h', '4h', '6h', '8h', '12h',
|
'1h', '2h', '4h', '6h', '8h', '12h',
|
||||||
|
@ -11,7 +11,7 @@ from tabulate import tabulate
|
|||||||
|
|
||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
from freqtrade.configuration import Configuration, TimeRange, remove_credentials
|
from freqtrade.configuration import Configuration, TimeRange, remove_credentials
|
||||||
from freqtrade.configuration.directory_operations import create_userdata_dir
|
from freqtrade.configuration.directory_operations import create_userdata_dir, copy_sample_files
|
||||||
from freqtrade.data.history import (convert_trades_to_ohlcv,
|
from freqtrade.data.history import (convert_trades_to_ohlcv,
|
||||||
refresh_backtest_ohlcv_data,
|
refresh_backtest_ohlcv_data,
|
||||||
refresh_backtest_trades_data)
|
refresh_backtest_trades_data)
|
||||||
@ -81,7 +81,8 @@ def start_create_userdir(args: Dict[str, Any]) -> None:
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if "user_data_dir" in args and args["user_data_dir"]:
|
if "user_data_dir" in args and args["user_data_dir"]:
|
||||||
create_userdata_dir(args["user_data_dir"], create_dir=True)
|
userdir = create_userdata_dir(args["user_data_dir"], create_dir=True)
|
||||||
|
copy_sample_files(userdir)
|
||||||
else:
|
else:
|
||||||
logger.warning("`create-userdir` requires --userdir to be set.")
|
logger.warning("`create-userdir` requires --userdir to be set.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -18,7 +18,7 @@ from freqtrade.configuration.deprecated_settings import (
|
|||||||
check_conflicting_settings, process_deprecated_setting,
|
check_conflicting_settings, process_deprecated_setting,
|
||||||
process_temporary_deprecated_settings)
|
process_temporary_deprecated_settings)
|
||||||
from freqtrade.configuration.directory_operations import (create_datadir,
|
from freqtrade.configuration.directory_operations import (create_datadir,
|
||||||
create_userdata_dir)
|
create_userdata_dir, copy_sample_files)
|
||||||
from freqtrade.configuration.load_config import load_config_file
|
from freqtrade.configuration.load_config import load_config_file
|
||||||
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
|
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
|
||||||
from freqtrade.loggers import _set_loggers
|
from freqtrade.loggers import _set_loggers
|
||||||
@ -709,6 +709,38 @@ def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> N
|
|||||||
assert md.call_count == 0
|
assert md.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_copy_sample_files(mocker, default_conf, caplog) -> None:
|
||||||
|
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||||
|
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||||
|
copymock = mocker.patch('shutil.copy', MagicMock())
|
||||||
|
|
||||||
|
copy_sample_files(Path('/tmp/bar'))
|
||||||
|
assert copymock.call_count == 4
|
||||||
|
assert copymock.call_args_list[0][0][1] == '/tmp/bar/strategies/sample_strategy.py'
|
||||||
|
assert copymock.call_args_list[1][0][1] == '/tmp/bar/hyperopts/sample_hyperopt_advanced.py'
|
||||||
|
assert copymock.call_args_list[2][0][1] == '/tmp/bar/hyperopts/sample_hyperopt_loss.py'
|
||||||
|
assert copymock.call_args_list[3][0][1] == '/tmp/bar/hyperopts/sample_hyperopt.py'
|
||||||
|
|
||||||
|
|
||||||
|
def test_copy_sample_files_errors(mocker, default_conf, caplog) -> None:
|
||||||
|
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||||
|
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||||
|
mocker.patch('shutil.copy', MagicMock())
|
||||||
|
with pytest.raises(OperationalException,
|
||||||
|
match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist\."):
|
||||||
|
copy_sample_files(Path('/tmp/bar'))
|
||||||
|
|
||||||
|
mocker.patch.object(Path, "is_dir", MagicMock(side_effect=[True, False]))
|
||||||
|
|
||||||
|
with pytest.raises(OperationalException,
|
||||||
|
match=r"Directory `.{1,2}tmp.{1,2}bar.{1,2}strategies` does not exist\."):
|
||||||
|
copy_sample_files(Path('/tmp/bar'))
|
||||||
|
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||||
|
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
|
||||||
|
copy_sample_files(Path('/tmp/bar'))
|
||||||
|
assert log_has_re(r"File `.*` exists already, not deploying sample.*", caplog)
|
||||||
|
|
||||||
|
|
||||||
def test_validate_tsl(default_conf):
|
def test_validate_tsl(default_conf):
|
||||||
default_conf['stoploss'] = 0.0
|
default_conf['stoploss'] = 0.0
|
||||||
with pytest.raises(OperationalException, match='The config stoploss needs to be different '
|
with pytest.raises(OperationalException, match='The config stoploss needs to be different '
|
||||||
|
Loading…
Reference in New Issue
Block a user