Merge branch 'develop' into freqai-pytorch-bugfixes
This commit is contained in:
@@ -1389,8 +1389,6 @@ def test_convert_data_trades(mocker, testdatadir):
|
||||
def test_start_list_data(testdatadir, capsys):
|
||||
args = [
|
||||
"list-data",
|
||||
"--data-format-ohlcv",
|
||||
"json",
|
||||
"--datadir",
|
||||
str(testdatadir),
|
||||
]
|
||||
@@ -1398,14 +1396,14 @@ def test_start_list_data(testdatadir, capsys):
|
||||
pargs['config'] = None
|
||||
start_list_data(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert "Found 17 pair / timeframe combinations." in captured.out
|
||||
assert "Found 16 pair / timeframe combinations." in captured.out
|
||||
assert "\n| Pair | Timeframe | Type |\n" in captured.out
|
||||
assert "\n| UNITTEST/BTC | 1m, 5m, 8m, 30m | spot |\n" in captured.out
|
||||
|
||||
args = [
|
||||
"list-data",
|
||||
"--data-format-ohlcv",
|
||||
"json",
|
||||
"feather",
|
||||
"--pairs", "XRP/ETH",
|
||||
"--datadir",
|
||||
str(testdatadir),
|
||||
@@ -1421,8 +1419,6 @@ def test_start_list_data(testdatadir, capsys):
|
||||
|
||||
args = [
|
||||
"list-data",
|
||||
"--data-format-ohlcv",
|
||||
"json",
|
||||
"--trading-mode", "futures",
|
||||
"--datadir",
|
||||
str(testdatadir),
|
||||
@@ -1439,8 +1435,6 @@ def test_start_list_data(testdatadir, capsys):
|
||||
|
||||
args = [
|
||||
"list-data",
|
||||
"--data-format-ohlcv",
|
||||
"json",
|
||||
"--pairs", "XRP/ETH",
|
||||
"--datadir",
|
||||
str(testdatadir),
|
||||
|
||||
+17
-16
@@ -526,6 +526,7 @@ def get_default_conf(testdatadir):
|
||||
"disableparamexport": True,
|
||||
"internals": {},
|
||||
"export": "none",
|
||||
"dataformat_ohlcv": "feather",
|
||||
"candle_type_def": CandleType.SPOT,
|
||||
}
|
||||
return configuration
|
||||
@@ -3001,85 +3002,85 @@ def mark_ohlcv():
|
||||
def funding_rate_history_hourly():
|
||||
return [
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000008,
|
||||
"timestamp": 1630454400000,
|
||||
"datetime": "2021-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000004,
|
||||
"timestamp": 1630458000000,
|
||||
"datetime": "2021-09-01T01:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000012,
|
||||
"timestamp": 1630461600000,
|
||||
"datetime": "2021-09-01T02:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000003,
|
||||
"timestamp": 1630465200000,
|
||||
"datetime": "2021-09-01T03:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000007,
|
||||
"timestamp": 1630468800000,
|
||||
"datetime": "2021-09-01T04:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000003,
|
||||
"timestamp": 1630472400000,
|
||||
"datetime": "2021-09-01T05:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000019,
|
||||
"timestamp": 1630476000000,
|
||||
"datetime": "2021-09-01T06:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000003,
|
||||
"timestamp": 1630479600000,
|
||||
"datetime": "2021-09-01T07:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000003,
|
||||
"timestamp": 1630483200000,
|
||||
"datetime": "2021-09-01T08:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0,
|
||||
"timestamp": 1630486800000,
|
||||
"datetime": "2021-09-01T09:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000013,
|
||||
"timestamp": 1630490400000,
|
||||
"datetime": "2021-09-01T10:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000077,
|
||||
"timestamp": 1630494000000,
|
||||
"datetime": "2021-09-01T11:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000072,
|
||||
"timestamp": 1630497600000,
|
||||
"datetime": "2021-09-01T12:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": 0.000097,
|
||||
"timestamp": 1630501200000,
|
||||
"datetime": "2021-09-01T13:00:00.000Z"
|
||||
@@ -3091,13 +3092,13 @@ def funding_rate_history_hourly():
|
||||
def funding_rate_history_octohourly():
|
||||
return [
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000008,
|
||||
"timestamp": 1630454400000,
|
||||
"datetime": "2021-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"symbol": "ADA/USDT",
|
||||
"symbol": "ADA/USDT:USDT",
|
||||
"fundingRate": -0.000003,
|
||||
"timestamp": 1630483200000,
|
||||
"datetime": "2021-09-01T08:00:00.000Z"
|
||||
|
||||
@@ -343,12 +343,24 @@ def test_calculate_expectancy(testdatadir):
|
||||
filename = testdatadir / "backtest_results/backtest-result.json"
|
||||
bt_data = load_backtest_data(filename)
|
||||
|
||||
expectancy = calculate_expectancy(DataFrame())
|
||||
expectancy, expectancy_ratio = calculate_expectancy(DataFrame())
|
||||
assert expectancy == 0.0
|
||||
assert expectancy_ratio == 100
|
||||
|
||||
expectancy = calculate_expectancy(bt_data)
|
||||
expectancy, expectancy_ratio = calculate_expectancy(bt_data)
|
||||
assert isinstance(expectancy, float)
|
||||
assert pytest.approx(expectancy) == 0.07151374226574791
|
||||
assert isinstance(expectancy_ratio, float)
|
||||
assert pytest.approx(expectancy) == 5.820687070932315e-06
|
||||
assert pytest.approx(expectancy_ratio) == 0.07151374226574791
|
||||
|
||||
data = {
|
||||
'profit_abs': [100, 200, 50, -150, 300, -100, 80, -30]
|
||||
}
|
||||
df = DataFrame(data)
|
||||
expectancy, expectancy_ratio = calculate_expectancy(df)
|
||||
|
||||
assert pytest.approx(expectancy) == 56.25
|
||||
assert pytest.approx(expectancy_ratio) == 0.60267857
|
||||
|
||||
|
||||
def test_calculate_sortino(testdatadir):
|
||||
|
||||
@@ -135,6 +135,73 @@ def test_ohlcv_fill_up_missing_data2(caplog):
|
||||
f"{len(data)} - after: {len(data2)}.*", caplog)
|
||||
|
||||
|
||||
def test_ohlcv_to_dataframe_1M():
|
||||
|
||||
# Monthly ticks from 2019-09-01 to 2023-07-01
|
||||
ticks = [
|
||||
[1567296000000, 8042.08, 10475.54, 7700.67, 8041.96, 608742.1109999999],
|
||||
[1569888000000, 8285.31, 10408.48, 7172.76, 9150.0, 2439561.887],
|
||||
[1572566400000, 9149.88, 9550.0, 6510.19, 7542.93, 4042674.725],
|
||||
[1575158400000, 7541.08, 7800.0, 6427.0, 7189.0, 4063882.296],
|
||||
[1577836800000, 7189.43, 9599.0, 6863.44, 9364.51, 5165281.358],
|
||||
[1580515200000, 9364.5, 10540.0, 8450.0, 8531.98, 4581788.124],
|
||||
[1583020800000, 8532.5, 9204.0, 3621.81, 6407.1, 10859497.479],
|
||||
[1585699200000, 6407.1, 9479.77, 6140.0, 8624.76, 11276526.968],
|
||||
[1588291200000, 8623.61, 10080.0, 7940.0, 9446.43, 12469561.02],
|
||||
[1590969600000, 9446.49, 10497.25, 8816.4, 9138.87, 6684044.201],
|
||||
[1593561600000, 9138.88, 11488.0, 8900.0, 11343.68, 5709327.926],
|
||||
[1596240000000, 11343.67, 12499.42, 10490.0, 11658.11, 6746487.129],
|
||||
[1598918400000, 11658.11, 12061.07, 9808.58, 10773.0, 6442697.051],
|
||||
[1601510400000, 10773.0, 14140.0, 10371.03, 13783.73, 7404103.004],
|
||||
[1604188800000, 13783.73, 19944.0, 13195.0, 19720.0, 12328272.549],
|
||||
[1606780800000, 19722.09, 29376.7, 17555.0, 28951.68, 10067314.24],
|
||||
[1609459200000, 28948.19, 42125.51, 27800.0, 33126.21, 12408873.079],
|
||||
[1612137600000, 33125.11, 58472.14, 32322.47, 45163.36, 8784474.482],
|
||||
[1614556800000, 45162.64, 61950.0, 44972.49, 58807.24, 9459821.267],
|
||||
[1617235200000, 58810.99, 64986.11, 46930.43, 57684.16, 7895051.389],
|
||||
[1619827200000, 57688.29, 59654.0, 28688.0, 37243.38, 16790964.443],
|
||||
[1622505600000, 37244.36, 41413.0, 28780.01, 35031.39, 23474519.886],
|
||||
[1625097600000, 35031.39, 48168.6, 29242.24, 41448.11, 16932491.175],
|
||||
[1627776000000, 41448.1, 50600.0, 37291.0, 47150.32, 13645800.254],
|
||||
[1630454400000, 47150.32, 52950.0, 39503.58, 43796.57, 10734742.869],
|
||||
[1633046400000, 43799.49, 67150.0, 43260.01, 61348.61, 9111112.847],
|
||||
[1635724800000, 61347.14, 69198.7, 53245.0, 56975.0, 7111424.463],
|
||||
[1638316800000, 56978.06, 59100.0, 40888.89, 46210.56, 8404449.024],
|
||||
[1640995200000, 46210.57, 48000.0, 32853.83, 38439.04, 11047479.277],
|
||||
[1643673600000, 38439.04, 45847.5, 34303.7, 43155.0, 10910339.91],
|
||||
[1646092800000, 43155.0, 48200.0, 37134.0, 45506.0, 10459721.586],
|
||||
[1648771200000, 45505.9, 47448.0, 37550.0, 37614.5, 8463568.862],
|
||||
[1651363200000, 37614.4, 40071.7, 26631.0, 31797.8, 14463715.774],
|
||||
[1654041600000, 31797.9, 31986.1, 17593.2, 19923.5, 20710810.306],
|
||||
[1656633600000, 19923.3, 24700.0, 18780.1, 23290.1, 20582518.513],
|
||||
[1659312000000, 23290.1, 25200.0, 19508.0, 20041.5, 17221921.557],
|
||||
[1661990400000, 20041.4, 22850.0, 18084.3, 19411.7, 21935261.414],
|
||||
[1664582400000, 19411.6, 21088.0, 17917.8, 20482.0, 16625843.584],
|
||||
[1667260800000, 20482.1, 21473.7, 15443.2, 17153.3, 18460614.013],
|
||||
[1669852800000, 17153.4, 18400.0, 16210.0, 16537.6, 9702408.711],
|
||||
[1672531200000, 16537.5, 23962.7, 16488.0, 23119.4, 14732180.645],
|
||||
[1675209600000, 23119.5, 25347.6, 21338.0, 23129.6, 15025197.415],
|
||||
[1677628800000, 23129.7, 29184.8, 19521.6, 28454.9, 23317458.541],
|
||||
[1680307200000, 28454.8, 31059.0, 26919.3, 29223.0, 14654208.219],
|
||||
[1682899200000, 29223.0, 29840.0, 25751.0, 27201.1, 13328157.284],
|
||||
[1685577600000, 27201.1, 31500.0, 24777.0, 30460.2, 14099299.273],
|
||||
[1688169600000, 30460.2, 31850.0, 28830.0, 29338.8, 8760361.377]
|
||||
]
|
||||
|
||||
data = ohlcv_to_dataframe(ticks, '1M', pair="UNITTEST/USDT",
|
||||
fill_missing=False, drop_incomplete=False)
|
||||
assert len(data) == len(ticks)
|
||||
assert data.iloc[0]['date'].strftime('%Y-%m-%d') == '2019-09-01'
|
||||
assert data.iloc[-1]['date'].strftime('%Y-%m-%d') == '2023-07-01'
|
||||
|
||||
# Test with filling missing data
|
||||
data = ohlcv_to_dataframe(ticks, '1M', pair="UNITTEST/USDT",
|
||||
fill_missing=True, drop_incomplete=False)
|
||||
assert len(data) == len(ticks)
|
||||
assert data.iloc[0]['date'].strftime('%Y-%m-%d') == '2019-09-01'
|
||||
assert data.iloc[-1]['date'].strftime('%Y-%m-%d') == '2023-07-01'
|
||||
|
||||
|
||||
def test_ohlcv_drop_incomplete(caplog):
|
||||
timeframe = '1d'
|
||||
ticks = [
|
||||
@@ -304,8 +371,8 @@ def test_convert_ohlcv_format(default_conf, testdatadir, tmpdir, file_base, cand
|
||||
files_temp = []
|
||||
files_new = []
|
||||
for file in file_base:
|
||||
file_orig = testdatadir / f"{prependix}{file}.json"
|
||||
file_temp = tmpdir1 / f"{prependix}{file}.json"
|
||||
file_orig = testdatadir / f"{prependix}{file}.feather"
|
||||
file_temp = tmpdir1 / f"{prependix}{file}.feather"
|
||||
file_new = tmpdir1 / f"{prependix}{file}.json.gz"
|
||||
IDataHandler.create_dir_if_needed(file_temp)
|
||||
copyfile(file_orig, file_temp)
|
||||
@@ -327,7 +394,7 @@ def test_convert_ohlcv_format(default_conf, testdatadir, tmpdir, file_base, cand
|
||||
|
||||
convert_ohlcv_format(
|
||||
default_conf,
|
||||
convert_from='json',
|
||||
convert_from='feather',
|
||||
convert_to='jsongz',
|
||||
erase=False,
|
||||
)
|
||||
@@ -341,7 +408,7 @@ def test_convert_ohlcv_format(default_conf, testdatadir, tmpdir, file_base, cand
|
||||
convert_ohlcv_format(
|
||||
default_conf,
|
||||
convert_from='jsongz',
|
||||
convert_to='json',
|
||||
convert_to='feather',
|
||||
erase=True,
|
||||
)
|
||||
for file in (files_temp):
|
||||
|
||||
@@ -20,7 +20,7 @@ from tests.conftest import log_has, log_has_re
|
||||
|
||||
|
||||
def test_datahandler_ohlcv_get_pairs(testdatadir):
|
||||
pairs = JsonDataHandler.ohlcv_get_pairs(testdatadir, '5m', candle_type=CandleType.SPOT)
|
||||
pairs = FeatherDataHandler.ohlcv_get_pairs(testdatadir, '5m', candle_type=CandleType.SPOT)
|
||||
# Convert to set to avoid failures due to sorting
|
||||
assert set(pairs) == {'UNITTEST/BTC', 'XLM/BTC', 'ETH/BTC', 'TRX/BTC', 'LTC/BTC',
|
||||
'XMR/BTC', 'ZEC/BTC', 'ADA/BTC', 'ETC/BTC', 'NXT/BTC',
|
||||
@@ -32,7 +32,7 @@ def test_datahandler_ohlcv_get_pairs(testdatadir):
|
||||
pairs = HDF5DataHandler.ohlcv_get_pairs(testdatadir, '5m', candle_type=CandleType.SPOT)
|
||||
assert set(pairs) == {'UNITTEST/BTC'}
|
||||
|
||||
pairs = JsonDataHandler.ohlcv_get_pairs(testdatadir, '1h', candle_type=CandleType.MARK)
|
||||
pairs = FeatherDataHandler.ohlcv_get_pairs(testdatadir, '1h', candle_type=CandleType.MARK)
|
||||
assert set(pairs) == {'UNITTEST/USDT:USDT', 'XRP/USDT:USDT'}
|
||||
|
||||
pairs = JsonGzDataHandler.ohlcv_get_pairs(testdatadir, '1h', candle_type=CandleType.FUTURES)
|
||||
@@ -79,7 +79,7 @@ def test_rebuild_pair_from_filename(input, expected):
|
||||
|
||||
|
||||
def test_datahandler_ohlcv_get_available_data(testdatadir):
|
||||
paircombs = JsonDataHandler.ohlcv_get_available_data(testdatadir, TradingMode.SPOT)
|
||||
paircombs = FeatherDataHandler.ohlcv_get_available_data(testdatadir, TradingMode.SPOT)
|
||||
# Convert to set to avoid failures due to sorting
|
||||
assert set(paircombs) == {
|
||||
('UNITTEST/BTC', '5m', CandleType.SPOT),
|
||||
@@ -98,10 +98,9 @@ def test_datahandler_ohlcv_get_available_data(testdatadir):
|
||||
('XRP/ETH', '5m', CandleType.SPOT),
|
||||
('UNITTEST/BTC', '30m', CandleType.SPOT),
|
||||
('UNITTEST/BTC', '8m', CandleType.SPOT),
|
||||
('NOPAIR/XXX', '4m', CandleType.SPOT),
|
||||
}
|
||||
|
||||
paircombs = JsonDataHandler.ohlcv_get_available_data(testdatadir, TradingMode.FUTURES)
|
||||
paircombs = FeatherDataHandler.ohlcv_get_available_data(testdatadir, TradingMode.FUTURES)
|
||||
# Convert to set to avoid failures due to sorting
|
||||
assert set(paircombs) == {
|
||||
('UNITTEST/USDT:USDT', '1h', 'mark'),
|
||||
@@ -140,16 +139,11 @@ def test_jsondatahandler_ohlcv_purge(mocker, testdatadir):
|
||||
|
||||
def test_jsondatahandler_ohlcv_load(testdatadir, caplog):
|
||||
dh = JsonDataHandler(testdatadir)
|
||||
df = dh.ohlcv_load('XRP/ETH', '5m', 'spot')
|
||||
assert len(df) == 712
|
||||
|
||||
df_mark = dh.ohlcv_load('UNITTEST/USDT:USDT', '1h', candle_type="mark")
|
||||
assert len(df_mark) == 100
|
||||
df = dh.ohlcv_load('UNITTEST/BTC', '1m', 'spot')
|
||||
assert len(df) > 0
|
||||
|
||||
df_no_mark = dh.ohlcv_load('UNITTEST/USDT', '1h', 'spot')
|
||||
assert len(df_no_mark) == 0
|
||||
|
||||
# Failure case (empty array)
|
||||
# # Failure case (empty array)
|
||||
df1 = dh.ohlcv_load('NOPAIR/XXX', '4m', 'spot')
|
||||
assert len(df1) == 0
|
||||
assert log_has("Could not load data for NOPAIR/XXX.", caplog)
|
||||
@@ -444,7 +438,7 @@ def test_generic_datahandler_ohlcv_load_and_resave(
|
||||
tmpdir2 = tmpdir1 / 'futures'
|
||||
tmpdir2.mkdir()
|
||||
# Load data from one common file
|
||||
dhbase = get_datahandler(testdatadir, 'json')
|
||||
dhbase = get_datahandler(testdatadir, 'feather')
|
||||
ohlcv = dhbase._ohlcv_load(pair, timeframe, None, candle_type=candle_type)
|
||||
assert isinstance(ohlcv, DataFrame)
|
||||
assert len(ohlcv) > 0
|
||||
|
||||
@@ -63,9 +63,10 @@ def test_historic_ohlcv(mocker, default_conf, ohlcv_history):
|
||||
|
||||
def test_historic_ohlcv_dataformat(mocker, default_conf, ohlcv_history):
|
||||
hdf5loadmock = MagicMock(return_value=ohlcv_history)
|
||||
jsonloadmock = MagicMock(return_value=ohlcv_history)
|
||||
featherloadmock = MagicMock(return_value=ohlcv_history)
|
||||
mocker.patch("freqtrade.data.history.hdf5datahandler.HDF5DataHandler._ohlcv_load", hdf5loadmock)
|
||||
mocker.patch("freqtrade.data.history.jsondatahandler.JsonDataHandler._ohlcv_load", jsonloadmock)
|
||||
mocker.patch("freqtrade.data.history.featherdatahandler.FeatherDataHandler._ohlcv_load",
|
||||
featherloadmock)
|
||||
|
||||
default_conf["runmode"] = RunMode.BACKTEST
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
@@ -73,17 +74,17 @@ def test_historic_ohlcv_dataformat(mocker, default_conf, ohlcv_history):
|
||||
data = dp.historic_ohlcv("UNITTEST/BTC", "5m")
|
||||
assert isinstance(data, DataFrame)
|
||||
hdf5loadmock.assert_not_called()
|
||||
jsonloadmock.assert_called_once()
|
||||
featherloadmock.assert_called_once()
|
||||
|
||||
# Switching to dataformat hdf5
|
||||
hdf5loadmock.reset_mock()
|
||||
jsonloadmock.reset_mock()
|
||||
featherloadmock.reset_mock()
|
||||
default_conf["dataformat_ohlcv"] = "hdf5"
|
||||
dp = DataProvider(default_conf, exchange)
|
||||
data = dp.historic_ohlcv("UNITTEST/BTC", "5m")
|
||||
assert isinstance(data, DataFrame)
|
||||
hdf5loadmock.assert_called_once()
|
||||
jsonloadmock.assert_not_called()
|
||||
featherloadmock.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candle_type', [
|
||||
|
||||
+18
-16
@@ -68,7 +68,7 @@ def test_load_data_7min_timeframe(caplog, testdatadir) -> None:
|
||||
|
||||
def test_load_data_1min_timeframe(ohlcv_history, mocker, caplog, testdatadir) -> None:
|
||||
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history)
|
||||
file = testdatadir / 'UNITTEST_BTC-1m.json'
|
||||
file = testdatadir / 'UNITTEST_BTC-1m.feather'
|
||||
load_data(datadir=testdatadir, timeframe='1m', pairs=['UNITTEST/BTC'])
|
||||
assert file.is_file()
|
||||
assert not log_has(
|
||||
@@ -79,7 +79,7 @@ def test_load_data_1min_timeframe(ohlcv_history, mocker, caplog, testdatadir) ->
|
||||
|
||||
def test_load_data_mark(ohlcv_history, mocker, caplog, testdatadir) -> None:
|
||||
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history)
|
||||
file = testdatadir / 'futures/UNITTEST_USDT_USDT-1h-mark.json'
|
||||
file = testdatadir / 'futures/UNITTEST_USDT_USDT-1h-mark.feather'
|
||||
load_data(datadir=testdatadir, timeframe='1h', pairs=['UNITTEST/BTC'], candle_type='mark')
|
||||
assert file.is_file()
|
||||
assert not log_has(
|
||||
@@ -90,7 +90,7 @@ def test_load_data_mark(ohlcv_history, mocker, caplog, testdatadir) -> None:
|
||||
|
||||
def test_load_data_startup_candles(mocker, testdatadir) -> None:
|
||||
ltfmock = mocker.patch(
|
||||
'freqtrade.data.history.jsondatahandler.JsonDataHandler._ohlcv_load',
|
||||
'freqtrade.data.history.featherdatahandler.FeatherDataHandler._ohlcv_load',
|
||||
MagicMock(return_value=DataFrame()))
|
||||
timerange = TimeRange('date', None, 1510639620, 0)
|
||||
load_pair_history(pair='UNITTEST/BTC', timeframe='1m',
|
||||
@@ -112,7 +112,7 @@ def test_load_data_with_new_pair_1min(ohlcv_history_list, mocker, caplog,
|
||||
tmpdir1 = Path(tmpdir)
|
||||
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history_list)
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
file = tmpdir1 / 'MEME_BTC-1m.json'
|
||||
file = tmpdir1 / 'MEME_BTC-1m.feather'
|
||||
|
||||
# do not download a new pair if refresh_pairs isn't set
|
||||
load_pair_history(datadir=tmpdir1, timeframe='1m', pair='MEME/BTC', candle_type=candle_type)
|
||||
@@ -280,10 +280,10 @@ def test_download_pair_history(
|
||||
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history_list)
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
tmpdir1 = Path(tmpdir)
|
||||
file1_1 = tmpdir1 / f'{subdir}MEME_BTC-1m{file_tail}.json'
|
||||
file1_5 = tmpdir1 / f'{subdir}MEME_BTC-5m{file_tail}.json'
|
||||
file2_1 = tmpdir1 / f'{subdir}CFI_BTC-1m{file_tail}.json'
|
||||
file2_5 = tmpdir1 / f'{subdir}CFI_BTC-5m{file_tail}.json'
|
||||
file1_1 = tmpdir1 / f'{subdir}MEME_BTC-1m{file_tail}.feather'
|
||||
file1_5 = tmpdir1 / f'{subdir}MEME_BTC-5m{file_tail}.feather'
|
||||
file2_1 = tmpdir1 / f'{subdir}CFI_BTC-1m{file_tail}.feather'
|
||||
file2_5 = tmpdir1 / f'{subdir}CFI_BTC-5m{file_tail}.feather'
|
||||
|
||||
assert not file1_1.is_file()
|
||||
assert not file2_1.is_file()
|
||||
@@ -326,7 +326,7 @@ def test_download_pair_history2(mocker, default_conf, testdatadir) -> None:
|
||||
[1509836580000, 0.00161, 0.00161, 0.00161, 0.00161, 82.390199]
|
||||
]
|
||||
json_dump_mock = mocker.patch(
|
||||
'freqtrade.data.history.jsondatahandler.JsonDataHandler.ohlcv_store',
|
||||
'freqtrade.data.history.featherdatahandler.FeatherDataHandler.ohlcv_store',
|
||||
return_value=None)
|
||||
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=tick)
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
@@ -386,7 +386,7 @@ def test_load_partial_missing(testdatadir, caplog) -> None:
|
||||
|
||||
def test_init(default_conf) -> None:
|
||||
assert {} == load_data(
|
||||
datadir=Path(''),
|
||||
datadir=Path(),
|
||||
pairs=[],
|
||||
timeframe=default_conf['timeframe']
|
||||
)
|
||||
@@ -395,14 +395,14 @@ def test_init(default_conf) -> None:
|
||||
def test_init_with_refresh(default_conf, mocker) -> None:
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
refresh_data(
|
||||
datadir=Path(''),
|
||||
datadir=Path(),
|
||||
pairs=[],
|
||||
timeframe=default_conf['timeframe'],
|
||||
exchange=exchange,
|
||||
candle_type=CandleType.SPOT
|
||||
)
|
||||
assert {} == load_data(
|
||||
datadir=Path(''),
|
||||
datadir=Path(),
|
||||
pairs=[],
|
||||
timeframe=default_conf['timeframe']
|
||||
)
|
||||
@@ -627,8 +627,8 @@ def test_download_trades_history(trades_history, mocker, default_conf, testdatad
|
||||
def test_convert_trades_to_ohlcv(testdatadir, tmpdir, caplog):
|
||||
tmpdir1 = Path(tmpdir)
|
||||
pair = 'XRP/ETH'
|
||||
file1 = tmpdir1 / 'XRP_ETH-1m.json'
|
||||
file5 = tmpdir1 / 'XRP_ETH-5m.json'
|
||||
file1 = tmpdir1 / 'XRP_ETH-1m.feather'
|
||||
file5 = tmpdir1 / 'XRP_ETH-5m.feather'
|
||||
filetrades = tmpdir1 / 'XRP_ETH-trades.json.gz'
|
||||
copyfile(testdatadir / file1.name, file1)
|
||||
copyfile(testdatadir / file5.name, file5)
|
||||
@@ -641,6 +641,7 @@ def test_convert_trades_to_ohlcv(testdatadir, tmpdir, caplog):
|
||||
tr = TimeRange.parse_timerange('20191011-20191012')
|
||||
|
||||
convert_trades_to_ohlcv([pair], timeframes=['1m', '5m'],
|
||||
data_format_trades='jsongz',
|
||||
datadir=tmpdir1, timerange=tr, erase=True)
|
||||
|
||||
assert log_has("Deleting existing data for pair XRP/ETH, interval 1m.", caplog)
|
||||
@@ -648,11 +649,12 @@ def test_convert_trades_to_ohlcv(testdatadir, tmpdir, caplog):
|
||||
df_1m = load_pair_history(datadir=tmpdir1, timeframe="1m", pair=pair)
|
||||
df_5m = load_pair_history(datadir=tmpdir1, timeframe="5m", pair=pair)
|
||||
|
||||
assert df_1m.equals(dfbak_1m)
|
||||
assert df_5m.equals(dfbak_5m)
|
||||
assert_frame_equal(dfbak_1m, df_1m, check_exact=True)
|
||||
assert_frame_equal(dfbak_5m, df_5m, check_exact=True)
|
||||
|
||||
assert not log_has('Could not convert NoDatapair to OHLCV.', caplog)
|
||||
|
||||
convert_trades_to_ohlcv(['NoDatapair'], timeframes=['1m', '5m'],
|
||||
data_format_trades='jsongz',
|
||||
datadir=tmpdir1, timerange=tr, erase=True)
|
||||
assert log_has('Could not convert NoDatapair to OHLCV.', caplog)
|
||||
|
||||
@@ -391,7 +391,7 @@ class TestCCXTExchange:
|
||||
assert po['id'] is not None
|
||||
if len(order.keys()) < 5:
|
||||
# Kucoin case
|
||||
assert po['status'] == 'closed'
|
||||
assert po['status'] is None
|
||||
continue
|
||||
assert po['timestamp'] == 1674493798550
|
||||
assert isinstance(po['datetime'], str)
|
||||
|
||||
@@ -4343,11 +4343,11 @@ def test__fetch_and_calculate_funding_fees(
|
||||
ex = get_patched_exchange(mocker, default_conf, api_mock, id=exchange)
|
||||
mocker.patch(f'{EXMS}.timeframes', PropertyMock(return_value=['1h', '4h', '8h']))
|
||||
funding_fees = ex._fetch_and_calculate_funding_fees(
|
||||
pair='ADA/USDT', amount=amount, is_short=True, open_date=d1, close_date=d2)
|
||||
pair='ADA/USDT:USDT', amount=amount, is_short=True, open_date=d1, close_date=d2)
|
||||
assert pytest.approx(funding_fees) == expected_fees
|
||||
# Fees for Longs are inverted
|
||||
funding_fees = ex._fetch_and_calculate_funding_fees(
|
||||
pair='ADA/USDT', amount=amount, is_short=False, open_date=d1, close_date=d2)
|
||||
pair='ADA/USDT:USDT', amount=amount, is_short=False, open_date=d1, close_date=d2)
|
||||
assert pytest.approx(funding_fees) == -expected_fees
|
||||
|
||||
# Return empty "refresh_latest"
|
||||
@@ -4355,7 +4355,7 @@ def test__fetch_and_calculate_funding_fees(
|
||||
ex = get_patched_exchange(mocker, default_conf, api_mock, id=exchange)
|
||||
with pytest.raises(ExchangeError, match="Could not find funding rates."):
|
||||
ex._fetch_and_calculate_funding_fees(
|
||||
pair='ADA/USDT', amount=amount, is_short=False, open_date=d1, close_date=d2)
|
||||
pair='ADA/USDT:USDT', amount=amount, is_short=False, open_date=d1, close_date=d2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('exchange,expected_fees', [
|
||||
@@ -5424,7 +5424,7 @@ def test_stoploss_contract_size(mocker, default_conf, contract_size, order_amoun
|
||||
|
||||
assert api_mock.create_order.call_args_list[0][1]['amount'] == order_amount
|
||||
assert order['amount'] == 100
|
||||
assert order['cost'] == 100
|
||||
assert order['cost'] == order_amount
|
||||
assert order['filled'] == 100
|
||||
assert order['remaining'] == 100
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ from freqtrade.data.history import get_timerange
|
||||
from freqtrade.enums import CandleType, ExitType, RunMode
|
||||
from freqtrade.exceptions import DependencyException, OperationalException
|
||||
from freqtrade.exchange.exchange import timeframe_to_next_date
|
||||
from freqtrade.optimize.backtest_caching import get_strategy_run_id
|
||||
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
|
||||
from freqtrade.resolvers import StrategyResolver
|
||||
@@ -601,6 +601,9 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
|
||||
|
||||
trade = backtesting._enter_trade(pair, row=row, direction='short')
|
||||
assert pytest.approx(trade.liquidation_price) == 0.11787191
|
||||
assert pytest.approx(trade.orders[0].cost) == (
|
||||
trade.stake_amount * trade.leverage + trade.fee_open)
|
||||
assert pytest.approx(trade.orders[-1].stake_amount) == trade.stake_amount
|
||||
|
||||
# Stake-amount too high!
|
||||
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=600.0)
|
||||
@@ -1995,3 +1998,40 @@ def test_get_strategy_run_id(default_conf_usdt):
|
||||
strategy = StrategyResolver.load_strategy(default_conf_usdt)
|
||||
x = get_strategy_run_id(strategy)
|
||||
assert isinstance(x, str)
|
||||
|
||||
|
||||
def test_get_backtest_metadata_filename():
|
||||
# Test with a file path
|
||||
filename = Path('backtest_results.json')
|
||||
expected = Path('backtest_results.meta.json')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
# Test with a file path with multiple dots in the name
|
||||
filename = Path('/path/to/backtest.results.json')
|
||||
expected = Path('/path/to/backtest.results.meta.json')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
# Test with a file path with no parent directory
|
||||
filename = Path('backtest_results.json')
|
||||
expected = Path('backtest_results.meta.json')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
# Test with a string file path
|
||||
filename = '/path/to/backtest_results.json'
|
||||
expected = Path('/path/to/backtest_results.meta.json')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
# Test with a string file path with no extension
|
||||
filename = '/path/to/backtest_results'
|
||||
expected = Path('/path/to/backtest_results.meta')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
# Test with a string file path with multiple dots in the name
|
||||
filename = '/path/to/backtest.results.json'
|
||||
expected = Path('/path/to/backtest.results.meta.json')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
# Test with a string file path with no parent directory
|
||||
filename = 'backtest_results.json'
|
||||
expected = Path('backtest_results.meta.json')
|
||||
assert get_backtest_metadata_filename(filename) == expected
|
||||
|
||||
@@ -23,7 +23,8 @@ from freqtrade.optimize.optimize_reports import (generate_backtest_stats, genera
|
||||
store_backtest_analysis_results,
|
||||
store_backtest_stats, text_table_bt_results,
|
||||
text_table_exit_reason, text_table_strategy)
|
||||
from freqtrade.optimize.optimize_reports.optimize_reports import _get_resample_from_period
|
||||
from freqtrade.optimize.optimize_reports.optimize_reports import (_get_resample_from_period,
|
||||
calc_streak)
|
||||
from freqtrade.resolvers.strategy_resolver import StrategyResolver
|
||||
from freqtrade.util import dt_ts
|
||||
from freqtrade.util.datetime_helpers import dt_from_ts, dt_utc
|
||||
@@ -212,7 +213,8 @@ def test_store_backtest_stats(testdatadir, mocker):
|
||||
|
||||
dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.bt_storage.file_dump_json')
|
||||
|
||||
store_backtest_stats(testdatadir, {'metadata': {}}, '2022_01_01_15_05_13')
|
||||
data = {'metadata': {}, 'strategy': {}, 'strategy_comparison': []}
|
||||
store_backtest_stats(testdatadir, data, '2022_01_01_15_05_13')
|
||||
|
||||
assert dump_mock.call_count == 3
|
||||
assert isinstance(dump_mock.call_args_list[0][0][0], Path)
|
||||
@@ -220,7 +222,7 @@ def test_store_backtest_stats(testdatadir, mocker):
|
||||
|
||||
dump_mock.reset_mock()
|
||||
filename = testdatadir / 'testresult.json'
|
||||
store_backtest_stats(filename, {'metadata': {}}, '2022_01_01_15_05_13')
|
||||
store_backtest_stats(filename, data, '2022_01_01_15_05_13')
|
||||
assert dump_mock.call_count == 3
|
||||
assert isinstance(dump_mock.call_args_list[0][0][0], Path)
|
||||
# result will be testdatadir / testresult-<timestamp>.json
|
||||
@@ -348,6 +350,32 @@ def test_generate_trading_stats(testdatadir):
|
||||
assert res['losses'] == 0
|
||||
|
||||
|
||||
def test_calc_streak(testdatadir):
|
||||
df = pd.DataFrame({
|
||||
'profit_ratio': [0.05, -0.02, -0.03, -0.05, 0.01, 0.02, 0.03, 0.04, -0.02, -0.03],
|
||||
})
|
||||
# 4 consecutive wins, 3 consecutive losses
|
||||
res = calc_streak(df)
|
||||
assert res == (4, 3)
|
||||
assert isinstance(res[0], int)
|
||||
assert isinstance(res[1], int)
|
||||
|
||||
# invert situation
|
||||
df1 = df.copy()
|
||||
df1['profit_ratio'] = df1['profit_ratio'] * -1
|
||||
assert calc_streak(df1) == (3, 4)
|
||||
|
||||
df_empty = pd.DataFrame({
|
||||
'profit_ratio': [],
|
||||
})
|
||||
assert df_empty.empty
|
||||
assert calc_streak(df_empty) == (0, 0)
|
||||
|
||||
filename = testdatadir / "backtest_results/backtest-result.json"
|
||||
bt_data = load_backtest_data(filename)
|
||||
assert calc_streak(bt_data) == (7, 18)
|
||||
|
||||
|
||||
def test_text_table_exit_reason():
|
||||
|
||||
results = pd.DataFrame(
|
||||
|
||||
@@ -563,14 +563,14 @@ def test_calc_open_close_trade_price(
|
||||
trade.open_order_id = f'something-{is_short}-{lev}-{exchange}'
|
||||
|
||||
oobj = Order.parse_from_ccxt_object(entry_order, 'ADA/USDT', trade.entry_side)
|
||||
oobj.trade = trade
|
||||
oobj._trade_live = trade
|
||||
oobj.update_from_ccxt_object(entry_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.funding_fees = funding_fees
|
||||
|
||||
oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', trade.exit_side)
|
||||
oobj.trade = trade
|
||||
oobj._trade_live = trade
|
||||
oobj.update_from_ccxt_object(exit_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ def test_trade_fromjson():
|
||||
assert trade.open_date_utc == datetime(2022, 10, 18, 9, 12, 42, tzinfo=timezone.utc)
|
||||
assert isinstance(trade.open_date, datetime)
|
||||
assert trade.exit_reason == 'no longer good'
|
||||
assert trade.realized_profit == 2.76315361
|
||||
|
||||
assert len(trade.orders) == 5
|
||||
last_o = trade.orders[-1]
|
||||
|
||||
@@ -35,7 +35,7 @@ def test_gen_pairlist_with_local_file(mocker, rpl_config):
|
||||
mock_file_path.exists.return_value = True
|
||||
|
||||
jsonparse = json.loads(mock_file.read.return_value)
|
||||
mocker.patch('freqtrade.plugins.pairlist.RemotePairList.json.load', return_value=jsonparse)
|
||||
mocker.patch('freqtrade.plugins.pairlist.RemotePairList.rapidjson.load', return_value=jsonparse)
|
||||
|
||||
rpl_config['pairlists'] = [
|
||||
{
|
||||
|
||||
@@ -402,6 +402,8 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
assert res['first_trade_timestamp'] == 0
|
||||
assert res['latest_trade_date'] == ''
|
||||
assert res['latest_trade_timestamp'] == 0
|
||||
assert res['expectancy'] == 0
|
||||
assert res['expectancy_ratio'] == 100
|
||||
|
||||
# Create some test data
|
||||
create_mock_trades_usdt(fee)
|
||||
@@ -413,6 +415,9 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
assert pytest.approx(stats['profit_all_coin']) == -77.45964918
|
||||
assert pytest.approx(stats['profit_all_percent_mean']) == -57.86
|
||||
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
|
||||
assert pytest.approx(stats['winrate']) == 0.666666667
|
||||
assert pytest.approx(stats['expectancy']) == 0.913333333
|
||||
assert pytest.approx(stats['expectancy_ratio']) == 0.223308883
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_humanized'] == '2 days ago'
|
||||
assert stats['latest_trade_humanized'] == '17 minutes ago'
|
||||
|
||||
+155
-18
@@ -10,6 +10,7 @@ from unittest.mock import ANY, MagicMock, PropertyMock
|
||||
|
||||
import pandas as pd
|
||||
import pytest
|
||||
import rapidjson
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, WebSocketDisconnect
|
||||
from fastapi.exceptions import HTTPException
|
||||
@@ -80,6 +81,16 @@ def client_post(client: TestClient, url, data={}):
|
||||
})
|
||||
|
||||
|
||||
def client_patch(client: TestClient, url, data={}):
|
||||
|
||||
return client.patch(url,
|
||||
json=data,
|
||||
headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS),
|
||||
'Origin': 'http://example.com',
|
||||
'content-type': 'application/json'
|
||||
})
|
||||
|
||||
|
||||
def client_get(client: TestClient, url):
|
||||
# Add fake Origin to ensure CORS kicks in
|
||||
return client.get(url, headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS),
|
||||
@@ -829,7 +840,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
||||
'profit_closed_percent_mean': -0.75, 'profit_closed_ratio_sum': -0.015,
|
||||
'profit_closed_percent_sum': -1.5, 'profit_closed_ratio': -6.739057628404269e-06,
|
||||
'profit_closed_percent': -0.0, 'winning_trades': 0, 'losing_trades': 2,
|
||||
'profit_factor': 0.0, 'trading_volume': 91.074,
|
||||
'profit_factor': 0.0, 'winrate': 0.0, 'expectancy': -0.0033695635,
|
||||
'expectancy_ratio': -1.0, 'trading_volume': 91.074,
|
||||
}
|
||||
),
|
||||
(
|
||||
@@ -844,7 +856,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
||||
'profit_closed_percent_mean': 0.75, 'profit_closed_ratio_sum': 0.015,
|
||||
'profit_closed_percent_sum': 1.5, 'profit_closed_ratio': 7.391275897987988e-07,
|
||||
'profit_closed_percent': 0.0, 'winning_trades': 2, 'losing_trades': 0,
|
||||
'profit_factor': None, 'trading_volume': 91.074,
|
||||
'profit_factor': None, 'winrate': 1.0, 'expectancy': 0.0003695635,
|
||||
'expectancy_ratio': 100, 'trading_volume': 91.074,
|
||||
}
|
||||
),
|
||||
(
|
||||
@@ -859,7 +872,9 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
||||
'profit_closed_percent_mean': 0.25, 'profit_closed_ratio_sum': 0.005,
|
||||
'profit_closed_percent_sum': 0.5, 'profit_closed_ratio': -5.429078808526421e-06,
|
||||
'profit_closed_percent': -0.0, 'winning_trades': 1, 'losing_trades': 1,
|
||||
'profit_factor': 0.02775724835771106, 'trading_volume': 91.074,
|
||||
'profit_factor': 0.02775724835771106, 'winrate': 0.5,
|
||||
'expectancy': -0.0027145635000000003, 'expectancy_ratio': -0.48612137582114445,
|
||||
'trading_volume': 91.074,
|
||||
}
|
||||
)
|
||||
])
|
||||
@@ -916,6 +931,9 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected)
|
||||
'winning_trades': expected['winning_trades'],
|
||||
'losing_trades': expected['losing_trades'],
|
||||
'profit_factor': expected['profit_factor'],
|
||||
'winrate': expected['winrate'],
|
||||
'expectancy': expected['expectancy'],
|
||||
'expectancy_ratio': expected['expectancy_ratio'],
|
||||
'max_drawdown': ANY,
|
||||
'max_drawdown_abs': ANY,
|
||||
'trading_volume': expected['trading_volume'],
|
||||
@@ -1469,30 +1487,47 @@ def test_api_pair_history(botclient, mocker):
|
||||
"&timerange=20180111-20180112")
|
||||
assert_response(rc, 422)
|
||||
|
||||
# Invalid strategy
|
||||
rc = client_get(client,
|
||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
||||
"&timerange=20180111-20180112&strategy={CURRENT_TEST_STRATEGY}11")
|
||||
assert_response(rc, 502)
|
||||
|
||||
# Working
|
||||
rc = client_get(client,
|
||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
||||
f"&timerange=20180111-20180112&strategy={CURRENT_TEST_STRATEGY}")
|
||||
assert_response(rc, 200)
|
||||
assert rc.json()['length'] == 289
|
||||
assert len(rc.json()['data']) == rc.json()['length']
|
||||
assert 'columns' in rc.json()
|
||||
assert 'data' in rc.json()
|
||||
result = rc.json()
|
||||
assert result['length'] == 289
|
||||
assert len(result['data']) == result['length']
|
||||
assert 'columns' in result
|
||||
assert 'data' in result
|
||||
data = result['data']
|
||||
assert len(data) == 289
|
||||
# analyed DF has 28 columns
|
||||
assert len(result['columns']) == 28
|
||||
assert len(data[0]) == 28
|
||||
date_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'date'][0]
|
||||
rsi_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'rsi'][0]
|
||||
|
||||
assert data[0][date_col_idx] == '2018-01-11 00:00:00'
|
||||
assert data[0][rsi_col_idx] is not None
|
||||
assert data[0][rsi_col_idx] > 0
|
||||
assert lfm.call_count == 1
|
||||
assert rc.json()['pair'] == 'UNITTEST/BTC'
|
||||
assert rc.json()['strategy'] == CURRENT_TEST_STRATEGY
|
||||
assert rc.json()['data_start'] == '2018-01-11 00:00:00+00:00'
|
||||
assert rc.json()['data_start_ts'] == 1515628800000
|
||||
assert rc.json()['data_stop'] == '2018-01-12 00:00:00+00:00'
|
||||
assert rc.json()['data_stop_ts'] == 1515715200000
|
||||
assert result['pair'] == 'UNITTEST/BTC'
|
||||
assert result['strategy'] == CURRENT_TEST_STRATEGY
|
||||
assert result['data_start'] == '2018-01-11 00:00:00+00:00'
|
||||
assert result['data_start_ts'] == 1515628800000
|
||||
assert result['data_stop'] == '2018-01-12 00:00:00+00:00'
|
||||
assert result['data_stop_ts'] == 1515715200000
|
||||
|
||||
# No data found
|
||||
rc = client_get(client,
|
||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
||||
f"&timerange=20200111-20200112&strategy={CURRENT_TEST_STRATEGY}")
|
||||
assert_response(rc, 502)
|
||||
assert rc.json()['error'] == ("Error querying /api/v1/pair_history: "
|
||||
"No data for UNITTEST/BTC, 5m in 20200111-20200112 found.")
|
||||
assert rc.json()['detail'] == ("No data for UNITTEST/BTC, 5m in 20200111-20200112 found.")
|
||||
|
||||
|
||||
def test_api_plot_config(botclient, mocker):
|
||||
@@ -1529,6 +1564,10 @@ def test_api_plot_config(botclient, mocker):
|
||||
assert_response(rc)
|
||||
assert rc.json()['subplots'] == {}
|
||||
|
||||
rc = client_get(client, f"{BASE_URI}/plot_config?strategy=NotAStrategy")
|
||||
assert_response(rc, 502)
|
||||
assert rc.json()['detail'] is not None
|
||||
|
||||
mocker.patch('freqtrade.rpc.api_server.api_v1.get_rpc_optional', return_value=None)
|
||||
|
||||
rc = client_get(client, f"{BASE_URI}/plot_config")
|
||||
@@ -1735,7 +1774,7 @@ def test_api_pairlists_evaluate(botclient, tmpdir, mocker):
|
||||
rc = client_get(client, f"{BASE_URI}/pairlists/evaluate/{job_id}")
|
||||
assert_response(rc)
|
||||
response = rc.json()
|
||||
assert response['result']['whitelist'] == ['ETH/BTC', 'LTC/BTC', 'XRP/BTC', 'NEO/BTC',]
|
||||
assert response['result']['whitelist'] == ['ETH/BTC', 'LTC/BTC', 'XRP/BTC', 'NEO/BTC']
|
||||
assert response['result']['length'] == 4
|
||||
|
||||
# Restart with additional filter, reducing the list to 2
|
||||
@@ -1779,7 +1818,7 @@ def test_list_available_pairs(botclient):
|
||||
rc = client_get(client, f"{BASE_URI}/available_pairs")
|
||||
|
||||
assert_response(rc)
|
||||
assert rc.json()['length'] == 13
|
||||
assert rc.json()['length'] == 12
|
||||
assert isinstance(rc.json()['pairs'], list)
|
||||
|
||||
rc = client_get(client, f"{BASE_URI}/available_pairs?timeframe=5m")
|
||||
@@ -1981,7 +2020,8 @@ def test_api_backtest_history(botclient, mocker, testdatadir):
|
||||
result = rc.json()
|
||||
assert len(result) == 3
|
||||
fn = result[0]['filename']
|
||||
assert fn == "backtest-result_multistrat.json"
|
||||
assert fn == "backtest-result_multistrat"
|
||||
assert result[0]['notes'] == ''
|
||||
strategy = result[0]['strategy']
|
||||
rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}&strategy={strategy}")
|
||||
assert_response(rc)
|
||||
@@ -1995,6 +2035,103 @@ def test_api_backtest_history(botclient, mocker, testdatadir):
|
||||
assert result2['backtest_result']['strategy'][strategy]
|
||||
|
||||
|
||||
def test_api_delete_backtest_history_entry(botclient, tmp_path: Path):
|
||||
ftbot, client = botclient
|
||||
|
||||
# Create a temporary directory and file
|
||||
bt_results_base = tmp_path / "backtest_results"
|
||||
bt_results_base.mkdir()
|
||||
file_path = bt_results_base / "test.json"
|
||||
file_path.touch()
|
||||
meta_path = file_path.with_suffix('.meta.json')
|
||||
meta_path.touch()
|
||||
|
||||
rc = client_delete(client, f"{BASE_URI}/backtest/history/randomFile.json")
|
||||
assert_response(rc, 503)
|
||||
assert rc.json()['detail'] == 'Bot is not in the correct state.'
|
||||
|
||||
ftbot.config['user_data_dir'] = tmp_path
|
||||
ftbot.config['runmode'] = RunMode.WEBSERVER
|
||||
rc = client_delete(client, f"{BASE_URI}/backtest/history/randomFile.json")
|
||||
assert rc.status_code == 404
|
||||
assert rc.json()['detail'] == 'File not found.'
|
||||
|
||||
rc = client_delete(client, f"{BASE_URI}/backtest/history/{file_path.name}")
|
||||
assert rc.status_code == 200
|
||||
|
||||
assert not file_path.exists()
|
||||
assert not meta_path.exists()
|
||||
|
||||
|
||||
def test_api_patch_backtest_history_entry(botclient, tmp_path: Path):
|
||||
ftbot, client = botclient
|
||||
|
||||
# Create a temporary directory and file
|
||||
bt_results_base = tmp_path / "backtest_results"
|
||||
bt_results_base.mkdir()
|
||||
file_path = bt_results_base / "test.json"
|
||||
file_path.touch()
|
||||
meta_path = file_path.with_suffix('.meta.json')
|
||||
with meta_path.open('w') as metafile:
|
||||
rapidjson.dump({
|
||||
CURRENT_TEST_STRATEGY: {
|
||||
"run_id": "6e542efc8d5e62cef6e5be0ffbc29be81a6e751d",
|
||||
"backtest_start_time": 1690176003}
|
||||
}, metafile)
|
||||
|
||||
def read_metadata():
|
||||
with meta_path.open('r') as metafile:
|
||||
return rapidjson.load(metafile)
|
||||
|
||||
rc = client_patch(client, f"{BASE_URI}/backtest/history/randomFile.json")
|
||||
assert_response(rc, 503)
|
||||
|
||||
ftbot.config['user_data_dir'] = tmp_path
|
||||
ftbot.config['runmode'] = RunMode.WEBSERVER
|
||||
|
||||
rc = client_patch(client, f"{BASE_URI}/backtest/history/randomFile.json", {
|
||||
"strategy": CURRENT_TEST_STRATEGY,
|
||||
})
|
||||
assert rc.status_code == 404
|
||||
|
||||
# Nonexisting strategy
|
||||
rc = client_patch(client, f"{BASE_URI}/backtest/history/{file_path.name}", {
|
||||
"strategy": f"{CURRENT_TEST_STRATEGY}xxx",
|
||||
})
|
||||
assert rc.status_code == 400
|
||||
assert rc.json()['detail'] == 'Strategy not in metadata.'
|
||||
|
||||
# no Notes
|
||||
rc = client_patch(client, f"{BASE_URI}/backtest/history/{file_path.name}", {
|
||||
"strategy": CURRENT_TEST_STRATEGY,
|
||||
})
|
||||
assert rc.status_code == 200
|
||||
res = rc.json()
|
||||
assert isinstance(res, list)
|
||||
assert len(res) == 1
|
||||
assert res[0]['strategy'] == CURRENT_TEST_STRATEGY
|
||||
assert res[0]['notes'] == ''
|
||||
|
||||
fileres = read_metadata()
|
||||
assert fileres[CURRENT_TEST_STRATEGY]['run_id'] == res[0]['run_id']
|
||||
assert fileres[CURRENT_TEST_STRATEGY]['notes'] == ''
|
||||
|
||||
rc = client_patch(client, f"{BASE_URI}/backtest/history/{file_path.name}", {
|
||||
"strategy": CURRENT_TEST_STRATEGY,
|
||||
"notes": "FooBar",
|
||||
})
|
||||
assert rc.status_code == 200
|
||||
res = rc.json()
|
||||
assert isinstance(res, list)
|
||||
assert len(res) == 1
|
||||
assert res[0]['strategy'] == CURRENT_TEST_STRATEGY
|
||||
assert res[0]['notes'] == 'FooBar'
|
||||
|
||||
fileres = read_metadata()
|
||||
assert fileres[CURRENT_TEST_STRATEGY]['run_id'] == res[0]['run_id']
|
||||
assert fileres[CURRENT_TEST_STRATEGY]['notes'] == 'FooBar'
|
||||
|
||||
|
||||
def test_health(botclient):
|
||||
ftbot, client = botclient
|
||||
|
||||
|
||||
@@ -799,6 +799,8 @@ async def test_telegram_profit_handle(
|
||||
assert '*Best Performing:* `ETH/USDT: 9.45%`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Max Drawdown:*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Profit factor:*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Winrate:*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Expectancy (Ratio):*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Trading volume:* `126 USDT`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
|
||||
@@ -381,7 +381,7 @@ def test__send_msg(default_conf, mocker, caplog):
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_count == 1
|
||||
assert post.call_args[1] == {'data': msg}
|
||||
assert post.call_args[1] == {'data': msg, 'timeout': 10}
|
||||
assert post.call_args[0] == (default_conf['webhook']['url'], )
|
||||
|
||||
post = MagicMock(side_effect=RequestException)
|
||||
@@ -399,7 +399,7 @@ def test__send_msg_with_json_format(default_conf, mocker, caplog):
|
||||
mocker.patch("freqtrade.rpc.webhook.post", post)
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_args[1] == {'json': msg}
|
||||
assert post.call_args[1] == {'json': msg, 'timeout': 10}
|
||||
|
||||
|
||||
def test__send_msg_with_raw_format(default_conf, mocker, caplog):
|
||||
@@ -411,7 +411,11 @@ def test__send_msg_with_raw_format(default_conf, mocker, caplog):
|
||||
mocker.patch("freqtrade.rpc.webhook.post", post)
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_args[1] == {'data': msg['data'], 'headers': {'Content-Type': 'text/plain'}}
|
||||
assert post.call_args[1] == {
|
||||
'data': msg['data'],
|
||||
'headers': {'Content-Type': 'text/plain'},
|
||||
'timeout': 10
|
||||
}
|
||||
|
||||
|
||||
def test_send_msg_discord(default_conf, mocker):
|
||||
|
||||
@@ -21,10 +21,10 @@ def test_binance_mig_data_conversion(default_conf_usdt, tmpdir, testdatadir):
|
||||
futures_dst = tmpdir / 'futures'
|
||||
futures_dst.mkdir()
|
||||
files = [
|
||||
'-1h-mark.json',
|
||||
'-1h-futures.json',
|
||||
'-8h-funding_rate.json',
|
||||
'-8h-mark.json',
|
||||
'-1h-mark.feather',
|
||||
'-1h-futures.feather',
|
||||
'-8h-funding_rate.feather',
|
||||
'-8h-mark.feather',
|
||||
]
|
||||
|
||||
# Copy files to tmpdir and rename to old naming
|
||||
|
||||
@@ -2793,7 +2793,7 @@ def test_manage_open_orders_entry(
|
||||
|
||||
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
|
||||
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234)
|
||||
# check it does cancel buy orders over the time limit
|
||||
# check it does cancel entry orders over the time limit
|
||||
freqtrade.manage_open_orders()
|
||||
assert cancel_order_mock.call_count == 1
|
||||
assert rpc_mock.call_count == 2
|
||||
@@ -2801,7 +2801,7 @@ def test_manage_open_orders_entry(
|
||||
select(Trade).filter(Trade.open_order_id.is_(open_trade.open_order_id))).all()
|
||||
nb_trades = len(trades)
|
||||
assert nb_trades == 0
|
||||
# Custom user buy-timeout is never called
|
||||
# Custom user entry-timeout is never called
|
||||
assert freqtrade.strategy.check_entry_timeout.call_count == 0
|
||||
# Entry adjustment is never called
|
||||
assert freqtrade.strategy.adjust_entry_price.call_count == 0
|
||||
@@ -5023,7 +5023,7 @@ def test_get_real_amount_in_point(default_conf_usdt, buy_order_fee, fee, mocker,
|
||||
(8.0, 0.1, 8.0, None),
|
||||
(8.0, 0.1, 7.9, 0.1),
|
||||
])
|
||||
def test_apply_fee_conditional(default_conf_usdt, fee, mocker,
|
||||
def test_apply_fee_conditional(default_conf_usdt, fee, mocker, caplog,
|
||||
amount, fee_abs, wallet, amount_exp):
|
||||
walletmock = mocker.patch('freqtrade.wallets.Wallets.update')
|
||||
mocker.patch('freqtrade.wallets.Wallets.get_free', return_value=wallet)
|
||||
@@ -5048,6 +5048,60 @@ def test_apply_fee_conditional(default_conf_usdt, fee, mocker,
|
||||
# Amount is kept as is
|
||||
assert freqtrade.apply_fee_conditional(trade, 'LTC', amount, fee_abs, order) == amount_exp
|
||||
assert walletmock.call_count == 1
|
||||
if fee_abs != 0 and amount_exp is None:
|
||||
assert log_has_re(r"Fee amount.*Eating.*dust\.", caplog)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('amount,fee_abs,wallet,amount_exp', [
|
||||
(8.0, 0.0, 16, None),
|
||||
(8.0, 0.0, 0, None),
|
||||
(8.0, 0.1, 8, 0.1),
|
||||
(8.0, 0.1, 20, None),
|
||||
(8.0, 0.1, 16.0, None),
|
||||
(8.0, 0.1, 7.9, 0.1),
|
||||
(8.0, 0.1, 12, 0.1),
|
||||
(8.0, 0.1, 15.9, 0.1),
|
||||
])
|
||||
def test_apply_fee_conditional_multibuy(default_conf_usdt, fee, mocker, caplog,
|
||||
amount, fee_abs, wallet, amount_exp):
|
||||
walletmock = mocker.patch('freqtrade.wallets.Wallets.update')
|
||||
mocker.patch('freqtrade.wallets.Wallets.get_free', return_value=wallet)
|
||||
trade = Trade(
|
||||
pair='LTC/ETH',
|
||||
amount=amount,
|
||||
exchange='binance',
|
||||
open_rate=0.245441,
|
||||
fee_open=fee.return_value,
|
||||
fee_close=fee.return_value,
|
||||
open_order_id="123456"
|
||||
)
|
||||
# One closed order
|
||||
order = Order(
|
||||
ft_order_side='buy',
|
||||
order_id='10',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
filled=amount,
|
||||
status="closed"
|
||||
)
|
||||
trade.orders.append(order)
|
||||
# Add additional order - this should NOT eat into dust unless the wallet was bigger already.
|
||||
order1 = Order(
|
||||
ft_order_side='buy',
|
||||
order_id='100',
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=True,
|
||||
)
|
||||
trade.orders.append(order1)
|
||||
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
|
||||
walletmock.reset_mock()
|
||||
# The new trade amount will be 2x amount - fee / wallet will have to be adapted to this.
|
||||
assert freqtrade.apply_fee_conditional(trade, 'LTC', amount, fee_abs, order1) == amount_exp
|
||||
assert walletmock.call_count == 1
|
||||
if fee_abs != 0 and amount_exp is None:
|
||||
assert log_has_re(r"Fee amount.*Eating.*dust\.", caplog)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("delta, is_high_delta", [
|
||||
|
||||
@@ -429,6 +429,7 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
|
||||
assert pytest.approx(trade.stop_loss) == 1.99 * (1 - 0.1 / leverage)
|
||||
assert pytest.approx(trade.initial_stop_loss) == 1.96 * (1 - 0.1 / leverage)
|
||||
assert trade.initial_stop_loss_pct == -0.1
|
||||
assert pytest.approx(trade.orders[-1].stake_amount) == trade.stake_amount
|
||||
|
||||
# 2nd order - not filling
|
||||
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=120)
|
||||
@@ -473,13 +474,38 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
|
||||
assert pytest.approx(trade.orders[1].amount) == 30.150753768 * leverage
|
||||
assert pytest.approx(trade.orders[-1].amount) == 61.538461232 * leverage
|
||||
|
||||
# Full exit
|
||||
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=False)
|
||||
freqtrade.strategy.custom_exit = MagicMock(return_value='Exit now')
|
||||
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=2.02)
|
||||
freqtrade.process()
|
||||
trade = Trade.get_trades().first()
|
||||
assert len(trade.orders) == 5
|
||||
assert trade.orders[-1].side == trade.exit_side
|
||||
assert trade.orders[-1].status == 'open'
|
||||
assert trade.orders[-1].price == 2.02
|
||||
assert pytest.approx(trade.amount) == 91.689215 * leverage
|
||||
assert pytest.approx(trade.orders[-1].amount) == 91.689215 * leverage
|
||||
assert freqtrade.strategy.adjust_entry_price.call_count == 0
|
||||
# Process again, should not adjust entry price
|
||||
freqtrade.process()
|
||||
trade = Trade.get_trades().first()
|
||||
assert len(trade.orders) == 5
|
||||
assert trade.orders[-1].status == 'open'
|
||||
assert trade.orders[-1].price == 2.02
|
||||
# Adjust entry price cannot be called - this is an exit order
|
||||
assert freqtrade.strategy.adjust_entry_price.call_count == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('leverage', [1, 2])
|
||||
def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, leverage) -> None:
|
||||
default_conf_usdt['position_adjustment_enable'] = True
|
||||
|
||||
spot = leverage == 1
|
||||
if not spot:
|
||||
default_conf_usdt['trading_mode'] = 'futures'
|
||||
default_conf_usdt['margin_mode'] = 'isolated'
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
freqtrade.trading_mode = TradingMode.FUTURES
|
||||
assert freqtrade.trading_mode == TradingMode.FUTURES if not spot else TradingMode.SPOT
|
||||
mocker.patch.multiple(
|
||||
EXMS,
|
||||
fetch_ticker=ticker_usdt,
|
||||
@@ -487,8 +513,11 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, levera
|
||||
amount_to_precision=lambda s, x, y: y,
|
||||
price_to_precision=lambda s, x, y: y,
|
||||
get_min_pair_stake_amount=MagicMock(return_value=10),
|
||||
get_funding_fees=MagicMock(return_value=0),
|
||||
)
|
||||
mocker.patch(f"{EXMS}.get_max_leverage", return_value=10)
|
||||
starting_amount = freqtrade.wallets.get_total('USDT')
|
||||
assert starting_amount == 1000
|
||||
|
||||
patch_get_signal(freqtrade)
|
||||
freqtrade.strategy.leverage = MagicMock(return_value=leverage)
|
||||
@@ -498,8 +527,14 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, levera
|
||||
trade = Trade.get_trades().first()
|
||||
assert len(trade.orders) == 1
|
||||
assert pytest.approx(trade.stake_amount) == 60
|
||||
assert trade.leverage == leverage
|
||||
assert pytest.approx(trade.amount) == 30.0 * leverage
|
||||
assert trade.open_rate == 2.0
|
||||
assert pytest.approx(freqtrade.wallets.get_free('USDT')) == starting_amount - 60
|
||||
if spot:
|
||||
assert pytest.approx(freqtrade.wallets.get_total('USDT')) == starting_amount - 60
|
||||
else:
|
||||
assert freqtrade.wallets.get_total('USDT') == starting_amount
|
||||
|
||||
# Too small size
|
||||
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-59)
|
||||
@@ -521,6 +556,15 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, levera
|
||||
assert pytest.approx(trade.amount) == 20.099 * leverage
|
||||
assert trade.open_rate == 2.0
|
||||
assert trade.is_open
|
||||
assert trade.realized_profit > 0.098 * leverage
|
||||
expected_profit = starting_amount - 40.1980 + trade.realized_profit
|
||||
assert pytest.approx(freqtrade.wallets.get_free('USDT')) == expected_profit
|
||||
|
||||
if spot:
|
||||
assert pytest.approx(freqtrade.wallets.get_total('USDT')) == expected_profit
|
||||
else:
|
||||
# total won't change in futures mode, only free / used will.
|
||||
assert freqtrade.wallets.get_total('USDT') == starting_amount + trade.realized_profit
|
||||
caplog.clear()
|
||||
|
||||
# Sell more than what we got (we got ~20 coins left)
|
||||
@@ -545,3 +589,10 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, levera
|
||||
assert pytest.approx(trade.stake_amount) == 40.198
|
||||
assert trade.is_open
|
||||
assert log_has_re('Amount to exit is 0.0 due to exchange limits - not exiting.', caplog)
|
||||
expected_profit = starting_amount - 40.1980 + trade.realized_profit
|
||||
assert pytest.approx(freqtrade.wallets.get_free('USDT')) == expected_profit
|
||||
if spot:
|
||||
assert pytest.approx(freqtrade.wallets.get_total('USDT')) == expected_profit
|
||||
else:
|
||||
# total won't change in futures mode, only free / used will.
|
||||
assert freqtrade.wallets.get_total('USDT') == starting_amount + trade.realized_profit
|
||||
|
||||
+19
-1
@@ -8,7 +8,7 @@ import pandas as pd
|
||||
import pytest
|
||||
|
||||
from freqtrade.misc import (dataframe_to_json, decimals_per_coin, deep_merge_dicts, file_dump_json,
|
||||
file_load_json, json_to_dataframe, pair_to_filename,
|
||||
file_load_json, is_file_in_dir, json_to_dataframe, pair_to_filename,
|
||||
parse_db_uri_for_logging, plural, render_template,
|
||||
render_template_with_fallback, round_coin_value, safe_value_fallback,
|
||||
safe_value_fallback2)
|
||||
@@ -64,6 +64,24 @@ def test_file_load_json(mocker, testdatadir) -> None:
|
||||
assert ret
|
||||
|
||||
|
||||
def test_is_file_in_dir(tmp_path):
|
||||
|
||||
# Create a temporary directory and file
|
||||
dir_path = tmp_path / "subdir"
|
||||
dir_path.mkdir()
|
||||
file_path = dir_path / "test.txt"
|
||||
file_path.touch()
|
||||
|
||||
# Test that the function returns True when the file is in the directory
|
||||
assert is_file_in_dir(file_path, dir_path) is True
|
||||
|
||||
# Test that the function returns False when the file is not in the directory
|
||||
assert is_file_in_dir(file_path, tmp_path) is False
|
||||
|
||||
file_path2 = tmp_path / "../../test2.txt"
|
||||
assert is_file_in_dir(file_path2, tmp_path) is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pair,expected_result", [
|
||||
("ETH/BTC", 'ETH_BTC'),
|
||||
("ETH/USDT", 'ETH_USDT'),
|
||||
|
||||
+29
-1
@@ -8,7 +8,8 @@ from sqlalchemy import select
|
||||
from freqtrade.constants import UNLIMITED_STAKE_AMOUNT
|
||||
from freqtrade.exceptions import DependencyException
|
||||
from freqtrade.persistence import Trade
|
||||
from tests.conftest import EXMS, create_mock_trades, get_patched_freqtradebot, patch_wallet
|
||||
from tests.conftest import (EXMS, create_mock_trades, create_mock_trades_usdt,
|
||||
get_patched_freqtradebot, patch_wallet)
|
||||
|
||||
|
||||
def test_sync_wallet_at_boot(mocker, default_conf):
|
||||
@@ -341,6 +342,33 @@ def test_sync_wallet_futures_live(mocker, default_conf):
|
||||
assert 'ETH/USDT:USDT' not in freqtrade.wallets._positions
|
||||
|
||||
|
||||
def test_sync_wallet_dry(mocker, default_conf_usdt, fee):
|
||||
default_conf_usdt['dry_run'] = True
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
assert len(freqtrade.wallets._wallets) == 1
|
||||
assert len(freqtrade.wallets._positions) == 0
|
||||
assert freqtrade.wallets.get_total('USDT') == 1000
|
||||
|
||||
create_mock_trades_usdt(fee, is_short=None)
|
||||
|
||||
freqtrade.wallets.update()
|
||||
|
||||
assert len(freqtrade.wallets._wallets) == 5
|
||||
assert len(freqtrade.wallets._positions) == 0
|
||||
bal = freqtrade.wallets.get_all_balances()
|
||||
assert bal['NEO'].total == 10
|
||||
assert bal['XRP'].total == 10
|
||||
assert bal['LTC'].total == 2
|
||||
assert bal['USDT'].total == 922.74
|
||||
|
||||
assert freqtrade.wallets.get_starting_balance() == default_conf_usdt['dry_run_wallet']
|
||||
total = freqtrade.wallets.get_total('LTC')
|
||||
free = freqtrade.wallets.get_free('LTC')
|
||||
used = freqtrade.wallets.get_used('LTC')
|
||||
assert free != 0
|
||||
assert free + used == total
|
||||
|
||||
|
||||
def test_sync_wallet_futures_dry(mocker, default_conf, fee):
|
||||
default_conf['dry_run'] = True
|
||||
default_conf['trading_mode'] = 'futures'
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,102 +0,0 @@
|
||||
[
|
||||
[1636959600000, 1.21431, 1.2198, 1.20895, 1.20895, null],
|
||||
[1636963200000, 1.20902, 1.21106, 1.19972, 1.20968, null],
|
||||
[1636966800000, 1.20968, 1.21876, 1.20791, 1.20998, null],
|
||||
[1636970400000, 1.20999, 1.21043, 1.20442, 1.20859, null],
|
||||
[1636974000000, 1.20858, 1.20933, 1.20154, 1.20581, null],
|
||||
[1636977600000, 1.20584, 1.20775, 1.20065, 1.20337, null],
|
||||
[1636981200000, 1.20342, 1.2097, 1.19327, 1.19792, null],
|
||||
[1636984800000, 1.19796, 1.1982, 1.18611, 1.19024, null],
|
||||
[1636988400000, 1.19025, 1.19177, 1.18373, 1.18771, null],
|
||||
[1636992000000, 1.18768, 1.19109, 1.18095, 1.1887, null],
|
||||
[1636995600000, 1.18869, 1.18968, 1.18355, 1.18387, null],
|
||||
[1636999200000, 1.18388, 1.18729, 1.17753, 1.18138, null],
|
||||
[1637002800000, 1.18145, 1.18684, 1.17799, 1.18463, null],
|
||||
[1637006400000, 1.18464, 1.18474, 1.17368, 1.17652, null],
|
||||
[1637010000000, 1.17653, 1.18185, 1.16557, 1.17979, null],
|
||||
[1637013600000, 1.17979, 1.18113, 1.16934, 1.18014, null],
|
||||
[1637017200000, 1.18014, 1.18015, 1.16999, 1.17214, null],
|
||||
[1637020800000, 1.17214, 1.17217, 1.12958, 1.14209, null],
|
||||
[1637024400000, 1.14255, 1.14666, 1.10933, 1.14198, null],
|
||||
[1637028000000, 1.14197, 1.14419, 1.12766, 1.12999, null],
|
||||
[1637031600000, 1.12999, 1.13522, 1.11142, 1.12177, null],
|
||||
[1637035200000, 1.12176, 1.13211, 1.10579, 1.1288, null],
|
||||
[1637038800000, 1.12871, 1.13243, 1.12142, 1.12316, null],
|
||||
[1637042400000, 1.12323, 1.1262, 1.11489, 1.12429, null],
|
||||
[1637046000000, 1.12406, 1.12727, 1.11835, 1.1249, null],
|
||||
[1637049600000, 1.12485, 1.13047, 1.1211, 1.12931, null],
|
||||
[1637053200000, 1.12931, 1.13346, 1.10256, 1.10267, null],
|
||||
[1637056800000, 1.10266, 1.10412, 1.04149, 1.0928, null],
|
||||
[1637060400000, 1.09277, 1.09856, 1.08371, 1.09093, null],
|
||||
[1637064000000, 1.09094, 1.09512, 1.079, 1.08003, null],
|
||||
[1637067600000, 1.0802, 1.09914, 1.08016, 1.09515, null],
|
||||
[1637071200000, 1.09518, 1.11627, 1.0937, 1.10985, null],
|
||||
[1637074800000, 1.10985, 1.11353, 1.09618, 1.10071, null],
|
||||
[1637078400000, 1.09989, 1.10852, 1.09763, 1.10461, null],
|
||||
[1637082000000, 1.10459, 1.10837, 1.09662, 1.09847, null],
|
||||
[1637085600000, 1.09858, 1.10506, 1.08687, 1.08716, null],
|
||||
[1637089200000, 1.08677, 1.10096, 1.08151, 1.09271, null],
|
||||
[1637092800000, 1.09245, 1.09269, 1.06592, 1.08025, null],
|
||||
[1637096400000, 1.08026, 1.09732, 1.07953, 1.09527, null],
|
||||
[1637100000000, 1.09527, 1.10506, 1.09524, 1.09933, null],
|
||||
[1637103600000, 1.09933, 1.10205, 1.08761, 1.08785, null],
|
||||
[1637107200000, 1.08763, 1.09518, 1.07646, 1.07999, null],
|
||||
[1637110800000, 1.07997, 1.0978, 1.07651, 1.07936, null],
|
||||
[1637114400000, 1.07932, 1.08758, 1.07352, 1.07603, null],
|
||||
[1637118000000, 1.07604, 1.08542, 1.05931, 1.06764, null],
|
||||
[1637121600000, 1.06788, 1.07848, 1.06045, 1.07608, null],
|
||||
[1637125200000, 1.07613, 1.08797, 1.07293, 1.08377, null],
|
||||
[1637128800000, 1.08379, 1.08567, 1.07428, 1.07942, null],
|
||||
[1637132400000, 1.07958, 1.09472, 1.07356, 1.08713, null],
|
||||
[1637136000000, 1.08714, 1.09149, 1.08018, 1.08021, null],
|
||||
[1637139600000, 1.08021, 1.08021, 1.0668, 1.07032, null],
|
||||
[1637143200000, 1.07042, 1.10563, 1.07034, 1.10255, null],
|
||||
[1637146800000, 1.10284, 1.10954, 1.09767, 1.10685, null],
|
||||
[1637150400000, 1.10669, 1.10848, 1.10157, 1.10537, null],
|
||||
[1637154000000, 1.10537, 1.11263, 1.09554, 1.09585, null],
|
||||
[1637157600000, 1.09569, 1.10051, 1.08402, 1.08431, null],
|
||||
[1637161200000, 1.08444, 1.08942, 1.07569, 1.08489, null],
|
||||
[1637164800000, 1.08498, 1.09581, 1.07939, 1.09485, null],
|
||||
[1637168400000, 1.09443, 1.09793, 1.08778, 1.0944, null],
|
||||
[1637172000000, 1.09445, 1.10227, 1.09376, 1.0992, null],
|
||||
[1637175600000, 1.0992, 1.10189, 1.09216, 1.09474, null],
|
||||
[1637179200000, 1.09476, 1.10198, 1.09045, 1.0993, null],
|
||||
[1637182800000, 1.09934, 1.09959, 1.08755, 1.0948, null],
|
||||
[1637186400000, 1.09483, 1.09519, 1.08532, 1.0923, null],
|
||||
[1637190000000, 1.0923, 1.09876, 1.0874, 1.095, null],
|
||||
[1637193600000, 1.09503, 1.10673, 1.09047, 1.10441, null],
|
||||
[1637197200000, 1.10437, 1.16166, 1.09815, 1.12902, null],
|
||||
[1637200800000, 1.12875, 1.15094, 1.1242, 1.13764, null],
|
||||
[1637204400000, 1.13795, 1.14262, 1.12341, 1.12423, null],
|
||||
[1637208000000, 1.12424, 1.14806, 1.11333, 1.1142, null],
|
||||
[1637211600000, 1.11435, 1.12608, 1.11085, 1.11436, null],
|
||||
[1637215200000, 1.11398, 1.11718, 1.10538, 1.11388, null],
|
||||
[1637218800000, 1.1139, 1.11452, 1.09674, 1.1072, null],
|
||||
[1637222400000, 1.10725, 1.10999, 1.10209, 1.10706, null],
|
||||
[1637226000000, 1.10712, 1.10712, 1.07747, 1.08658, null],
|
||||
[1637229600000, 1.08692, 1.09865, 1.0807, 1.09767, null],
|
||||
[1637233200000, 1.09768, 1.10211, 1.08348, 1.08409, null],
|
||||
[1637236800000, 1.08423, 1.09498, 1.08002, 1.08259, null],
|
||||
[1637240400000, 1.0827, 1.08773, 1.06597, 1.07719, null],
|
||||
[1637244000000, 1.07718, 1.08075, 1.06678, 1.07077, null],
|
||||
[1637247600000, 1.07029, 1.07824, 1.04568, 1.05497, null],
|
||||
[1637251200000, 1.05591, 1.06325, 1.03957, 1.04032, null],
|
||||
[1637254800000, 1.04051, 1.05342, 1.01557, 1.04158, null],
|
||||
[1637258400000, 1.04153, 1.05436, 1.04122, 1.05208, null],
|
||||
[1637262000000, 1.05207, 1.05948, 1.04961, 1.05515, null],
|
||||
[1637265600000, 1.05516, 1.05927, 1.04767, 1.04808, null],
|
||||
[1637269200000, 1.04789, 1.05622, 1.04191, 1.04587, null],
|
||||
[1637272800000, 1.04575, 1.05336, 1.03405, 1.03941, null],
|
||||
[1637276400000, 1.03931, 1.04614, 1.02868, 1.0411, null],
|
||||
[1637280000000, 1.04093, 1.05672, 1.0295, 1.05495, null],
|
||||
[1637283600000, 1.05495, 1.0553, 1.03548, 1.03595, null],
|
||||
[1637287200000, 1.0359, 1.04585, 1.02026, 1.02312, null],
|
||||
[1637290800000, 1.0242, 1.02908, 1.01788, 1.02871, null],
|
||||
[1637294400000, 1.02871, 1.04474, 1.02584, 1.04247, null],
|
||||
[1637298000000, 1.04251, 1.04654, 1.03685, 1.0449, null],
|
||||
[1637301600000, 1.0449, 1.04971, 1.04109, 1.04452, null],
|
||||
[1637305200000, 1.04456, 1.04875, 1.03802, 1.04268, null],
|
||||
[1637308800000, 1.04239, 1.06573, 1.04164, 1.05717, null],
|
||||
[1637312400000, 1.05721, 1.06464, 1.05619, 1.05896, null],
|
||||
[1637316000000, 1.05893, 1.05918, 1.04976, 1.05188, null]
|
||||
]
|
||||
Binary file not shown.
@@ -1,102 +0,0 @@
|
||||
[
|
||||
[ 1637110800000, 1.0801, 1.09758, 1.07654, 1.07925, 3153694.607359 ],
|
||||
[ 1637114400000, 1.07896, 1.0875, 1.07351, 1.07616, 2697616.070908 ],
|
||||
[ 1637118000000, 1.07607, 1.08521, 1.05896, 1.06804, 4014666.826073 ],
|
||||
[ 1637121600000, 1.06848, 1.07846, 1.06067, 1.07629, 3764015.567745 ],
|
||||
[ 1637125200000, 1.07647, 1.08791, 1.07309, 1.0839, 1669038.113726 ],
|
||||
[ 1637128800000, 1.08414, 1.0856, 1.07431, 1.0794, 1921068.874499 ],
|
||||
[ 1637132400000, 1.0798, 1.09499, 1.07363, 1.08721, 2491096.863582 ],
|
||||
[ 1637136000000, 1.08688, 1.09133, 1.08004, 1.08011, 1983486.794272 ],
|
||||
[ 1637139600000, 1.08017, 1.08027, 1.06667, 1.07039, 3429247.985309 ],
|
||||
[ 1637143200000, 1.07054, 1.10699, 1.07038, 1.10284, 4554151.954177 ],
|
||||
[ 1637146800000, 1.10315, 1.10989, 1.09781, 1.1071, 2012983.10465 ],
|
||||
[ 1637150400000, 1.10627, 1.10849, 1.10155, 1.10539, 1117804.08918 ],
|
||||
[ 1637154000000, 1.10545, 1.11299, 1.09574, 1.09604, 2252781.33926 ],
|
||||
[ 1637157600000, 1.09583, 1.10037, 1.08402, 1.08404, 1882359.279342 ],
|
||||
[ 1637161200000, 1.08433, 1.08924, 1.07583, 1.08543, 1826745.82579 ],
|
||||
[ 1637164800000, 1.08571, 1.09622, 1.07946, 1.09496, 1651730.678891 ],
|
||||
[ 1637168400000, 1.09509, 1.0979, 1.0878, 1.0945, 1081210.614598 ],
|
||||
[ 1637172000000, 1.09483, 1.10223, 1.09362, 1.09922, 1065998.492028 ],
|
||||
[ 1637175600000, 1.09916, 1.10201, 1.09226, 1.09459, 924935.492048 ],
|
||||
[ 1637179200000, 1.09458, 1.10196, 1.09051, 1.09916, 1253539.625345 ],
|
||||
[ 1637182800000, 1.09939, 1.09948, 1.08751, 1.09485, 1066269.190094 ],
|
||||
[ 1637186400000, 1.0949, 1.095, 1.08537, 1.09229, 924726.680514 ],
|
||||
[ 1637190000000, 1.0923, 1.09877, 1.08753, 1.09522, 1150213.905599 ],
|
||||
[ 1637193600000, 1.09538, 1.10675, 1.09058, 1.10453, 1489867.578178 ],
|
||||
[ 1637197200000, 1.10446, 1.16313, 1.0978, 1.12907, 10016166.026355 ],
|
||||
[ 1637200800000, 1.1287, 1.15367, 1.12403, 1.1381, 7167920.053752 ],
|
||||
[ 1637204400000, 1.13818, 1.14242, 1.12358, 1.1244, 2665326.190545 ],
|
||||
[ 1637208000000, 1.12432, 1.14864, 1.11061, 1.11447, 9340547.947608 ],
|
||||
[ 1637211600000, 1.114, 1.12618, 1.10911, 1.11412, 11759138.472952 ],
|
||||
[ 1637215200000, 1.11381, 1.11701, 1.10507, 1.1136, 3104670.727264 ],
|
||||
[ 1637218800000, 1.11433, 1.1145, 1.09682, 1.10715, 2522287.830673 ],
|
||||
[ 1637222400000, 1.1073, 1.11, 1.10224, 1.10697, 2021691.204473 ],
|
||||
[ 1637226000000, 1.10622, 1.10707, 1.07727, 1.08674, 3679010.223352 ],
|
||||
[ 1637229600000, 1.08651, 1.09861, 1.08065, 1.09771, 2041421.476307 ],
|
||||
[ 1637233200000, 1.09784, 1.102, 1.08339, 1.08399, 1920597.122813 ],
|
||||
[ 1637236800000, 1.08458, 1.09523, 1.07961, 1.08263, 2403158.337373 ],
|
||||
[ 1637240400000, 1.08309, 1.08959, 1.06094, 1.07703, 4425686.808376 ],
|
||||
[ 1637244000000, 1.07702, 1.08064, 1.063, 1.07049, 3361334.048801 ],
|
||||
[ 1637247600000, 1.07126, 1.07851, 1.04538, 1.0562, 5865602.611111 ],
|
||||
[ 1637251200000, 1.05616, 1.06326, 1.0395, 1.04074, 4206860.947352 ],
|
||||
[ 1637254800000, 1.04023, 1.0533, 1.01478, 1.0417, 5641193.647291 ],
|
||||
[ 1637258400000, 1.04177, 1.05444, 1.04132, 1.05204, 1819341.083656 ],
|
||||
[ 1637262000000, 1.05201, 1.05962, 1.04964, 1.05518, 1567923.362515 ],
|
||||
[ 1637265600000, 1.05579, 1.05924, 1.04772, 1.04773, 1794108.065606 ],
|
||||
[ 1637269200000, 1.0484, 1.05622, 1.04183, 1.04544, 1936537.403899 ],
|
||||
[ 1637272800000, 1.04543, 1.05331, 1.03396, 1.03892, 2839486.418143 ],
|
||||
[ 1637276400000, 1.03969, 1.04592, 1.02886, 1.04086, 3116275.899177 ],
|
||||
[ 1637280000000, 1.0409, 1.05681, 1.02922, 1.05481, 4671209.916896 ],
|
||||
[ 1637283600000, 1.05489, 1.05538, 1.03539, 1.03599, 2566357.247547 ],
|
||||
[ 1637287200000, 1.03596, 1.04606, 1.02038, 1.02428, 3441834.238546 ],
|
||||
[ 1637290800000, 1.02483, 1.0291, 1.01785, 1.0285, 2678602.729339 ],
|
||||
[ 1637294400000, 1.0287, 1.0446, 1.0259, 1.04264, 2303621.340808 ],
|
||||
[ 1637298000000, 1.04313, 1.04676, 1.03662, 1.04499, 2426475.439485 ],
|
||||
[ 1637301600000, 1.0451, 1.04971, 1.041, 1.04448, 2088365.810515 ],
|
||||
[ 1637305200000, 1.04473, 1.04845, 1.03801, 1.04227, 2222396.213472 ],
|
||||
[ 1637308800000, 1.04211, 1.06965, 1.04168, 1.05711, 3267643.936025 ],
|
||||
[ 1637312400000, 1.0569, 1.06578, 1.05626, 1.05844, 1512848.016057 ],
|
||||
[ 1637316000000, 1.05814, 1.05916, 1.04923, 1.05464, 1710694.805693 ],
|
||||
[ 1637319600000, 1.05484, 1.05731, 1.0458, 1.05359, 1587100.45253 ],
|
||||
[ 1637323200000, 1.05382, 1.06063, 1.05156, 1.05227, 1409095.236152 ],
|
||||
[ 1637326800000, 1.05256, 1.06489, 1.04996, 1.06471, 1879315.174541 ],
|
||||
[ 1637330400000, 1.06491, 1.1036, 1.06489, 1.09439, 6212842.71216 ],
|
||||
[ 1637334000000, 1.09441, 1.10252, 1.082, 1.08879, 4833417.181969 ],
|
||||
[ 1637337600000, 1.08866, 1.09485, 1.07538, 1.09045, 2554438.746366 ],
|
||||
[ 1637341200000, 1.09058, 1.09906, 1.08881, 1.09039, 1961024.28963 ],
|
||||
[ 1637344800000, 1.09063, 1.09447, 1.08555, 1.09041, 1427538.639232 ],
|
||||
[ 1637348400000, 1.09066, 1.09521, 1.088, 1.09332, 847724.821691 ],
|
||||
[ 1637352000000, 1.09335, 1.09489, 1.08402, 1.08501, 1035043.133874 ],
|
||||
[ 1637355600000, 1.08474, 1.08694, 1.08, 1.08606, 969952.892274 ],
|
||||
[ 1637359200000, 1.08601, 1.09, 1.08201, 1.08476, 1105782.581808 ],
|
||||
[ 1637362800000, 1.08463, 1.09245, 1.08201, 1.08971, 1334467.438673 ],
|
||||
[ 1637366400000, 1.0897, 1.09925, 1.08634, 1.09049, 2460070.020396 ],
|
||||
[ 1637370000000, 1.0908, 1.10002, 1.09002, 1.09845, 1210028.489394 ],
|
||||
[ 1637373600000, 1.09785, 1.09791, 1.08944, 1.08962, 1261987.295847 ],
|
||||
[ 1637377200000, 1.08951, 1.0919, 1.08429, 1.08548, 1124938.783404 ],
|
||||
[ 1637380800000, 1.08536, 1.09, 1.08424, 1.08783, 1330935.680168 ],
|
||||
[ 1637384400000, 1.0877, 1.08969, 1.08266, 1.08617, 874900.746037 ],
|
||||
[ 1637388000000, 1.08622, 1.09224, 1.0843, 1.0889, 1240184.759178 ],
|
||||
[ 1637391600000, 1.08917, 1.0909, 1.08408, 1.08535, 706148.380072 ],
|
||||
[ 1637395200000, 1.08521, 1.08857, 1.07829, 1.08349, 1713832.050838 ],
|
||||
[ 1637398800000, 1.08343, 1.08841, 1.08272, 1.0855, 696597.06327 ],
|
||||
[ 1637402400000, 1.08553, 1.0898, 1.08353, 1.08695, 1104159.802108 ],
|
||||
[ 1637406000000, 1.08703, 1.09838, 1.08635, 1.09695, 1404001.384389 ],
|
||||
[ 1637409600000, 1.09695, 1.10175, 1.09024, 1.09278, 1219090.620484 ],
|
||||
[ 1637413200000, 1.093, 1.09577, 1.08615, 1.08792, 994797.546591 ],
|
||||
[ 1637416800000, 1.08793, 1.09239, 1.08572, 1.08725, 1251685.429497 ],
|
||||
[ 1637420400000, 1.08721, 1.08767, 1.06029, 1.06556, 3955719.53631 ],
|
||||
[ 1637424000000, 1.06553, 1.07385, 1.06169, 1.07257, 1868359.179534 ],
|
||||
[ 1637427600000, 1.07266, 1.0745, 1.06759, 1.07261, 1015134.469304 ],
|
||||
[ 1637431200000, 1.07255, 1.0974, 1.06819, 1.09369, 4377675.964829 ],
|
||||
[ 1637434800000, 1.09368, 1.09562, 1.08899, 1.09036, 914791.699929 ],
|
||||
[ 1637438400000, 1.09085, 1.09262, 1.08855, 1.09214, 661436.936672 ],
|
||||
[ 1637442000000, 1.0924, 1.09475, 1.08874, 1.09282, 593143.283519 ],
|
||||
[ 1637445600000, 1.09301, 1.09638, 1.09154, 1.09611, 603952.916221 ],
|
||||
[ 1637449200000, 1.09569, 1.09828, 1.09301, 1.09747, 676053.591571 ],
|
||||
[ 1637452800000, 1.09742, 1.09822, 1.09011, 1.0902, 1375704.506469 ],
|
||||
[ 1637456400000, 1.0901, 1.09311, 1.08619, 1.08856, 928706.03929 ],
|
||||
[ 1637460000000, 1.08855, 1.08941, 1.07401, 1.08035, 2669150.388642 ],
|
||||
[ 1637463600000, 1.08016, 1.08341, 1.07448, 1.07672, 1604049.131307 ],
|
||||
[ 1637467200000, 1.07685, 1.08229, 1.07552, 1.0765, 1153357.274076 ]
|
||||
]
|
||||
Binary file not shown.
-102
@@ -1,102 +0,0 @@
|
||||
[
|
||||
[1636956000000, 1.20932, 1.21787, 1.20763, 1.21431, null],
|
||||
[1636959600000, 1.21431, 1.2198, 1.20895, 1.20895, null],
|
||||
[1636963200000, 1.20902, 1.21106, 1.19972, 1.20968, null],
|
||||
[1636966800000, 1.20968, 1.21876, 1.20791, 1.20998, null],
|
||||
[1636970400000, 1.20999, 1.21043, 1.20442, 1.20859, null],
|
||||
[1636974000000, 1.20858, 1.20933, 1.20154, 1.20581, null],
|
||||
[1636977600000, 1.20584, 1.20775, 1.20065, 1.20337, null],
|
||||
[1636981200000, 1.20342, 1.2097, 1.19327, 1.19792, null],
|
||||
[1636984800000, 1.19796, 1.1982, 1.18611, 1.19024, null],
|
||||
[1636988400000, 1.19025, 1.19177, 1.18373, 1.18771, null],
|
||||
[1636992000000, 1.18768, 1.19109, 1.18095, 1.1887, null],
|
||||
[1636995600000, 1.18869, 1.18968, 1.18355, 1.18387, null],
|
||||
[1636999200000, 1.18388, 1.18729, 1.17753, 1.18138, null],
|
||||
[1637002800000, 1.18145, 1.18684, 1.17799, 1.18463, null],
|
||||
[1637006400000, 1.18464, 1.18474, 1.17368, 1.17652, null],
|
||||
[1637010000000, 1.17653, 1.18185, 1.16557, 1.17979, null],
|
||||
[1637013600000, 1.17979, 1.18113, 1.16934, 1.18014, null],
|
||||
[1637017200000, 1.18014, 1.18015, 1.16999, 1.17214, null],
|
||||
[1637020800000, 1.17214, 1.17217, 1.12958, 1.14209, null],
|
||||
[1637024400000, 1.14255, 1.14666, 1.10933, 1.14198, null],
|
||||
[1637028000000, 1.14197, 1.14419, 1.12766, 1.12999, null],
|
||||
[1637031600000, 1.12999, 1.13522, 1.11142, 1.12177, null],
|
||||
[1637035200000, 1.12176, 1.13211, 1.10579, 1.1288, null],
|
||||
[1637038800000, 1.12871, 1.13243, 1.12142, 1.12316, null],
|
||||
[1637042400000, 1.12323, 1.1262, 1.11489, 1.12429, null],
|
||||
[1637046000000, 1.12406, 1.12727, 1.11835, 1.1249, null],
|
||||
[1637049600000, 1.12485, 1.13047, 1.1211, 1.12931, null],
|
||||
[1637053200000, 1.12931, 1.13346, 1.10256, 1.10267, null],
|
||||
[1637056800000, 1.10266, 1.10412, 1.04149, 1.0928, null],
|
||||
[1637060400000, 1.09277, 1.09856, 1.08371, 1.09093, null],
|
||||
[1637064000000, 1.09094, 1.09512, 1.079, 1.08003, null],
|
||||
[1637067600000, 1.0802, 1.09914, 1.08016, 1.09515, null],
|
||||
[1637071200000, 1.09518, 1.11627, 1.0937, 1.10985, null],
|
||||
[1637074800000, 1.10985, 1.11353, 1.09618, 1.10071, null],
|
||||
[1637078400000, 1.09989, 1.10852, 1.09763, 1.10461, null],
|
||||
[1637082000000, 1.10459, 1.10837, 1.09662, 1.09847, null],
|
||||
[1637085600000, 1.09858, 1.10506, 1.08687, 1.08716, null],
|
||||
[1637089200000, 1.08677, 1.10096, 1.08151, 1.09271, null],
|
||||
[1637092800000, 1.09245, 1.09269, 1.06592, 1.08025, null],
|
||||
[1637096400000, 1.08026, 1.09732, 1.07953, 1.09527, null],
|
||||
[1637100000000, 1.09527, 1.10506, 1.09524, 1.09933, null],
|
||||
[1637103600000, 1.09933, 1.10205, 1.08761, 1.08785, null],
|
||||
[1637107200000, 1.08763, 1.09518, 1.07646, 1.07999, null],
|
||||
[1637110800000, 1.07997, 1.0978, 1.07651, 1.07936, null],
|
||||
[1637114400000, 1.07932, 1.08758, 1.07352, 1.07603, null],
|
||||
[1637118000000, 1.07604, 1.08542, 1.05931, 1.06764, null],
|
||||
[1637121600000, 1.06788, 1.07848, 1.06045, 1.07608, null],
|
||||
[1637125200000, 1.07613, 1.08797, 1.07293, 1.08377, null],
|
||||
[1637128800000, 1.08379, 1.08567, 1.07428, 1.07942, null],
|
||||
[1637132400000, 1.07958, 1.09472, 1.07356, 1.08713, null],
|
||||
[1637136000000, 1.08714, 1.09149, 1.08018, 1.08021, null],
|
||||
[1637139600000, 1.08021, 1.08021, 1.0668, 1.07032, null],
|
||||
[1637143200000, 1.07042, 1.10563, 1.07034, 1.10255, null],
|
||||
[1637146800000, 1.10284, 1.10954, 1.09767, 1.10685, null],
|
||||
[1637150400000, 1.10669, 1.10848, 1.10157, 1.10537, null],
|
||||
[1637154000000, 1.10537, 1.11263, 1.09554, 1.09585, null],
|
||||
[1637157600000, 1.09569, 1.10051, 1.08402, 1.08431, null],
|
||||
[1637161200000, 1.08444, 1.08942, 1.07569, 1.08489, null],
|
||||
[1637164800000, 1.08498, 1.09581, 1.07939, 1.09485, null],
|
||||
[1637168400000, 1.09443, 1.09793, 1.08778, 1.0944, null],
|
||||
[1637172000000, 1.09445, 1.10227, 1.09376, 1.0992, null],
|
||||
[1637175600000, 1.0992, 1.10189, 1.09216, 1.09474, null],
|
||||
[1637179200000, 1.09476, 1.10198, 1.09045, 1.0993, null],
|
||||
[1637182800000, 1.09934, 1.09959, 1.08755, 1.0948, null],
|
||||
[1637186400000, 1.09483, 1.09519, 1.08532, 1.0923, null],
|
||||
[1637190000000, 1.0923, 1.09876, 1.0874, 1.095, null],
|
||||
[1637193600000, 1.09503, 1.10673, 1.09047, 1.10441, null],
|
||||
[1637197200000, 1.10437, 1.16166, 1.09815, 1.12902, null],
|
||||
[1637200800000, 1.12875, 1.15094, 1.1242, 1.13764, null],
|
||||
[1637204400000, 1.13795, 1.14262, 1.12341, 1.12423, null],
|
||||
[1637208000000, 1.12424, 1.14806, 1.11333, 1.1142, null],
|
||||
[1637211600000, 1.11435, 1.12608, 1.11085, 1.11436, null],
|
||||
[1637215200000, 1.11398, 1.11718, 1.10538, 1.11388, null],
|
||||
[1637218800000, 1.1139, 1.11452, 1.09674, 1.1072, null],
|
||||
[1637222400000, 1.10725, 1.10999, 1.10209, 1.10706, null],
|
||||
[1637226000000, 1.10712, 1.10712, 1.07747, 1.08658, null],
|
||||
[1637229600000, 1.08692, 1.09865, 1.0807, 1.09767, null],
|
||||
[1637233200000, 1.09768, 1.10211, 1.08348, 1.08409, null],
|
||||
[1637236800000, 1.08423, 1.09498, 1.08002, 1.08259, null],
|
||||
[1637240400000, 1.0827, 1.08773, 1.06597, 1.07719, null],
|
||||
[1637244000000, 1.07718, 1.08075, 1.06678, 1.07077, null],
|
||||
[1637247600000, 1.07029, 1.07824, 1.04568, 1.05497, null],
|
||||
[1637251200000, 1.05591, 1.06325, 1.03957, 1.04032, null],
|
||||
[1637254800000, 1.04051, 1.05342, 1.01557, 1.04158, null],
|
||||
[1637258400000, 1.04153, 1.05436, 1.04122, 1.05208, null],
|
||||
[1637262000000, 1.05207, 1.05948, 1.04961, 1.05515, null],
|
||||
[1637265600000, 1.05516, 1.05927, 1.04767, 1.04808, null],
|
||||
[1637269200000, 1.04789, 1.05622, 1.04191, 1.04587, null],
|
||||
[1637272800000, 1.04575, 1.05336, 1.03405, 1.03941, null],
|
||||
[1637276400000, 1.03931, 1.04614, 1.02868, 1.0411, null],
|
||||
[1637280000000, 1.04093, 1.05672, 1.0295, 1.05495, null],
|
||||
[1637283600000, 1.05495, 1.0553, 1.03548, 1.03595, null],
|
||||
[1637287200000, 1.0359, 1.04585, 1.02026, 1.02312, null],
|
||||
[1637290800000, 1.0242, 1.02908, 1.01788, 1.02871, null],
|
||||
[1637294400000, 1.02871, 1.04474, 1.02584, 1.04247, null],
|
||||
[1637298000000, 1.04251, 1.04654, 1.03685, 1.0449, null],
|
||||
[1637301600000, 1.0449, 1.04971, 1.04109, 1.04452, null],
|
||||
[1637305200000, 1.04456, 1.04875, 1.03802, 1.04268, null],
|
||||
[1637308800000, 1.04239, 1.06573, 1.04164, 1.05717, null],
|
||||
[1637312400000, 1.05721, 1.06464, 1.05619, 1.06051, null]
|
||||
]
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1 +0,0 @@
|
||||
[[1637193600017,0.0001,0.0,0.0,0.0,0.0],[1637222400007,0.0001,0.0,0.0,0.0,0.0],[1637251200011,0.0001,0.0,0.0,0.0,0.0],[1637280000000,0.0001,0.0,0.0,0.0,0.0],[1637308800000,0.0001,0.0,0.0,0.0,0.0],[1637337600005,0.0001,0.0,0.0,0.0,0.0],[1637366400012,0.00013046,0.0,0.0,0.0,0.0],[1637395200000,0.0001,0.0,0.0,0.0,0.0],[1637424000007,0.0001,0.0,0.0,0.0,0.0],[1637452800000,0.00013862,0.0,0.0,0.0,0.0],[1637481600006,0.0001,0.0,0.0,0.0,0.0],[1637510400000,0.00019881,0.0,0.0,0.0,0.0],[1637539200004,0.00013991,0.0,0.0,0.0,0.0],[1637568000000,0.0001,0.0,0.0,0.0,0.0],[1637596800000,0.0001,0.0,0.0,0.0,0.0],[1637625600004,0.0001,0.0,0.0,0.0,0.0],[1637654400010,0.0001,0.0,0.0,0.0,0.0],[1637683200005,0.00017402,0.0,0.0,0.0,0.0],[1637712000001,0.00016775,0.0,0.0,0.0,0.0],[1637740800003,0.00033523,0.0,0.0,0.0,0.0],[1637769600010,0.0001,0.0,0.0,0.0,0.0],[1637798400000,0.00020066,0.0,0.0,0.0,0.0],[1637827200010,0.00034381,0.0,0.0,0.0,0.0],[1637856000000,0.00032096,0.0,0.0,0.0,0.0],[1637884800000,0.00058316,0.0,0.0,0.0,0.0],[1637913600000,0.0001646,0.0,0.0,0.0,0.0],[1637942400016,0.0001,0.0,0.0,0.0,0.0],[1637971200005,0.0001,0.0,0.0,0.0,0.0],[1638000000008,0.0001,0.0,0.0,0.0,0.0],[1638028800007,0.0001,0.0,0.0,0.0,0.0],[1638057600018,0.0001,0.0,0.0,0.0,0.0],[1638086400000,0.0001,0.0,0.0,0.0,0.0],[1638115200004,0.0001,0.0,0.0,0.0,0.0],[1638144000002,0.0001,0.0,0.0,0.0,0.0],[1638172800004,0.0001,0.0,0.0,0.0,0.0],[1638201600000,0.0001,0.0,0.0,0.0,0.0],[1638230400000,0.0001,0.0,0.0,0.0,0.0],[1638259200006,0.0001,0.0,0.0,0.0,0.0],[1638288000000,0.0001,0.0,0.0,0.0,0.0],[1638316800000,0.0001,0.0,0.0,0.0,0.0],[1638345600000,0.0001,0.0,0.0,0.0,0.0],[1638374400001,0.0001,0.0,0.0,0.0,0.0],[1638403200000,0.0001,0.0,0.0,0.0,0.0],[1638432000007,0.0001,0.0,0.0,0.0,0.0],[1638460800008,0.0001,0.0,0.0,0.0,0.0],[1638489600004,0.0001,0.0,0.0,0.0,0.0],[1638518400002,0.0001,0.0,0.0,0.0,0.0],[1638547200006,0.0001,0.0,0.0,0.0,0.0],[1638576000006,0.0001,0.0,0.0,0.0,0.0],[1638604800004,-0.00219334,0.0,0.0,0.0,0.0],[1638633600000,0.0001,0.0,0.0,0.0,0.0],[1638662400003,0.00006147,0.0,0.0,0.0,0.0],[1638691200008,0.0001,0.0,0.0,0.0,0.0],[1638720000007,0.0001,0.0,0.0,0.0,0.0],[1638748800009,0.0001,0.0,0.0,0.0,0.0],[1638777600001,0.0001,0.0,0.0,0.0,0.0],[1638806400000,0.0001,0.0,0.0,0.0,0.0],[1638835200018,0.0001,0.0,0.0,0.0,0.0],[1638864000000,0.0001,0.0,0.0,0.0,0.0],[1638892800000,0.0001,0.0,0.0,0.0,0.0],[1638921600000,0.0001,0.0,0.0,0.0,0.0],[1638950400018,0.0001,0.0,0.0,0.0,0.0],[1638979200010,0.0001,0.0,0.0,0.0,0.0],[1639008000010,0.0001,0.0,0.0,0.0,0.0],[1639036800000,0.0001,0.0,0.0,0.0,0.0],[1639065600000,0.0001,0.0,0.0,0.0,0.0],[1639094400000,0.0001,0.0,0.0,0.0,0.0],[1639123200008,0.0001,0.0,0.0,0.0,0.0],[1639152000012,0.00008995,0.0,0.0,0.0,0.0],[1639180800009,0.0001,0.0,0.0,0.0,0.0],[1639209600008,-0.00002574,0.0,0.0,0.0,0.0],[1639238400000,-0.00002024,0.0,0.0,0.0,0.0],[1639267200001,-0.00008282,0.0,0.0,0.0,0.0],[1639296000015,0.0001,0.0,0.0,0.0,0.0],[1639324800011,0.00008752,0.0,0.0,0.0,0.0],[1639353600006,0.0001,0.0,0.0,0.0,0.0],[1639382400019,0.0001,0.0,0.0,0.0,0.0],[1639411200000,0.0001,0.0,0.0,0.0,0.0],[1639440000004,0.00007825,0.0,0.0,0.0,0.0],[1639468800000,0.00007108,0.0,0.0,0.0,0.0],[1639497600015,0.0001,0.0,0.0,0.0,0.0],[1639526400000,0.0001,0.0,0.0,0.0,0.0],[1639555200008,0.0001,0.0,0.0,0.0,0.0],[1639584000005,0.0001,0.0,0.0,0.0,0.0],[1639612800006,0.0001,0.0,0.0,0.0,0.0],[1639641600009,0.0001,0.0,0.0,0.0,0.0],[1639670400000,0.0001,0.0,0.0,0.0,0.0],[1639699200000,0.0001,0.0,0.0,0.0,0.0],[1639728000005,0.0001,0.0,0.0,0.0,0.0],[1639756800006,0.0001,0.0,0.0,0.0,0.0],[1639785600014,0.0001,0.0,0.0,0.0,0.0]]
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user