Merge branch 'freqtrade:develop' into pos_adjust

This commit is contained in:
Stefano Ariestasia 2022-01-22 21:25:16 +09:00 committed by GitHub
commit fe5f61694b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 45 additions and 7 deletions

View File

@ -100,6 +100,9 @@ def get_latest_hyperopt_file(directory: Union[Path, str], predef_filename: str =
if isinstance(directory, str): if isinstance(directory, str):
directory = Path(directory) directory = Path(directory)
if predef_filename: if predef_filename:
if Path(predef_filename).is_absolute():
raise OperationalException(
"--hyperopt-filename expects only the filename, not an absolute path.")
return directory / predef_filename return directory / predef_filename
return directory / get_latest_hyperopt_filename(directory) return directory / get_latest_hyperopt_filename(directory)

View File

@ -248,8 +248,10 @@ def get_strategy_run_id(strategy) -> str:
if k in config: if k in config:
del config[k] del config[k]
# Explicitly allow NaN values (e.g. max_open_trades).
# as it does not matter for getting the hash.
digest.update(rapidjson.dumps(config, default=str, digest.update(rapidjson.dumps(config, default=str,
number_mode=rapidjson.NM_NATIVE).encode('utf-8')) number_mode=rapidjson.NM_NAN).encode('utf-8'))
with open(strategy.__file__, 'rb') as fp: with open(strategy.__file__, 'rb') as fp:
digest.update(fp.read()) digest.update(fp.read())
return digest.hexdigest().lower() return digest.hexdigest().lower()

View File

@ -137,6 +137,7 @@ class HyperoptTools():
} }
if not HyperoptTools._test_hyperopt_results_exist(results_file): if not HyperoptTools._test_hyperopt_results_exist(results_file):
# No file found. # No file found.
logger.warning(f"Hyperopt file {results_file} not found.")
return [], 0 return [], 0
epochs = [] epochs = []

View File

@ -20,7 +20,7 @@ from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, Blac
Stats, StatusMsg, StrategyListResponse, Stats, StatusMsg, StrategyListResponse,
StrategyResponse, SysInfo, Version, StrategyResponse, SysInfo, Version,
WhitelistResponse) WhitelistResponse)
from freqtrade.rpc.api_server.deps import get_config, get_rpc, get_rpc_optional from freqtrade.rpc.api_server.deps import get_config, get_exchange, get_rpc, get_rpc_optional
from freqtrade.rpc.rpc import RPCException from freqtrade.rpc.rpc import RPCException
@ -217,12 +217,14 @@ def pair_candles(pair: str, timeframe: str, limit: Optional[int], rpc: RPC = Dep
@router.get('/pair_history', response_model=PairHistory, tags=['candle data']) @router.get('/pair_history', response_model=PairHistory, tags=['candle data'])
def pair_history(pair: str, timeframe: str, timerange: str, strategy: str, def pair_history(pair: str, timeframe: str, timerange: str, strategy: str,
config=Depends(get_config)): config=Depends(get_config), exchange=Depends(get_exchange)):
# The initial call to this endpoint can be slow, as it may need to initialize
# the exchange class.
config = deepcopy(config) config = deepcopy(config)
config.update({ config.update({
'strategy': strategy, 'strategy': strategy,
}) })
return RPC._rpc_analysed_history_full(config, pair, timeframe, timerange) return RPC._rpc_analysed_history_full(config, pair, timeframe, timerange, exchange)
@router.get('/plot_config', response_model=PlotConfig, tags=['candle data']) @router.get('/plot_config', response_model=PlotConfig, tags=['candle data'])

View File

@ -1,5 +1,7 @@
from typing import Any, Dict, Iterator, Optional from typing import Any, Dict, Iterator, Optional
from fastapi import Depends
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.rpc.rpc import RPC, RPCException from freqtrade.rpc.rpc import RPC, RPCException
@ -28,3 +30,11 @@ def get_config() -> Dict[str, Any]:
def get_api_config() -> Dict[str, Any]: def get_api_config() -> Dict[str, Any]:
return ApiServer._config['api_server'] return ApiServer._config['api_server']
def get_exchange(config=Depends(get_config)):
if not ApiServer._exchange:
from freqtrade.resolvers import ExchangeResolver
ApiServer._exchange = ExchangeResolver.load_exchange(
config['exchange']['name'], config)
return ApiServer._exchange

View File

@ -41,6 +41,8 @@ class ApiServer(RPCHandler):
_has_rpc: bool = False _has_rpc: bool = False
_bgtask_running: bool = False _bgtask_running: bool = False
_config: Dict[str, Any] = {} _config: Dict[str, Any] = {}
# Exchange - only available in webserver mode.
_exchange = None
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
""" """

View File

@ -1000,7 +1000,7 @@ class RPC:
@staticmethod @staticmethod
def _rpc_analysed_history_full(config, pair: str, timeframe: str, def _rpc_analysed_history_full(config, pair: str, timeframe: str,
timerange: str) -> Dict[str, Any]: timerange: str, exchange) -> Dict[str, Any]:
timerange_parsed = TimeRange.parse_timerange(timerange) timerange_parsed = TimeRange.parse_timerange(timerange)
_data = load_data( _data = load_data(
@ -1015,7 +1015,7 @@ class RPC:
from freqtrade.data.dataprovider import DataProvider from freqtrade.data.dataprovider import DataProvider
from freqtrade.resolvers.strategy_resolver import StrategyResolver from freqtrade.resolvers.strategy_resolver import StrategyResolver
strategy = StrategyResolver.load_strategy(config) strategy = StrategyResolver.load_strategy(config)
strategy.dp = DataProvider(config, exchange=None, pairlists=None) strategy.dp = DataProvider(config, exchange=exchange, pairlists=None)
df_analyzed = strategy.analyze_ticker(_data[pair], {'pair': pair}) df_analyzed = strategy.analyze_ticker(_data[pair], {'pair': pair})

View File

@ -51,6 +51,12 @@ def test_get_latest_hyperopt_file(testdatadir):
res = get_latest_hyperopt_file(str(testdatadir.parent)) res = get_latest_hyperopt_file(str(testdatadir.parent))
assert res == testdatadir.parent / "hyperopt_results.pickle" assert res == testdatadir.parent / "hyperopt_results.pickle"
# Test with absolute path
with pytest.raises(
OperationalException,
match="--hyperopt-filename expects only the filename, not an absolute path."):
get_latest_hyperopt_file(str(testdatadir.parent), str(testdatadir.parent))
def test_load_backtest_metadata(mocker, testdatadir): def test_load_backtest_metadata(mocker, testdatadir):
res = load_backtest_metadata(testdatadir / 'nonexistant.file.json') res = load_backtest_metadata(testdatadir / 'nonexistant.file.json')

View File

@ -21,6 +21,7 @@ from freqtrade.data.dataprovider import DataProvider
from freqtrade.data.history import get_timerange from freqtrade.data.history import get_timerange
from freqtrade.enums import RunMode, SellType from freqtrade.enums import RunMode, SellType
from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exceptions import DependencyException, OperationalException
from freqtrade.misc import get_strategy_run_id
from freqtrade.optimize.backtesting import Backtesting from freqtrade.optimize.backtesting import Backtesting
from freqtrade.persistence import LocalTrade from freqtrade.persistence import LocalTrade
from freqtrade.resolvers import StrategyResolver from freqtrade.resolvers import StrategyResolver
@ -1357,3 +1358,13 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda
for line in exists: for line in exists:
assert log_has(line, caplog) assert log_has(line, caplog)
def test_get_strategy_run_id(default_conf_usdt):
default_conf_usdt.update({
'strategy': 'StrategyTestV2',
'max_open_trades': float('inf')
})
strategy = StrategyResolver.load_strategy(default_conf_usdt)
x = get_strategy_run_id(strategy)
assert isinstance(x, str)

View File

@ -10,7 +10,7 @@ import rapidjson
from freqtrade.constants import FTHYPT_FILEVERSION from freqtrade.constants import FTHYPT_FILEVERSION
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer
from tests.conftest import log_has from tests.conftest import log_has, log_has_re
# Functions for recurrent object patching # Functions for recurrent object patching
@ -24,6 +24,7 @@ def test_save_results_saves_epochs(hyperopt, tmpdir, caplog) -> None:
hyperopt.results_file = Path(tmpdir / 'ut_results.fthypt') hyperopt.results_file = Path(tmpdir / 'ut_results.fthypt')
hyperopt_epochs = HyperoptTools.load_filtered_results(hyperopt.results_file, {}) hyperopt_epochs = HyperoptTools.load_filtered_results(hyperopt.results_file, {})
assert log_has_re("Hyperopt file .* not found.", caplog)
assert hyperopt_epochs == ([], 0) assert hyperopt_epochs == ([], 0)
# Test writing to temp dir and reading again # Test writing to temp dir and reading again