Merge branch 'develop' into add-custom-roi-strategy-callback
This commit is contained in:
@@ -56,7 +56,7 @@ def test_get_latest_backtest_filename(testdatadir, mocker):
|
||||
res = get_latest_backtest_filename(str(testdir_bt))
|
||||
assert res == "backtest-result.json"
|
||||
|
||||
mocker.patch("freqtrade.data.btanalysis.json_load", return_value={})
|
||||
mocker.patch("freqtrade.data.btanalysis.bt_fileutils.json_load", return_value={})
|
||||
|
||||
with pytest.raises(ValueError, match=r"Invalid '.last_result.json' format."):
|
||||
get_latest_backtest_filename(testdir_bt)
|
||||
@@ -84,8 +84,8 @@ def test_load_backtest_metadata(mocker, testdatadir):
|
||||
res = load_backtest_metadata(testdatadir / "nonexistent.file.json")
|
||||
assert res == {}
|
||||
|
||||
mocker.patch("freqtrade.data.btanalysis.get_backtest_metadata_filename")
|
||||
mocker.patch("freqtrade.data.btanalysis.json_load", side_effect=Exception())
|
||||
mocker.patch("freqtrade.data.btanalysis.bt_fileutils.get_backtest_metadata_filename")
|
||||
mocker.patch("freqtrade.data.btanalysis.bt_fileutils.json_load", side_effect=Exception())
|
||||
with pytest.raises(
|
||||
OperationalException, match=r"Unexpected error.*loading backtest metadata\."
|
||||
):
|
||||
@@ -94,7 +94,7 @@ def test_load_backtest_metadata(mocker, testdatadir):
|
||||
|
||||
def test_load_backtest_data_old_format(testdatadir, mocker):
|
||||
filename = testdatadir / "backtest-result_test222.json"
|
||||
mocker.patch("freqtrade.data.btanalysis.load_backtest_stats", return_value=[])
|
||||
mocker.patch("freqtrade.data.btanalysis.bt_fileutils.load_backtest_stats", return_value=[])
|
||||
|
||||
with pytest.raises(
|
||||
OperationalException,
|
||||
@@ -149,7 +149,7 @@ def test_load_backtest_data_multi(testdatadir):
|
||||
def test_load_trades_from_db(default_conf, fee, is_short, mocker):
|
||||
create_mock_trades(fee, is_short)
|
||||
# remove init so it does not init again
|
||||
init_mock = mocker.patch("freqtrade.data.btanalysis.init_db", MagicMock())
|
||||
init_mock = mocker.patch("freqtrade.data.btanalysis.bt_fileutils.init_db", MagicMock())
|
||||
|
||||
trades = load_trades_from_db(db_url=default_conf["db_url"])
|
||||
assert init_mock.call_count == 1
|
||||
@@ -221,8 +221,10 @@ def test_analyze_trade_parallelism(testdatadir):
|
||||
|
||||
|
||||
def test_load_trades(default_conf, mocker):
|
||||
db_mock = mocker.patch("freqtrade.data.btanalysis.load_trades_from_db", MagicMock())
|
||||
bt_mock = mocker.patch("freqtrade.data.btanalysis.load_backtest_data", MagicMock())
|
||||
db_mock = mocker.patch(
|
||||
"freqtrade.data.btanalysis.bt_fileutils.load_trades_from_db", MagicMock()
|
||||
)
|
||||
bt_mock = mocker.patch("freqtrade.data.btanalysis.bt_fileutils.load_backtest_data", MagicMock())
|
||||
|
||||
load_trades(
|
||||
"DB",
|
||||
@@ -268,6 +270,14 @@ def test_calculate_market_change(testdatadir):
|
||||
assert isinstance(result, float)
|
||||
assert pytest.approx(result) == 0.01100002
|
||||
|
||||
result = calculate_market_change(data, min_date=dt_utc(2018, 1, 20))
|
||||
assert isinstance(result, float)
|
||||
assert pytest.approx(result) == 0.0375149
|
||||
|
||||
# Move min-date after the last date
|
||||
result = calculate_market_change(data, min_date=dt_utc(2018, 2, 20))
|
||||
assert pytest.approx(result) == 0.0
|
||||
|
||||
|
||||
def test_combine_dataframes_with_mean(testdatadir):
|
||||
pairs = ["ETH/BTC", "ADA/BTC"]
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# pragma pylint: disable=missing-docstring, C0103
|
||||
|
||||
from datetime import timezone
|
||||
|
||||
import pandas as pd
|
||||
from numpy import nan
|
||||
from pandas import DataFrame, Timestamp
|
||||
|
||||
from freqtrade.data.btanalysis.historic_precision import get_tick_size_over_time
|
||||
|
||||
|
||||
def test_get_tick_size_over_time():
|
||||
"""
|
||||
Test the get_tick_size_over_time function with predefined data
|
||||
"""
|
||||
# Create test dataframe with different levels of precision
|
||||
data = {
|
||||
"date": [
|
||||
Timestamp("2020-01-01 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-01-02 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-01-03 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-01-15 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-01-16 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-01-31 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-02-01 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-02-15 00:00:00", tz=timezone.utc),
|
||||
Timestamp("2020-03-15 00:00:00", tz=timezone.utc),
|
||||
],
|
||||
"open": [1.23456, 1.234, 1.23, 1.2, 1.23456, 1.234, 2.3456, 2.34, 2.34],
|
||||
"high": [1.23457, 1.235, 1.24, 1.3, 1.23456, 1.235, 2.3457, 2.34, 2.34],
|
||||
"low": [1.23455, 1.233, 1.22, 1.1, 1.23456, 1.233, 2.3455, 2.34, 2.34],
|
||||
"close": [1.23456, 1.234, 1.23, 1.2, 1.23456, 1.234, 2.3456, 2.34, 2.34],
|
||||
"volume": [100, 200, 300, 400, 500, 600, 700, 800, 900],
|
||||
}
|
||||
|
||||
candles = DataFrame(data)
|
||||
|
||||
# Calculate significant digits
|
||||
result = get_tick_size_over_time(candles)
|
||||
|
||||
# Check that the result is a pandas Series
|
||||
assert isinstance(result, pd.Series)
|
||||
|
||||
# Check that we have three months of data (Jan, Feb and March 2020 )
|
||||
assert len(result) == 3
|
||||
|
||||
# Before
|
||||
assert result.asof("2019-01-01 00:00:00+00:00") is nan
|
||||
# January should have 5 significant digits (based on 1.23456789 being the most precise value)
|
||||
# which should be converted to 0.00001
|
||||
|
||||
assert result.asof("2020-01-01 00:00:00+00:00") == 0.00001
|
||||
assert result.asof("2020-01-01 00:00:00+00:00") == 0.00001
|
||||
assert result.asof("2020-02-25 00:00:00+00:00") == 0.0001
|
||||
assert result.asof("2020-03-25 00:00:00+00:00") == 0.01
|
||||
assert result.asof("2020-04-01 00:00:00+00:00") == 0.01
|
||||
# Value far past the last date should be the last value
|
||||
assert result.asof("2025-04-01 00:00:00+00:00") == 0.01
|
||||
|
||||
assert result.iloc[0] == 0.00001
|
||||
|
||||
|
||||
def test_get_tick_size_over_time_real_data(testdatadir):
|
||||
"""
|
||||
Test the get_tick_size_over_time function with real data from the testdatadir
|
||||
"""
|
||||
from freqtrade.data.history import load_pair_history
|
||||
|
||||
# Load some test data from the testdata directory
|
||||
pair = "UNITTEST/BTC"
|
||||
timeframe = "1m"
|
||||
|
||||
candles = load_pair_history(
|
||||
datadir=testdatadir,
|
||||
pair=pair,
|
||||
timeframe=timeframe,
|
||||
)
|
||||
|
||||
# Make sure we have test data
|
||||
assert not candles.empty, "No test data found, cannot run test"
|
||||
|
||||
# Calculate significant digits
|
||||
result = get_tick_size_over_time(candles)
|
||||
|
||||
assert isinstance(result, pd.Series)
|
||||
|
||||
# Verify that all values are between 0 and 1 (valid precision values)
|
||||
assert all(result > 0)
|
||||
assert all(result < 1)
|
||||
|
||||
assert all(result <= 0.0001)
|
||||
assert all(result >= 0.00000001)
|
||||
@@ -5599,11 +5599,13 @@ def test_liquidation_price_is_none(
|
||||
def test_get_max_pair_stake_amount(
|
||||
mocker,
|
||||
default_conf,
|
||||
leverage_tiers,
|
||||
):
|
||||
api_mock = MagicMock()
|
||||
default_conf["margin_mode"] = "isolated"
|
||||
default_conf["trading_mode"] = "futures"
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock)
|
||||
exchange._leverage_tiers = leverage_tiers
|
||||
markets = {
|
||||
"XRP/USDT:USDT": {
|
||||
"limits": {
|
||||
@@ -5667,11 +5669,23 @@ def test_get_max_pair_stake_amount(
|
||||
"contractSize": 0.01,
|
||||
"spot": False,
|
||||
},
|
||||
"ZEC/USDT:USDT": {
|
||||
"limits": {
|
||||
"amount": {"min": 0.001, "max": None},
|
||||
"cost": {"min": 5, "max": None},
|
||||
},
|
||||
"contractSize": 1,
|
||||
"spot": False,
|
||||
},
|
||||
}
|
||||
|
||||
mocker.patch(f"{EXMS}.markets", markets)
|
||||
assert exchange.get_max_pair_stake_amount("XRP/USDT:USDT", 2.0) == 20000
|
||||
assert exchange.get_max_pair_stake_amount("XRP/USDT:USDT", 2.0, 5) == 4000
|
||||
# limit leverage tiers
|
||||
assert exchange.get_max_pair_stake_amount("ZEC/USDT:USDT", 2.0, 5) == 100_000
|
||||
assert exchange.get_max_pair_stake_amount("ZEC/USDT:USDT", 2.0, 50) == 1000
|
||||
|
||||
assert exchange.get_max_pair_stake_amount("LTC/USDT:USDT", 2.0) == float("inf")
|
||||
assert exchange.get_max_pair_stake_amount("ETH/USDT:USDT", 2.0) == 200
|
||||
assert exchange.get_max_pair_stake_amount("DOGE/USDT:USDT", 2.0) == 500
|
||||
@@ -5902,8 +5916,8 @@ def test_get_max_leverage_futures(default_conf, mocker, leverage_tiers):
|
||||
assert exchange.get_max_leverage("XRP/USDT:USDT", 1.0) == 20.0
|
||||
assert exchange.get_max_leverage("BNB/USDT:USDT", 100.0) == 75.0
|
||||
assert exchange.get_max_leverage("BTC/USDT:USDT", 170.30) == 125.0
|
||||
assert pytest.approx(exchange.get_max_leverage("XRP/USDT:USDT", 99999.9)) == 5.000005
|
||||
assert pytest.approx(exchange.get_max_leverage("BNB/USDT:USDT", 1500)) == 33.333333333333333
|
||||
assert pytest.approx(exchange.get_max_leverage("XRP/USDT:USDT", 99999.9)) == 5
|
||||
assert pytest.approx(exchange.get_max_leverage("BNB/USDT:USDT", 1500)) == 25
|
||||
assert exchange.get_max_leverage("BTC/USDT:USDT", 300000000) == 2.0
|
||||
assert exchange.get_max_leverage("BTC/USDT:USDT", 600000000) == 1.0 # Last tier
|
||||
|
||||
|
||||
@@ -599,7 +599,7 @@ def exchange_ws(request, exchange_conf, exchange_mode, class_mocker):
|
||||
else:
|
||||
pytest.skip("Exchange does not support futures.")
|
||||
|
||||
if not exchange._has_watch_ohlcv:
|
||||
if not exchange._exchange_ws:
|
||||
pytest.skip("Exchange does not support watch_ohlcv.")
|
||||
yield exchange, name, pair
|
||||
exchange.close()
|
||||
|
||||
@@ -22,6 +22,7 @@ from freqtrade.data.history import get_timerange
|
||||
from freqtrade.enums import CandleType, ExitType, RunMode
|
||||
from freqtrade.exceptions import DependencyException, OperationalException
|
||||
from freqtrade.exchange import timeframe_to_next_date, timeframe_to_prev_date
|
||||
from freqtrade.exchange.exchange_utils import DECIMAL_PLACES, TICK_SIZE
|
||||
from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename, get_strategy_run_id
|
||||
from freqtrade.optimize.backtesting import Backtesting
|
||||
from freqtrade.persistence import LocalTrade, Trade
|
||||
@@ -348,6 +349,29 @@ def test_data_to_dataframe_bt(default_conf, mocker, testdatadir) -> None:
|
||||
assert processed["UNITTEST/BTC"].equals(processed2["UNITTEST/BTC"])
|
||||
|
||||
|
||||
def test_get_pair_precision_bt(default_conf, mocker) -> None:
|
||||
patch_exchange(mocker)
|
||||
default_conf["timeframe"] = "30m"
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
pair = "UNITTEST/BTC"
|
||||
backtesting.pairlists._whitelist = [pair]
|
||||
ex_mock = mocker.patch(f"{EXMS}.get_precision_price", return_value=1e-5)
|
||||
data, timerange = backtesting.load_bt_data()
|
||||
assert data
|
||||
|
||||
assert backtesting.get_pair_precision(pair, dt_utc(2018, 1, 1)) == (1e-8, TICK_SIZE)
|
||||
assert ex_mock.call_count == 0
|
||||
assert backtesting.get_pair_precision(pair, dt_utc(2017, 12, 15)) == (1e-8, TICK_SIZE)
|
||||
assert ex_mock.call_count == 0
|
||||
|
||||
# Fallback to exchange logic
|
||||
assert backtesting.get_pair_precision(pair, dt_utc(2017, 1, 15)) == (1e-5, DECIMAL_PLACES)
|
||||
assert ex_mock.call_count == 1
|
||||
assert backtesting.get_pair_precision("ETH/BTC", dt_utc(2017, 1, 15)) == (1e-5, DECIMAL_PLACES)
|
||||
assert ex_mock.call_count == 2
|
||||
|
||||
|
||||
def test_backtest_abort(default_conf, mocker, testdatadir) -> None:
|
||||
patch_exchange(mocker)
|
||||
backtesting = Backtesting(default_conf)
|
||||
@@ -828,6 +852,7 @@ def test_backtest_one(default_conf, mocker, testdatadir) -> None:
|
||||
},
|
||||
],
|
||||
],
|
||||
"funding_fees": [0.0, 0.0],
|
||||
}
|
||||
)
|
||||
pd.testing.assert_frame_equal(results, expected)
|
||||
@@ -991,7 +1016,7 @@ def test_backtest_one_detail_futures(
|
||||
timerange=timerange,
|
||||
candle_type=CandleType.FUTURES,
|
||||
)
|
||||
backtesting.load_bt_data_detail()
|
||||
backtesting._load_bt_data_detail()
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
|
||||
@@ -1119,7 +1144,7 @@ def test_backtest_one_detail_futures_funding_fees(
|
||||
timerange=timerange,
|
||||
candle_type=CandleType.FUTURES,
|
||||
)
|
||||
backtesting.load_bt_data_detail()
|
||||
backtesting._load_bt_data_detail()
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
|
||||
@@ -2576,7 +2601,7 @@ def test_backtest_start_multi_strat_caching(
|
||||
],
|
||||
)
|
||||
mocker.patch.multiple(
|
||||
"freqtrade.data.btanalysis",
|
||||
"freqtrade.data.btanalysis.bt_fileutils",
|
||||
load_backtest_metadata=load_backtest_metadata,
|
||||
load_backtest_stats=load_backtest_stats,
|
||||
)
|
||||
|
||||
@@ -80,6 +80,7 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) ->
|
||||
"is_short": [False, False],
|
||||
"open_timestamp": [1517251200000, 1517283000000],
|
||||
"close_timestamp": [1517263200000, 1517285400000],
|
||||
"funding_fees": [0.0, 0.0],
|
||||
}
|
||||
)
|
||||
results_no = results.drop(columns=["orders"])
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
# pragma pylint: disable=missing-docstring,W0212,C0103
|
||||
from datetime import datetime, timedelta
|
||||
from functools import wraps
|
||||
from functools import partial, wraps
|
||||
from pathlib import Path
|
||||
from unittest.mock import ANY, MagicMock, PropertyMock
|
||||
|
||||
import pandas as pd
|
||||
import pytest
|
||||
from filelock import Timeout
|
||||
from skopt.space import Integer
|
||||
|
||||
from freqtrade.commands.optimize_commands import setup_optimize_configuration, start_hyperopt
|
||||
from freqtrade.data.history import load_data
|
||||
@@ -17,7 +16,7 @@ from freqtrade.optimize.hyperopt import Hyperopt
|
||||
from freqtrade.optimize.hyperopt.hyperopt_auto import HyperOptAuto
|
||||
from freqtrade.optimize.hyperopt_tools import HyperoptTools
|
||||
from freqtrade.optimize.optimize_reports import generate_strategy_stats
|
||||
from freqtrade.optimize.space import SKDecimal
|
||||
from freqtrade.optimize.space import SKDecimal, ft_IntDistribution
|
||||
from freqtrade.strategy import IntParameter
|
||||
from freqtrade.util import dt_utc
|
||||
from tests.conftest import (
|
||||
@@ -578,7 +577,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
|
||||
"buy_plusdi": 0.02,
|
||||
"buy_rsi": 35,
|
||||
},
|
||||
"roi": {"0": 0.12000000000000001, "20.0": 0.02, "50.0": 0.01, "110.0": 0},
|
||||
"roi": {"0": 0.12, "20.0": 0.02, "50.0": 0.01, "110.0": 0},
|
||||
"protection": {
|
||||
"protection_cooldown_lookback": 20,
|
||||
"protection_enabled": True,
|
||||
@@ -606,9 +605,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
|
||||
hyperopt.hyperopter.min_date = dt_utc(2017, 12, 10)
|
||||
hyperopt.hyperopter.max_date = dt_utc(2017, 12, 13)
|
||||
hyperopt.hyperopter.init_spaces()
|
||||
generate_optimizer_value = hyperopt.hyperopter.generate_optimizer(
|
||||
list(optimizer_param.values())
|
||||
)
|
||||
generate_optimizer_value = hyperopt.hyperopter.generate_optimizer(optimizer_param)
|
||||
assert generate_optimizer_value == response_expected
|
||||
|
||||
|
||||
@@ -1088,8 +1085,8 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmp_path, fee) -> None
|
||||
assert opt.backtesting.strategy.max_open_trades != 1
|
||||
|
||||
opt.custom_hyperopt.generate_estimator = lambda *args, **kwargs: "ET1"
|
||||
with pytest.raises(OperationalException, match="Estimator ET1 not supported."):
|
||||
opt.get_optimizer(2, 42, 2, 2)
|
||||
with pytest.raises(OperationalException, match="Optuna Sampler ET1 not supported."):
|
||||
opt.get_optimizer(42)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
||||
@@ -1186,19 +1183,27 @@ def test_in_strategy_auto_hyperopt_per_epoch(mocker, hyperopt_conf, tmp_path, fe
|
||||
|
||||
def test_SKDecimal():
|
||||
space = SKDecimal(1, 2, decimals=2)
|
||||
assert 1.5 in space
|
||||
assert 2.5 not in space
|
||||
assert space.low == 100
|
||||
assert space.high == 200
|
||||
assert space._contains(1.5)
|
||||
assert not space._contains(2.5)
|
||||
assert space.low == 1
|
||||
assert space.high == 2
|
||||
|
||||
assert space.inverse_transform([200]) == [2.0]
|
||||
assert space.inverse_transform([100]) == [1.0]
|
||||
assert space.inverse_transform([150, 160]) == [1.5, 1.6]
|
||||
assert space._contains(1.51)
|
||||
assert space._contains(1.01)
|
||||
# Falls out of the space with 2 decimals
|
||||
assert not space._contains(1.511)
|
||||
assert not space._contains(1.111222)
|
||||
|
||||
assert space.transform([1.5]) == [150]
|
||||
assert space.transform([2.0]) == [200]
|
||||
assert space.transform([1.0]) == [100]
|
||||
assert space.transform([1.5, 1.6]) == [150, 160]
|
||||
with pytest.raises(ValueError):
|
||||
SKDecimal(1, 2, step=5, decimals=0.2)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
SKDecimal(1, 2, step=None, decimals=None)
|
||||
|
||||
s = SKDecimal(1, 2, step=0.1, decimals=None)
|
||||
assert s.step == 0.1
|
||||
assert s._contains(1.1)
|
||||
assert not s._contains(1.11)
|
||||
|
||||
|
||||
def test_stake_amount_unlimited_max_open_trades(mocker, hyperopt_conf, tmp_path, fee) -> None:
|
||||
@@ -1217,10 +1222,6 @@ def test_stake_amount_unlimited_max_open_trades(mocker, hyperopt_conf, tmp_path,
|
||||
}
|
||||
)
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
mocker.patch(
|
||||
"freqtrade.optimize.hyperopt.hyperopt_optimizer.HyperOptimizer._get_params_dict",
|
||||
return_value={"max_open_trades": -1},
|
||||
)
|
||||
|
||||
assert isinstance(hyperopt.hyperopter.custom_hyperopt, HyperOptAuto)
|
||||
|
||||
@@ -1228,7 +1229,7 @@ def test_stake_amount_unlimited_max_open_trades(mocker, hyperopt_conf, tmp_path,
|
||||
|
||||
hyperopt.start()
|
||||
|
||||
assert hyperopt.hyperopter.backtesting.strategy.max_open_trades == 1
|
||||
assert hyperopt.hyperopter.backtesting.strategy.max_open_trades == 3
|
||||
|
||||
|
||||
def test_max_open_trades_dump(mocker, hyperopt_conf, tmp_path, fee, capsys) -> None:
|
||||
@@ -1246,9 +1247,15 @@ def test_max_open_trades_dump(mocker, hyperopt_conf, tmp_path, fee, capsys) -> N
|
||||
}
|
||||
)
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
|
||||
def optuna_mock(hyperopt, *args, **kwargs):
|
||||
a = hyperopt.get_optuna_asked_points(*args, **kwargs)
|
||||
a[0]._cached_frozen_trial.params["max_open_trades"] = -1
|
||||
return a, [True]
|
||||
|
||||
mocker.patch(
|
||||
"freqtrade.optimize.hyperopt.hyperopt_optimizer.HyperOptimizer._get_params_dict",
|
||||
return_value={"max_open_trades": -1},
|
||||
"freqtrade.optimize.hyperopt.Hyperopt.get_asked_points",
|
||||
side_effect=partial(optuna_mock, hyperopt),
|
||||
)
|
||||
|
||||
assert isinstance(hyperopt.hyperopter.custom_hyperopt, HyperOptAuto)
|
||||
@@ -1266,8 +1273,8 @@ def test_max_open_trades_dump(mocker, hyperopt_conf, tmp_path, fee, capsys) -> N
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
mocker.patch(
|
||||
"freqtrade.optimize.hyperopt.hyperopt_optimizer.HyperOptimizer._get_params_dict",
|
||||
return_value={"max_open_trades": -1},
|
||||
"freqtrade.optimize.hyperopt.Hyperopt.get_asked_points",
|
||||
side_effect=partial(optuna_mock, hyperopt),
|
||||
)
|
||||
|
||||
assert isinstance(hyperopt.hyperopter.custom_hyperopt, HyperOptAuto)
|
||||
@@ -1304,7 +1311,7 @@ def test_max_open_trades_consistency(mocker, hyperopt_conf, tmp_path, fee) -> No
|
||||
assert isinstance(hyperopt.hyperopter.custom_hyperopt, HyperOptAuto)
|
||||
|
||||
hyperopt.hyperopter.custom_hyperopt.max_open_trades_space = lambda: [
|
||||
Integer(1, 10, name="max_open_trades")
|
||||
ft_IntDistribution(1, 10, "max_open_trades")
|
||||
]
|
||||
|
||||
first_time_evaluated = False
|
||||
@@ -1313,9 +1320,10 @@ def test_max_open_trades_consistency(mocker, hyperopt_conf, tmp_path, fee) -> No
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
nonlocal first_time_evaluated
|
||||
|
||||
stake_amount = func(*args, **kwargs)
|
||||
if first_time_evaluated is False:
|
||||
assert stake_amount == 1
|
||||
assert stake_amount == 2
|
||||
first_time_evaluated = True
|
||||
return stake_amount
|
||||
|
||||
@@ -1329,5 +1337,5 @@ def test_max_open_trades_consistency(mocker, hyperopt_conf, tmp_path, fee) -> No
|
||||
|
||||
hyperopt.start()
|
||||
|
||||
assert hyperopt.hyperopter.backtesting.strategy.max_open_trades == 8
|
||||
assert hyperopt.config["max_open_trades"] == 8
|
||||
assert hyperopt.hyperopter.backtesting.strategy.max_open_trades == 4
|
||||
assert hyperopt.config["max_open_trades"] == 4
|
||||
|
||||
@@ -228,7 +228,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
||||
assert results[0] == response_norate
|
||||
|
||||
|
||||
def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
|
||||
def test_rpc_status_table(default_conf, ticker, fee, mocker, time_machine) -> None:
|
||||
time_machine.move_to("2024-05-10 11:15:00 +00:00", tick=False)
|
||||
mocker.patch.multiple(
|
||||
"freqtrade.rpc.fiat_convert.FtCoinGeckoApi",
|
||||
get_price=MagicMock(return_value={"bitcoin": {"usd": 15000.0}}),
|
||||
|
||||
@@ -1864,7 +1864,21 @@ def test_api_pair_candles(botclient, ohlcv_history):
|
||||
ohlcv_history["exit_short"] = 0
|
||||
|
||||
ftbot.dataprovider._set_cached_df("XRP/BTC", timeframe, ohlcv_history, CandleType.SPOT)
|
||||
fake_plot_annotations = [
|
||||
{
|
||||
"type": "area",
|
||||
"start": "2024-01-01 15:00:00",
|
||||
"end": "2024-01-01 16:00:00",
|
||||
"y_start": 94000.2,
|
||||
"y_end": 98000,
|
||||
"color": "",
|
||||
"label": "some label",
|
||||
}
|
||||
]
|
||||
plot_annotations_mock = MagicMock(return_value=fake_plot_annotations)
|
||||
ftbot.strategy.plot_annotations = plot_annotations_mock
|
||||
for call in ("get", "post"):
|
||||
plot_annotations_mock.reset_mock()
|
||||
if call == "get":
|
||||
rc = client_get(
|
||||
client,
|
||||
@@ -1894,6 +1908,8 @@ def test_api_pair_candles(botclient, ohlcv_history):
|
||||
assert resp["data_start_ts"] == 1511686200000
|
||||
assert resp["data_stop"] == "2017-11-26 09:00:00+00:00"
|
||||
assert resp["data_stop_ts"] == 1511686800000
|
||||
assert resp["annotations"] == fake_plot_annotations
|
||||
assert plot_annotations_mock.call_count == 1
|
||||
assert isinstance(resp["columns"], list)
|
||||
base_cols = {
|
||||
"date",
|
||||
@@ -2235,6 +2251,7 @@ def test_api_pair_history(botclient, tmp_path, mocker):
|
||||
assert result["data_start_ts"] == 1515628800000
|
||||
assert result["data_stop"] == "2018-01-12 00:00:00+00:00"
|
||||
assert result["data_stop_ts"] == 1515715200000
|
||||
assert result["annotations"] == []
|
||||
lfm.reset_mock()
|
||||
|
||||
# No data found
|
||||
@@ -2869,7 +2886,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmp_path):
|
||||
def test_api_backtest_history(botclient, mocker, testdatadir):
|
||||
ftbot, client = botclient
|
||||
mocker.patch(
|
||||
"freqtrade.data.btanalysis._get_backtest_files",
|
||||
"freqtrade.data.btanalysis.bt_fileutils._get_backtest_files",
|
||||
return_value=[
|
||||
testdatadir / "backtest_results/backtest-result_multistrat.json",
|
||||
testdatadir / "backtest_results/backtest-result.json",
|
||||
|
||||
@@ -946,7 +946,7 @@ def test_is_informative_pairs_callback(default_conf):
|
||||
|
||||
def test_hyperopt_parameters():
|
||||
HyperoptStateContainer.set_state(HyperoptState.INDICATORS)
|
||||
from skopt.space import Categorical, Integer, Real
|
||||
from optuna.distributions import CategoricalDistribution, FloatDistribution, IntDistribution
|
||||
|
||||
with pytest.raises(OperationalException, match=r"Name is determined.*"):
|
||||
IntParameter(low=0, high=5, default=1, name="hello")
|
||||
@@ -977,7 +977,7 @@ def test_hyperopt_parameters():
|
||||
|
||||
intpar = IntParameter(low=0, high=5, default=1, space="buy")
|
||||
assert intpar.value == 1
|
||||
assert isinstance(intpar.get_space(""), Integer)
|
||||
assert isinstance(intpar.get_space(""), IntDistribution)
|
||||
assert isinstance(intpar.range, range)
|
||||
assert len(list(intpar.range)) == 1
|
||||
# Range contains ONLY the default / value.
|
||||
@@ -989,7 +989,7 @@ def test_hyperopt_parameters():
|
||||
|
||||
fltpar = RealParameter(low=0.0, high=5.5, default=1.0, space="buy")
|
||||
assert fltpar.value == 1
|
||||
assert isinstance(fltpar.get_space(""), Real)
|
||||
assert isinstance(fltpar.get_space(""), FloatDistribution)
|
||||
|
||||
fltpar = DecimalParameter(low=0.0, high=0.5, default=0.14, decimals=1, space="buy")
|
||||
assert fltpar.value == 0.1
|
||||
@@ -1006,7 +1006,7 @@ def test_hyperopt_parameters():
|
||||
["buy_rsi", "buy_macd", "buy_none"], default="buy_macd", space="buy"
|
||||
)
|
||||
assert catpar.value == "buy_macd"
|
||||
assert isinstance(catpar.get_space(""), Categorical)
|
||||
assert isinstance(catpar.get_space(""), CategoricalDistribution)
|
||||
assert isinstance(catpar.range, list)
|
||||
assert len(list(catpar.range)) == 1
|
||||
# Range contains ONLY the default / value.
|
||||
@@ -1017,7 +1017,7 @@ def test_hyperopt_parameters():
|
||||
|
||||
boolpar = BooleanParameter(default=True, space="buy")
|
||||
assert boolpar.value is True
|
||||
assert isinstance(boolpar.get_space(""), Categorical)
|
||||
assert isinstance(boolpar.get_space(""), CategoricalDistribution)
|
||||
assert isinstance(boolpar.range, list)
|
||||
assert len(list(boolpar.range)) == 1
|
||||
|
||||
|
||||
@@ -385,6 +385,17 @@ def test_strategy_max_open_trades_infinity_from_strategy(caplog, default_conf):
|
||||
assert strategy.max_open_trades == float("inf")
|
||||
assert default_conf["max_open_trades"] == float("inf")
|
||||
|
||||
# test if the default value is set to infinity (V2 doesn't set max_open_trades explicitly)
|
||||
del default_conf["max_open_trades"]
|
||||
default_conf.update(
|
||||
{
|
||||
"strategy": "StrategyTestV2",
|
||||
}
|
||||
)
|
||||
strategy2 = StrategyResolver.load_strategy(default_conf)
|
||||
assert strategy2.max_open_trades == float("inf")
|
||||
assert default_conf["max_open_trades"] == float("inf")
|
||||
|
||||
|
||||
def test_strategy_max_open_trades_infinity_from_config(caplog, default_conf, mocker):
|
||||
caplog.set_level(logging.INFO)
|
||||
|
||||
Reference in New Issue
Block a user