Merge branch 'freqtrade:develop' into develop

This commit is contained in:
hippocritical
2023-05-26 08:38:32 +02:00
committed by GitHub
58 changed files with 790 additions and 662 deletions

View File

@@ -1,12 +1,11 @@
import json
import re
from datetime import datetime
from datetime import datetime, timedelta
from io import BytesIO
from pathlib import Path
from unittest.mock import MagicMock, PropertyMock
from zipfile import ZipFile
import arrow
import pytest
from freqtrade.commands import (start_backtesting_show, start_convert_data, start_convert_trades,
@@ -25,6 +24,7 @@ from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException
from freqtrade.persistence.models import init_db
from freqtrade.persistence.pairlock_middleware import PairLocks
from freqtrade.util import dt_floor_day, dt_now, dt_utc
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades, get_args, log_has,
log_has_re, patch_exchange, patched_configuration_load_config_file)
from tests.conftest_trades import MOCK_TRADE_COUNT
@@ -689,7 +689,7 @@ def test_download_data_timerange(mocker, markets):
start_download_data(pargs)
assert dl_mock.call_count == 1
# 20days ago
days_ago = arrow.get(arrow.now().shift(days=-20).date()).int_timestamp
days_ago = dt_floor_day(dt_now() - timedelta(days=20)).timestamp()
assert dl_mock.call_args_list[0][1]['timerange'].startts == days_ago
dl_mock.reset_mock()
@@ -704,8 +704,7 @@ def test_download_data_timerange(mocker, markets):
start_download_data(pargs)
assert dl_mock.call_count == 1
assert dl_mock.call_args_list[0][1]['timerange'].startts == arrow.Arrow(
2020, 1, 1).int_timestamp
assert dl_mock.call_args_list[0][1]['timerange'].startts == int(dt_utc(2020, 1, 1).timestamp())
def test_download_data_no_markets(mocker, caplog):

View File

@@ -8,7 +8,6 @@ from pathlib import Path
from typing import Optional
from unittest.mock import MagicMock, Mock, PropertyMock
import arrow
import numpy as np
import pandas as pd
import pytest
@@ -23,6 +22,8 @@ from freqtrade.exchange.exchange import timeframe_to_minutes
from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import LocalTrade, Order, Trade, init_db
from freqtrade.resolvers import ExchangeResolver
from freqtrade.util import dt_ts
from freqtrade.util.datetime_helpers import dt_now
from freqtrade.worker import Worker
from tests.conftest_trades import (leverage_trade, mock_trade_1, mock_trade_2, mock_trade_3,
mock_trade_4, mock_trade_5, mock_trade_6, short_trade)
@@ -1663,8 +1664,8 @@ def limit_buy_order_open():
'type': 'limit',
'side': 'buy',
'symbol': 'mocked',
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': arrow.utcnow().isoformat(),
'timestamp': dt_ts(),
'datetime': dt_now().isoformat(),
'price': 0.00001099,
'average': 0.00001099,
'amount': 90.99181073,
@@ -1691,8 +1692,8 @@ def limit_buy_order_old():
'type': 'limit',
'side': 'buy',
'symbol': 'mocked',
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'price': 0.00001099,
'amount': 90.99181073,
'filled': 0.0,
@@ -1708,8 +1709,8 @@ def limit_sell_order_old():
'type': 'limit',
'side': 'sell',
'symbol': 'ETH/BTC',
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'price': 0.00001099,
'amount': 90.99181073,
'filled': 0.0,
@@ -1725,8 +1726,8 @@ def limit_buy_order_old_partial():
'type': 'limit',
'side': 'buy',
'symbol': 'ETH/BTC',
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'price': 0.00001099,
'amount': 90.99181073,
'filled': 23.0,
@@ -1756,8 +1757,8 @@ def limit_buy_order_canceled_empty(request):
'info': {},
'id': 'AZNPFF-4AC4N-7MKTAT',
'clientOrderId': None,
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'lastTradeTimestamp': None,
'status': 'canceled',
'symbol': 'LTC/USDT',
@@ -1777,8 +1778,8 @@ def limit_buy_order_canceled_empty(request):
'info': {},
'id': '1234512345',
'clientOrderId': 'alb1234123',
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'lastTradeTimestamp': None,
'symbol': 'LTC/USDT',
'type': 'limit',
@@ -1798,8 +1799,8 @@ def limit_buy_order_canceled_empty(request):
'info': {},
'id': '1234512345',
'clientOrderId': 'alb1234123',
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'lastTradeTimestamp': None,
'symbol': 'LTC/USDT',
'type': 'limit',
@@ -1823,8 +1824,8 @@ def limit_sell_order_open():
'type': 'limit',
'side': 'sell',
'symbol': 'mocked',
'datetime': arrow.utcnow().isoformat(),
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': dt_now().isoformat(),
'timestamp': dt_ts(),
'price': 0.00001173,
'amount': 90.99181073,
'filled': 0.0,
@@ -2486,8 +2487,8 @@ def buy_order_fee():
'type': 'limit',
'side': 'buy',
'symbol': 'mocked',
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'timestamp': dt_ts(dt_now() - timedelta(minutes=601)),
'datetime': (dt_now() - timedelta(minutes=601)).isoformat(),
'price': 0.245441,
'amount': 8.0,
'cost': 1.963528,
@@ -2596,7 +2597,7 @@ def open_trade():
fee_open=0.0,
fee_close=0.0,
stake_amount=1,
open_date=arrow.utcnow().shift(minutes=-601).datetime,
open_date=dt_now() - timedelta(minutes=601),
is_open=True
)
trade.orders = [
@@ -2634,7 +2635,7 @@ def open_trade_usdt():
fee_open=0.0,
fee_close=0.0,
stake_amount=60.0,
open_date=arrow.utcnow().shift(minutes=-601).datetime,
open_date=dt_now() - timedelta(minutes=601),
is_open=True
)
trade.orders = [
@@ -2838,8 +2839,8 @@ def limit_buy_order_usdt_open():
'type': 'limit',
'side': 'buy',
'symbol': 'mocked',
'datetime': arrow.utcnow().isoformat(),
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': dt_now().isoformat(),
'timestamp': dt_ts(),
'price': 2.00,
'average': 2.00,
'amount': 30.0,
@@ -2866,8 +2867,8 @@ def limit_sell_order_usdt_open():
'type': 'limit',
'side': 'sell',
'symbol': 'mocked',
'datetime': arrow.utcnow().isoformat(),
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': dt_now().isoformat(),
'timestamp': dt_ts(),
'price': 2.20,
'amount': 30.0,
'cost': 66.0,
@@ -2893,8 +2894,8 @@ def market_buy_order_usdt():
'type': 'market',
'side': 'buy',
'symbol': 'mocked',
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': arrow.utcnow().isoformat(),
'timestamp': dt_ts(),
'datetime': dt_now().isoformat(),
'price': 2.00,
'amount': 30.0,
'filled': 30.0,
@@ -2950,8 +2951,8 @@ def market_sell_order_usdt():
'type': 'market',
'side': 'sell',
'symbol': 'mocked',
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': arrow.utcnow().isoformat(),
'timestamp': dt_ts(),
'datetime': dt_now().isoformat(),
'price': 2.20,
'amount': 30.0,
'filled': 30.0,

View File

@@ -1,8 +1,8 @@
from datetime import datetime, timedelta, timezone
from pathlib import Path
from unittest.mock import MagicMock
import pytest
from arrow import Arrow
from pandas import DataFrame, DateOffset, Timestamp, to_datetime
from freqtrade.configuration import TimeRange
@@ -18,6 +18,7 @@ from freqtrade.data.metrics import (calculate_cagr, calculate_calmar, calculate_
calculate_underwater, combine_dataframes_with_mean,
create_cum_profit)
from freqtrade.exceptions import OperationalException
from freqtrade.util import dt_utc
from tests.conftest import CURRENT_TEST_STRATEGY, create_mock_trades
from tests.conftest_trades import MOCK_TRADE_COUNT
@@ -162,25 +163,25 @@ def test_extract_trades_of_period(testdatadir):
{'pair': [pair, pair, pair, pair],
'profit_ratio': [0.0, 0.1, -0.2, -0.5],
'profit_abs': [0.0, 1, -2, -5],
'open_date': to_datetime([Arrow(2017, 11, 13, 15, 40, 0).datetime,
Arrow(2017, 11, 14, 9, 41, 0).datetime,
Arrow(2017, 11, 14, 14, 20, 0).datetime,
Arrow(2017, 11, 15, 3, 40, 0).datetime,
'open_date': to_datetime([datetime(2017, 11, 13, 15, 40, 0, tzinfo=timezone.utc),
datetime(2017, 11, 14, 9, 41, 0, tzinfo=timezone.utc),
datetime(2017, 11, 14, 14, 20, 0, tzinfo=timezone.utc),
datetime(2017, 11, 15, 3, 40, 0, tzinfo=timezone.utc),
], utc=True
),
'close_date': to_datetime([Arrow(2017, 11, 13, 16, 40, 0).datetime,
Arrow(2017, 11, 14, 10, 41, 0).datetime,
Arrow(2017, 11, 14, 15, 25, 0).datetime,
Arrow(2017, 11, 15, 3, 55, 0).datetime,
'close_date': to_datetime([datetime(2017, 11, 13, 16, 40, 0, tzinfo=timezone.utc),
datetime(2017, 11, 14, 10, 41, 0, tzinfo=timezone.utc),
datetime(2017, 11, 14, 15, 25, 0, tzinfo=timezone.utc),
datetime(2017, 11, 15, 3, 55, 0, tzinfo=timezone.utc),
], utc=True)
})
trades1 = extract_trades_of_period(data, trades)
# First and last trade are dropped as they are out of range
assert len(trades1) == 2
assert trades1.iloc[0].open_date == Arrow(2017, 11, 14, 9, 41, 0).datetime
assert trades1.iloc[0].close_date == Arrow(2017, 11, 14, 10, 41, 0).datetime
assert trades1.iloc[-1].open_date == Arrow(2017, 11, 14, 14, 20, 0).datetime
assert trades1.iloc[-1].close_date == Arrow(2017, 11, 14, 15, 25, 0).datetime
assert trades1.iloc[0].open_date == datetime(2017, 11, 14, 9, 41, 0, tzinfo=timezone.utc)
assert trades1.iloc[0].close_date == datetime(2017, 11, 14, 10, 41, 0, tzinfo=timezone.utc)
assert trades1.iloc[-1].open_date == datetime(2017, 11, 14, 14, 20, 0, tzinfo=timezone.utc)
assert trades1.iloc[-1].close_date == datetime(2017, 11, 14, 15, 25, 0, tzinfo=timezone.utc)
def test_analyze_trade_parallelism(testdatadir):
@@ -420,7 +421,7 @@ def test_calculate_max_drawdown2():
-0.025782, 0.010400, 0.012374, 0.012467, 0.114741, 0.010303, 0.010088,
-0.033961, 0.010680, 0.010886, -0.029274, 0.011178, 0.010693, 0.010711]
dates = [Arrow(2020, 1, 1).shift(days=i) for i in range(len(values))]
dates = [dt_utc(2020, 1, 1) + timedelta(days=i) for i in range(len(values))]
df = DataFrame(zip(values, dates), columns=['profit', 'open_date'])
# sort by profit and reset index
df = df.sort_values('profit').reset_index(drop=True)
@@ -454,8 +455,8 @@ def test_calculate_max_drawdown_abs(profits, relative, highd, lowd, result, resu
[1000, 500, 1000, 11000, 10000] # absolute results
[1000, 50%, 0%, 0%, ~9%] # Relative drawdowns
"""
init_date = Arrow(2020, 1, 1)
dates = [init_date.shift(days=i) for i in range(len(profits))]
init_date = datetime(2020, 1, 1, tzinfo=timezone.utc)
dates = [init_date + timedelta(days=i) for i in range(len(profits))]
df = DataFrame(zip(profits, dates), columns=['profit_abs', 'open_date'])
# sort by profit and reset index
df = df.sort_values('profit_abs').reset_index(drop=True)
@@ -467,8 +468,8 @@ def test_calculate_max_drawdown_abs(profits, relative, highd, lowd, result, resu
assert isinstance(drawdown, float)
assert isinstance(drawdown_rel, float)
assert hdate == init_date.shift(days=highd)
assert ldate == init_date.shift(days=lowd)
assert hdate == init_date + timedelta(days=highd)
assert ldate == init_date + timedelta(days=lowd)
# High must be before low
assert hdate < ldate

View File

@@ -6,7 +6,6 @@ from pathlib import Path
from shutil import copyfile
from unittest.mock import MagicMock, PropertyMock
import arrow
import pytest
from pandas import DataFrame
from pandas.testing import assert_frame_equal
@@ -26,6 +25,7 @@ from freqtrade.enums import CandleType
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.misc import file_dump_json
from freqtrade.resolvers import StrategyResolver
from freqtrade.util import dt_utc
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_patched_exchange, log_has, log_has_re,
patch_exchange)
@@ -198,7 +198,6 @@ def test_load_cached_data_for_updating(mocker, testdatadir) -> None:
fill_missing=False, drop_incomplete=False)
# now = last cached item + 1 hour
now_ts = test_data[-1][0] / 1000 + 60 * 60
mocker.patch('arrow.utcnow', return_value=arrow.get(now_ts))
# timeframe starts earlier than the cached data
# should fully update data
@@ -353,10 +352,10 @@ def test_download_backtesting_data_exception(mocker, caplog, default_conf, tmpdi
def test_load_partial_missing(testdatadir, caplog) -> None:
# Make sure we start fresh - test missing data at start
start = arrow.get('2018-01-01T00:00:00')
end = arrow.get('2018-01-11T00:00:00')
start = dt_utc(2018, 1, 1)
end = dt_utc(2018, 1, 11)
data = load_data(testdatadir, '5m', ['UNITTEST/BTC'], startup_candles=20,
timerange=TimeRange('date', 'date', start.int_timestamp, end.int_timestamp))
timerange=TimeRange('date', 'date', start.timestamp(), end.timestamp()))
assert log_has(
'Using indicator startup period: 20 ...', caplog
)
@@ -369,16 +368,16 @@ def test_load_partial_missing(testdatadir, caplog) -> None:
caplog)
# Make sure we start fresh - test missing data at end
caplog.clear()
start = arrow.get('2018-01-10T00:00:00')
end = arrow.get('2018-02-20T00:00:00')
start = dt_utc(2018, 1, 10)
end = dt_utc(2018, 2, 20)
data = load_data(datadir=testdatadir, timeframe='5m', pairs=['UNITTEST/BTC'],
timerange=TimeRange('date', 'date', start.int_timestamp, end.int_timestamp))
timerange=TimeRange('date', 'date', start.timestamp(), end.timestamp()))
# timedifference in 5 minutes
td = ((end - start).total_seconds() // 60 // 5) + 1
assert td != len(data['UNITTEST/BTC'])
# Shift endtime with +5
end_real = arrow.get(data['UNITTEST/BTC'].iloc[-1, 0])
end_real = data['UNITTEST/BTC'].iloc[-1, 0].to_pydatetime()
assert log_has(f'UNITTEST/BTC, spot, 5m, '
f'data ends at {end_real.strftime(DATETIME_PRINT_FORMAT)}',
caplog)

View File

@@ -3,9 +3,9 @@
import logging
import math
from datetime import timedelta
from unittest.mock import MagicMock
import arrow
import numpy as np
import pytest
from pandas import DataFrame
@@ -14,6 +14,7 @@ from freqtrade.data.converter import ohlcv_to_dataframe
from freqtrade.edge import Edge, PairInfo
from freqtrade.enums import ExitType
from freqtrade.exceptions import OperationalException
from freqtrade.util.datetime_helpers import dt_ts, dt_utc
from tests.conftest import EXMS, get_patched_freqtradebot, log_has
from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe,
_get_frame_time_from_offset)
@@ -27,7 +28,7 @@ from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe,
# 5) Stoploss and sell are hit. should sell on stoploss
####################################################################
tests_start_time = arrow.get(2018, 10, 3)
tests_start_time = dt_utc(2018, 10, 3)
timeframe_in_minute = 60
# End helper functions
@@ -220,7 +221,7 @@ def test_edge_heartbeat_calculate(mocker, edge_conf):
heartbeat = edge_conf['edge']['process_throttle_secs']
# should not recalculate if heartbeat not reached
edge._last_updated = arrow.utcnow().int_timestamp - heartbeat + 1
edge._last_updated = dt_ts() - heartbeat + 1
assert edge.calculate(edge_conf['exchange']['pair_whitelist']) is False
@@ -232,7 +233,7 @@ def mocked_load_data(datadir, pairs=[], timeframe='0m',
NEOBTC = [
[
tests_start_time.shift(minutes=(x * timeframe_in_minute)).int_timestamp * 1000,
dt_ts(tests_start_time + timedelta(minutes=(x * timeframe_in_minute))),
math.sin(x * hz) / 1000 + base,
math.sin(x * hz) / 1000 + base + 0.0001,
math.sin(x * hz) / 1000 + base - 0.0001,
@@ -244,7 +245,7 @@ def mocked_load_data(datadir, pairs=[], timeframe='0m',
base = 0.002
LTCBTC = [
[
tests_start_time.shift(minutes=(x * timeframe_in_minute)).int_timestamp * 1000,
dt_ts(tests_start_time + timedelta(minutes=(x * timeframe_in_minute))),
math.sin(x * hz) / 1000 + base,
math.sin(x * hz) / 1000 + base + 0.0001,
math.sin(x * hz) / 1000 + base - 0.0001,
@@ -268,7 +269,7 @@ def test_edge_process_downloaded_data(mocker, edge_conf):
assert edge.calculate(edge_conf['exchange']['pair_whitelist'])
assert len(edge._cached_pairs) == 2
assert edge._last_updated <= arrow.utcnow().int_timestamp + 2
assert edge._last_updated <= dt_ts() + 2
def test_edge_process_no_data(mocker, edge_conf, caplog):

View File

@@ -514,7 +514,7 @@ def test_fill_leverage_tiers_binance_dryrun(default_conf, mocker, leverage_tiers
def test_additional_exchange_init_binance(default_conf, mocker):
api_mock = MagicMock()
api_mock.fapiPrivateGetPositionsideDual = MagicMock(return_value={"dualSidePosition": True})
api_mock.fapiPrivateGetPositionSideDual = MagicMock(return_value={"dualSidePosition": True})
api_mock.fapiPrivateGetMultiAssetsMargin = MagicMock(return_value={"multiAssetsMargin": True})
default_conf['dry_run'] = False
default_conf['trading_mode'] = TradingMode.FUTURES
@@ -522,12 +522,12 @@ def test_additional_exchange_init_binance(default_conf, mocker):
with pytest.raises(OperationalException,
match=r"Hedge Mode is not supported.*\nMulti-Asset Mode is not supported.*"):
get_patched_exchange(mocker, default_conf, id="binance", api_mock=api_mock)
api_mock.fapiPrivateGetPositionsideDual = MagicMock(return_value={"dualSidePosition": False})
api_mock.fapiPrivateGetPositionSideDual = MagicMock(return_value={"dualSidePosition": False})
api_mock.fapiPrivateGetMultiAssetsMargin = MagicMock(return_value={"multiAssetsMargin": False})
exchange = get_patched_exchange(mocker, default_conf, id="binance", api_mock=api_mock)
assert exchange
ccxt_exceptionhandlers(mocker, default_conf, api_mock, 'binance',
"additional_exchange_init", "fapiPrivateGetPositionsideDual")
"additional_exchange_init", "fapiPrivateGetPositionSideDual")
def test__set_leverage_binance(mocker, default_conf):

View File

@@ -43,6 +43,10 @@ EXCHANGES = {
'hasQuoteVolumeFutures': True,
'leverage_tiers_public': False,
'leverage_in_spot_market': False,
'private_methods': [
'fapiPrivateGetPositionSideDual',
'fapiPrivateGetMultiAssetsMargin'
],
'sample_order': [{
"symbol": "SOLUSDT",
"orderId": 3551312894,
@@ -221,11 +225,13 @@ EXCHANGES = {
'hasQuoteVolumeFutures': False,
'leverage_tiers_public': True,
'leverage_in_spot_market': True,
'private_methods': ['fetch_accounts'],
},
'bybit': {
'pair': 'BTC/USDT',
'stake_currency': 'USDT',
'hasQuoteVolume': True,
'use_ci_proxy': True,
'timeframe': '1h',
'futures_pair': 'BTC/USDT:USDT',
'futures': True,
@@ -755,3 +761,8 @@ class TestCCXTExchange():
max_stake_amount = futures.get_max_pair_stake_amount(futures_pair, 40000)
assert (isinstance(max_stake_amount, float))
assert max_stake_amount >= 0.0
def test_private_method_presence(self, exchange: EXCHANGE_FIXTURE_TYPE):
exch, exchangename = exchange
for method in EXCHANGES[exchangename].get('private_methods', []):
assert hasattr(exch._api, method)

View File

@@ -5,7 +5,6 @@ from datetime import datetime, timedelta, timezone
from random import randint
from unittest.mock import MagicMock, Mock, PropertyMock, patch
import arrow
import ccxt
import pytest
from ccxt import DECIMAL_PLACES, ROUND, ROUND_UP, TICK_SIZE, TRUNCATE
@@ -23,6 +22,7 @@ from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, API_RETRY_CO
calculate_backoff, remove_exchange_credentials)
from freqtrade.exchange.exchange import amount_to_contract_precision
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
from freqtrade.util import dt_now, dt_ts
from tests.conftest import (EXMS, generate_test_data_raw, get_mock_coro, get_patched_exchange,
log_has, log_has_re, num_log_has_re)
@@ -644,7 +644,7 @@ def test_reload_markets(default_conf, mocker, caplog):
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="binance",
mock_markets=False)
exchange._load_async_markets = MagicMock()
exchange._last_markets_refresh = arrow.utcnow().int_timestamp
exchange._last_markets_refresh = dt_ts()
assert exchange.markets == initial_markets
@@ -655,7 +655,7 @@ def test_reload_markets(default_conf, mocker, caplog):
api_mock.load_markets = MagicMock(return_value=updated_markets)
# more than 10 minutes have passed, reload is executed
exchange._last_markets_refresh = arrow.utcnow().int_timestamp - 15 * 60
exchange._last_markets_refresh = dt_ts(dt_now() - timedelta(minutes=15))
exchange.reload_markets()
assert exchange.markets == updated_markets
assert exchange._load_async_markets.call_count == 1
@@ -2076,7 +2076,7 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name, candle_
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
ohlcv = [
[
arrow.utcnow().int_timestamp * 1000, # unix timestamp ms
dt_ts(), # unix timestamp ms
1, # open
2, # high
3, # low
@@ -2096,7 +2096,7 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name, candle_
ret = exchange.get_historic_ohlcv(
pair,
"5m",
int((arrow.utcnow().int_timestamp - since) * 1000),
dt_ts(dt_now() - timedelta(seconds=since)),
candle_type=candle_type
)
@@ -2114,7 +2114,7 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name, candle_
ret = exchange.get_historic_ohlcv(
pair,
"5m",
int((arrow.utcnow().int_timestamp - since) * 1000),
dt_ts(dt_now() - timedelta(seconds=since)),
candle_type=candle_type
)
assert log_has_re(r"Async code raised an exception: .*", caplog)
@@ -2166,7 +2166,7 @@ async def test__async_get_historic_ohlcv(default_conf, mocker, caplog, exchange_
def test_refresh_latest_ohlcv(mocker, default_conf, caplog, candle_type) -> None:
ohlcv = [
[
(arrow.utcnow().shift(minutes=-5).int_timestamp) * 1000, # unix timestamp ms
dt_ts(dt_now() - timedelta(minutes=5)), # unix timestamp ms
1, # open
2, # high
3, # low
@@ -2174,7 +2174,7 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog, candle_type) -> None
5, # volume (in quote currency)
],
[
arrow.utcnow().int_timestamp * 1000, # unix timestamp ms
dt_ts(), # unix timestamp ms
3, # open
1, # high
4, # low
@@ -2364,7 +2364,7 @@ def test_refresh_latest_ohlcv_cache(mocker, default_conf, candle_type, time_mach
async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_name):
ohlcv = [
[
arrow.utcnow().int_timestamp * 1000, # unix timestamp ms
dt_ts(), # unix timestamp ms
1, # open
2, # high
3, # low
@@ -2401,7 +2401,7 @@ async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_
api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError("Unknown error"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
await exchange._async_get_candle_history(pair, "5m", CandleType.SPOT,
(arrow.utcnow().int_timestamp - 2000) * 1000)
dt_ts(dt_now() - timedelta(seconds=2000)))
exchange.close()
@@ -2410,7 +2410,7 @@ async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_
api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.NotSupported("Not supported"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
await exchange._async_get_candle_history(pair, "5m", CandleType.SPOT,
(arrow.utcnow().int_timestamp - 2000) * 1000)
dt_ts(dt_now() - timedelta(seconds=2000)))
exchange.close()
@@ -2433,7 +2433,7 @@ async def test__async_kucoin_get_candle_history(default_conf, mocker, caplog):
with pytest.raises(DDosProtection, match=r'429 Too Many Requests'):
await exchange._async_get_candle_history(
"ETH/BTC", "5m", CandleType.SPOT,
since_ms=(arrow.utcnow().int_timestamp - 2000) * 1000, count=3)
since_ms=dt_ts(dt_now() - timedelta(seconds=2000)), count=3)
assert num_log_has_re(msg, caplog) == 3
caplog.clear()
@@ -2450,7 +2450,7 @@ async def test__async_kucoin_get_candle_history(default_conf, mocker, caplog):
with pytest.raises(DDosProtection, match=r'429 Too Many Requests'):
await exchange._async_get_candle_history(
"ETH/BTC", "5m", CandleType.SPOT,
(arrow.utcnow().int_timestamp - 2000) * 1000, count=3)
dt_ts(dt_now() - timedelta(seconds=2000)), count=3)
# Expect the "returned exception" message 12 times (4 retries * 3 (loop))
assert num_log_has_re(msg, caplog) == 12
assert num_log_has_re(msg2, caplog) == 9
@@ -2908,14 +2908,14 @@ async def test__async_fetch_trades(default_conf, mocker, caplog, exchange_name,
with pytest.raises(OperationalException, match=r'Could not fetch trade data*'):
api_mock.fetch_trades = MagicMock(side_effect=ccxt.BaseError("Unknown error"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
await exchange._async_fetch_trades(pair, since=(arrow.utcnow().int_timestamp - 2000) * 1000)
await exchange._async_fetch_trades(pair, since=dt_ts(dt_now() - timedelta(seconds=2000)))
exchange.close()
with pytest.raises(OperationalException, match=r'Exchange.* does not support fetching '
r'historical trade data\..*'):
api_mock.fetch_trades = MagicMock(side_effect=ccxt.NotSupported("Not supported"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
await exchange._async_fetch_trades(pair, since=(arrow.utcnow().int_timestamp - 2000) * 1000)
await exchange._async_fetch_trades(pair, since=dt_ts(dt_now() - timedelta(seconds=2000)))
exchange.close()

View File

@@ -1,13 +1,14 @@
from datetime import timedelta
from typing import Dict, List, NamedTuple, Optional
import arrow
from pandas import DataFrame
from freqtrade.enums import ExitType
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.util.datetime_helpers import dt_utc
tests_start_time = arrow.get(2018, 10, 3)
tests_start_time = dt_utc(2018, 10, 3)
tests_timeframe = '1h'
@@ -46,7 +47,7 @@ class BTContainer(NamedTuple):
def _get_frame_time_from_offset(offset):
minutes = offset * timeframe_to_minutes(tests_timeframe)
return tests_start_time.shift(minutes=minutes).datetime
return tests_start_time + timedelta(minutes=minutes)
def _build_backtest_dataframe(data):

View File

@@ -9,7 +9,6 @@ from unittest.mock import MagicMock, PropertyMock
import numpy as np
import pandas as pd
import pytest
from arrow import Arrow
from freqtrade import constants
from freqtrade.commands.optimize_commands import setup_optimize_configuration, start_backtesting
@@ -26,6 +25,7 @@ from freqtrade.optimize.backtest_caching import get_strategy_run_id
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.persistence import LocalTrade, Trade
from freqtrade.resolvers import StrategyResolver
from freqtrade.util.datetime_helpers import dt_utc
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_args, log_has, log_has_re,
patch_exchange, patched_configuration_load_config_file)
@@ -346,7 +346,7 @@ def test_backtest_abort(default_conf, mocker, testdatadir) -> None:
def test_backtesting_start(default_conf, mocker, caplog) -> None:
def get_timerange(input1):
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
return dt_utc(2017, 11, 14, 21, 17), dt_utc(2017, 11, 14, 22, 59)
mocker.patch('freqtrade.data.history.get_timerange', get_timerange)
patch_exchange(mocker)
@@ -385,7 +385,7 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
def test_backtesting_start_no_data(default_conf, mocker, caplog, testdatadir) -> None:
def get_timerange(input1):
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
return dt_utc(2017, 11, 14, 21, 17), dt_utc(2017, 11, 14, 22, 59)
mocker.patch('freqtrade.data.history.history_utils.load_pair_history',
MagicMock(return_value=pd.DataFrame()))
@@ -710,11 +710,11 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
'stake_amount': [0.001, 0.001],
'max_stake_amount': [0.001, 0.001],
'amount': [0.00957442, 0.0097064],
'open_date': pd.to_datetime([Arrow(2018, 1, 29, 18, 40, 0).datetime,
Arrow(2018, 1, 30, 3, 30, 0).datetime], utc=True
'open_date': pd.to_datetime([dt_utc(2018, 1, 29, 18, 40, 0),
dt_utc(2018, 1, 30, 3, 30, 0)], utc=True
),
'close_date': pd.to_datetime([Arrow(2018, 1, 29, 22, 35, 0).datetime,
Arrow(2018, 1, 30, 4, 10, 0).datetime], utc=True),
'close_date': pd.to_datetime([dt_utc(2018, 1, 29, 22, 35, 0),
dt_utc(2018, 1, 30, 4, 10, 0)], utc=True),
'open_rate': [0.104445, 0.10302485],
'close_rate': [0.104969, 0.103541],
'fee_open': [0.0025, 0.0025],

View File

@@ -5,13 +5,13 @@ from unittest.mock import MagicMock
import pandas as pd
import pytest
from arrow import Arrow
from freqtrade.configuration import TimeRange
from freqtrade.data import history
from freqtrade.data.history import get_timerange
from freqtrade.enums import ExitType, TradingMode
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.util.datetime_helpers import dt_utc
from tests.conftest import EXMS, patch_exchange
@@ -52,11 +52,11 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) ->
'stake_amount': [500.0, 100.0],
'max_stake_amount': [500.0, 100],
'amount': [4806.87657523, 970.63960782],
'open_date': pd.to_datetime([Arrow(2018, 1, 29, 18, 40, 0).datetime,
Arrow(2018, 1, 30, 3, 30, 0).datetime], utc=True
'open_date': pd.to_datetime([dt_utc(2018, 1, 29, 18, 40, 0),
dt_utc(2018, 1, 30, 3, 30, 0)], utc=True
),
'close_date': pd.to_datetime([Arrow(2018, 1, 29, 22, 00, 0).datetime,
Arrow(2018, 1, 30, 4, 10, 0).datetime], utc=True),
'close_date': pd.to_datetime([dt_utc(2018, 1, 29, 22, 00, 0),
dt_utc(2018, 1, 30, 4, 10, 0)], utc=True),
'open_rate': [0.10401764894444211, 0.10302485],
'close_rate': [0.10453904066847439, 0.103541],
'fee_open': [0.0025, 0.0025],

View File

@@ -6,7 +6,6 @@ from unittest.mock import ANY, MagicMock, PropertyMock
import pandas as pd
import pytest
from arrow import Arrow
from filelock import Timeout
from skopt.space import Integer
@@ -20,6 +19,7 @@ from freqtrade.optimize.hyperopt_tools import HyperoptTools
from freqtrade.optimize.optimize_reports import generate_strategy_stats
from freqtrade.optimize.space import SKDecimal
from freqtrade.strategy import IntParameter
from freqtrade.util import dt_utc
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_args, get_markets, log_has, log_has_re,
patch_exchange, patched_configuration_load_config_file)
@@ -349,14 +349,14 @@ def test_hyperopt_format_results(hyperopt):
"UNITTEST/BTC", "UNITTEST/BTC"],
"profit_ratio": [0.003312, 0.010801, 0.013803, 0.002780],
"profit_abs": [0.000003, 0.000011, 0.000014, 0.000003],
"open_date": [Arrow(2017, 11, 14, 19, 32, 00).datetime,
Arrow(2017, 11, 14, 21, 36, 00).datetime,
Arrow(2017, 11, 14, 22, 12, 00).datetime,
Arrow(2017, 11, 14, 22, 44, 00).datetime],
"close_date": [Arrow(2017, 11, 14, 21, 35, 00).datetime,
Arrow(2017, 11, 14, 22, 10, 00).datetime,
Arrow(2017, 11, 14, 22, 43, 00).datetime,
Arrow(2017, 11, 14, 22, 58, 00).datetime],
"open_date": [dt_utc(2017, 11, 14, 19, 32, 00),
dt_utc(2017, 11, 14, 21, 36, 00),
dt_utc(2017, 11, 14, 22, 12, 00),
dt_utc(2017, 11, 14, 22, 44, 00)],
"close_date": [dt_utc(2017, 11, 14, 21, 35, 00),
dt_utc(2017, 11, 14, 22, 10, 00),
dt_utc(2017, 11, 14, 22, 43, 00),
dt_utc(2017, 11, 14, 22, 58, 00)],
"open_rate": [0.002543, 0.003003, 0.003089, 0.003214],
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"trade_duration": [123, 34, 31, 14],
@@ -379,8 +379,8 @@ def test_hyperopt_format_results(hyperopt):
'backtest_end_time': 1619718665,
}
results_metrics = generate_strategy_stats(['XRP/BTC'], '', bt_result,
Arrow(2017, 11, 14, 19, 32, 00),
Arrow(2017, 12, 14, 19, 32, 00), market_change=0)
dt_utc(2017, 11, 14, 19, 32, 00),
dt_utc(2017, 12, 14, 19, 32, 00), market_change=0)
results_explanation = HyperoptTools.format_results_explanation_string(results_metrics, 'BTC')
total_profit = results_metrics['profit_total_abs']
@@ -423,14 +423,14 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
"UNITTEST/BTC", "UNITTEST/BTC"],
"profit_ratio": [0.003312, 0.010801, 0.013803, 0.002780],
"profit_abs": [0.000003, 0.000011, 0.000014, 0.000003],
"open_date": [Arrow(2017, 11, 14, 19, 32, 00).datetime,
Arrow(2017, 11, 14, 21, 36, 00).datetime,
Arrow(2017, 11, 14, 22, 12, 00).datetime,
Arrow(2017, 11, 14, 22, 44, 00).datetime],
"close_date": [Arrow(2017, 11, 14, 21, 35, 00).datetime,
Arrow(2017, 11, 14, 22, 10, 00).datetime,
Arrow(2017, 11, 14, 22, 43, 00).datetime,
Arrow(2017, 11, 14, 22, 58, 00).datetime],
"open_date": [dt_utc(2017, 11, 14, 19, 32, 00),
dt_utc(2017, 11, 14, 21, 36, 00),
dt_utc(2017, 11, 14, 22, 12, 00),
dt_utc(2017, 11, 14, 22, 44, 00)],
"close_date": [dt_utc(2017, 11, 14, 21, 35, 00),
dt_utc(2017, 11, 14, 22, 10, 00),
dt_utc(2017, 11, 14, 22, 43, 00),
dt_utc(2017, 11, 14, 22, 58, 00)],
"open_rate": [0.002543, 0.003003, 0.003089, 0.003214],
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"trade_duration": [123, 34, 31, 14],
@@ -453,7 +453,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
mocker.patch('freqtrade.optimize.hyperopt.Backtesting.backtest', return_value=backtest_result)
mocker.patch('freqtrade.optimize.hyperopt.get_timerange',
return_value=(Arrow(2017, 12, 10), Arrow(2017, 12, 13)))
return_value=(dt_utc(2017, 12, 10), dt_utc(2017, 12, 13)))
patch_exchange(mocker)
mocker.patch.object(Path, 'open')
mocker.patch('freqtrade.configuration.config_validation.validate_config_schema')
@@ -513,8 +513,8 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
}
hyperopt = Hyperopt(hyperopt_conf)
hyperopt.min_date = Arrow(2017, 12, 10)
hyperopt.max_date = Arrow(2017, 12, 13)
hyperopt.min_date = dt_utc(2017, 12, 10)
hyperopt.max_date = dt_utc(2017, 12, 13)
hyperopt.init_spaces()
generate_optimizer_value = hyperopt.generate_optimizer(list(optimizer_param.values()))
assert generate_optimizer_value == response_expected

View File

@@ -6,7 +6,6 @@ from shutil import copyfile
import joblib
import pandas as pd
import pytest
from arrow import Arrow
from freqtrade.configuration import TimeRange
from freqtrade.constants import BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN
@@ -25,6 +24,8 @@ from freqtrade.optimize.optimize_reports import (_get_resample_from_period, gene
store_backtest_stats, text_table_bt_results,
text_table_exit_reason, text_table_strategy)
from freqtrade.resolvers.strategy_resolver import StrategyResolver
from freqtrade.util import dt_ts
from freqtrade.util.datetime_helpers import dt_from_ts, dt_utc
from tests.conftest import CURRENT_TEST_STRATEGY
from tests.data.test_history import _clean_test_file
@@ -80,14 +81,14 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
"UNITTEST/BTC", "UNITTEST/BTC"],
"profit_ratio": [0.003312, 0.010801, 0.013803, 0.002780],
"profit_abs": [0.000003, 0.000011, 0.000014, 0.000003],
"open_date": [Arrow(2017, 11, 14, 19, 32, 00).datetime,
Arrow(2017, 11, 14, 21, 36, 00).datetime,
Arrow(2017, 11, 14, 22, 12, 00).datetime,
Arrow(2017, 11, 14, 22, 44, 00).datetime],
"close_date": [Arrow(2017, 11, 14, 21, 35, 00).datetime,
Arrow(2017, 11, 14, 22, 10, 00).datetime,
Arrow(2017, 11, 14, 22, 43, 00).datetime,
Arrow(2017, 11, 14, 22, 58, 00).datetime],
"open_date": [dt_utc(2017, 11, 14, 19, 32, 00),
dt_utc(2017, 11, 14, 21, 36, 00),
dt_utc(2017, 11, 14, 22, 12, 00),
dt_utc(2017, 11, 14, 22, 44, 00)],
"close_date": [dt_utc(2017, 11, 14, 21, 35, 00),
dt_utc(2017, 11, 14, 22, 10, 00),
dt_utc(2017, 11, 14, 22, 43, 00),
dt_utc(2017, 11, 14, 22, 58, 00)],
"open_rate": [0.002543, 0.003003, 0.003089, 0.003214],
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"trade_duration": [123, 34, 31, 14],
@@ -106,14 +107,14 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
'canceled_trade_entries': 0,
'canceled_entry_orders': 0,
'replaced_entry_orders': 0,
'backtest_start_time': Arrow.utcnow().int_timestamp,
'backtest_end_time': Arrow.utcnow().int_timestamp,
'backtest_start_time': dt_ts() // 1000,
'backtest_end_time': dt_ts() // 1000,
'run_id': '123',
}
}
timerange = TimeRange.parse_timerange('1510688220-1510700340')
min_date = Arrow.fromtimestamp(1510688220)
max_date = Arrow.fromtimestamp(1510700340)
min_date = dt_from_ts(1510688220)
max_date = dt_from_ts(1510700340)
btdata = history.load_data(testdatadir, '1m', ['UNITTEST/BTC'], timerange=timerange,
fill_up_missing=True)
@@ -135,14 +136,14 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
{"pair": ["UNITTEST/BTC", "UNITTEST/BTC", "UNITTEST/BTC", "UNITTEST/BTC"],
"profit_ratio": [0.003312, 0.010801, -0.013803, 0.002780],
"profit_abs": [0.000003, 0.000011, -0.000014, 0.000003],
"open_date": [Arrow(2017, 11, 14, 19, 32, 00).datetime,
Arrow(2017, 11, 14, 21, 36, 00).datetime,
Arrow(2017, 11, 14, 22, 12, 00).datetime,
Arrow(2017, 11, 14, 22, 44, 00).datetime],
"close_date": [Arrow(2017, 11, 14, 21, 35, 00).datetime,
Arrow(2017, 11, 14, 22, 10, 00).datetime,
Arrow(2017, 11, 14, 22, 43, 00).datetime,
Arrow(2017, 11, 14, 22, 58, 00).datetime],
"open_date": [dt_utc(2017, 11, 14, 19, 32, 00),
dt_utc(2017, 11, 14, 21, 36, 00),
dt_utc(2017, 11, 14, 22, 12, 00),
dt_utc(2017, 11, 14, 22, 44, 00)],
"close_date": [dt_utc(2017, 11, 14, 21, 35, 00),
dt_utc(2017, 11, 14, 22, 10, 00),
dt_utc(2017, 11, 14, 22, 43, 00),
dt_utc(2017, 11, 14, 22, 58, 00)],
"open_rate": [0.002543, 0.003003, 0.003089, 0.003214],
"close_rate": [0.002546, 0.003014, 0.0032903, 0.003217],
"trade_duration": [123, 34, 31, 14],
@@ -161,8 +162,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
'canceled_trade_entries': 0,
'canceled_entry_orders': 0,
'replaced_entry_orders': 0,
'backtest_start_time': Arrow.utcnow().int_timestamp,
'backtest_end_time': Arrow.utcnow().int_timestamp,
'backtest_start_time': dt_ts() // 1000,
'backtest_end_time': dt_ts() // 1000,
'run_id': '124',
}
}

View File

@@ -2,7 +2,6 @@
from datetime import datetime, timedelta, timezone
from types import FunctionType
import arrow
import pytest
from sqlalchemy import select
@@ -10,6 +9,7 @@ from freqtrade.constants import CUSTOM_TAG_MAX_LENGTH, DATETIME_PRINT_FORMAT
from freqtrade.enums import TradingMode
from freqtrade.exceptions import DependencyException
from freqtrade.persistence import LocalTrade, Order, Trade, init_db
from freqtrade.util import dt_now
from tests.conftest import create_mock_trades, create_mock_trades_with_leverage, log_has, log_has_re
@@ -27,7 +27,7 @@ def test_enter_exit_side(fee, is_short):
open_rate=0.01,
amount=5,
is_open=True,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
@@ -49,7 +49,7 @@ def test_set_stop_loss_liquidation(fee):
open_rate=2.0,
amount=30.0,
is_open=True,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
@@ -329,7 +329,7 @@ def test_borrowed(fee, is_short, lev, borrowed, trading_mode):
open_rate=2.0,
amount=30.0,
is_open=True,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
@@ -428,7 +428,7 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_
open_rate=open_rate,
amount=30.0,
is_open=True,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
@@ -485,7 +485,7 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee,
is_open=True,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
exchange='binance',
trading_mode=margin,
leverage=1.0,
@@ -635,7 +635,7 @@ def test_trade_close(fee):
assert pytest.approx(trade.close_profit) == 0.094513715
assert trade.close_date is not None
new_date = arrow.Arrow(2020, 2, 2, 15, 6, 1).datetime,
new_date = datetime(2020, 2, 2, 15, 6, 1),
assert trade.close_date != new_date
# Close should NOT update close_date if the trade has been closed already
assert trade.is_open is False
@@ -1326,7 +1326,7 @@ def test_to_json(fee):
amount_requested=123.0,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
open_rate=0.123,
exchange='binance',
enter_tag=None,
@@ -1411,8 +1411,8 @@ def test_to_json(fee):
amount_requested=101.0,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
close_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=2),
close_date=dt_now() - timedelta(hours=1),
open_rate=0.123,
close_rate=0.125,
enter_tag='buys_signal_001',
@@ -1496,7 +1496,7 @@ def test_stoploss_reinitialization(default_conf, fee):
pair='ADA/USDT',
stake_amount=30.0,
fee_open=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=30.0,
fee_close=fee.return_value,
exchange='binance',
@@ -1557,7 +1557,7 @@ def test_stoploss_reinitialization_leverage(default_conf, fee):
pair='ADA/USDT',
stake_amount=30.0,
fee_open=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=30.0,
fee_close=fee.return_value,
exchange='binance',
@@ -1619,7 +1619,7 @@ def test_stoploss_reinitialization_short(default_conf, fee):
pair='ADA/USDT',
stake_amount=0.001,
fee_open=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=10,
fee_close=fee.return_value,
exchange='binance',
@@ -1678,7 +1678,7 @@ def test_update_fee(fee):
pair='ADA/USDT',
stake_amount=30.0,
fee_open=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=30.0,
fee_close=fee.return_value,
exchange='binance',
@@ -1717,7 +1717,7 @@ def test_fee_updated(fee):
pair='ADA/USDT',
stake_amount=30.0,
fee_open=fee.return_value,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=30.0,
fee_close=fee.return_value,
exchange='binance',
@@ -2092,7 +2092,7 @@ def test_recalc_trade_from_orders(fee):
trade = Trade(
pair='ADA/USDT',
stake_amount=o1_cost,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=o1_amount,
fee_open=fee.return_value,
fee_close=fee.return_value,
@@ -2167,8 +2167,8 @@ def test_recalc_trade_from_orders(fee):
filled=o2_amount,
remaining=0,
cost=o2_cost,
order_date=arrow.utcnow().shift(hours=-1).datetime,
order_filled_date=arrow.utcnow().shift(hours=-1).datetime,
order_date=dt_now() - timedelta(hours=1),
order_filled_date=dt_now() - timedelta(hours=1),
)
trade.orders.append(order2)
trade.recalc_trade_from_orders()
@@ -2201,8 +2201,8 @@ def test_recalc_trade_from_orders(fee):
filled=o3_amount,
remaining=0,
cost=o3_cost,
order_date=arrow.utcnow().shift(hours=-1).datetime,
order_filled_date=arrow.utcnow().shift(hours=-1).datetime,
order_date=dt_now() - timedelta(hours=1),
order_filled_date=dt_now() - timedelta(hours=1),
)
trade.orders.append(order3)
trade.recalc_trade_from_orders()
@@ -2257,7 +2257,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
trade = Trade(
pair='ADA/USDT',
stake_amount=o1_cost,
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_date=dt_now() - timedelta(hours=2),
amount=o1_amount,
fee_open=fee.return_value,
fee_close=fee.return_value,
@@ -2309,8 +2309,8 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
filled=o1_amount,
remaining=0,
cost=o1_cost,
order_date=arrow.utcnow().shift(hours=-1).datetime,
order_filled_date=arrow.utcnow().shift(hours=-1).datetime,
order_date=dt_now() - timedelta(hours=1),
order_filled_date=dt_now() - timedelta(hours=1),
)
trade.orders.append(order2)
trade.recalc_trade_from_orders()
@@ -2337,8 +2337,8 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
filled=0,
remaining=4,
cost=5,
order_date=arrow.utcnow().shift(hours=-1).datetime,
order_filled_date=arrow.utcnow().shift(hours=-1).datetime,
order_date=dt_now() - timedelta(hours=1),
order_filled_date=dt_now() - timedelta(hours=1),
)
trade.orders.append(order3)
trade.recalc_trade_from_orders()
@@ -2364,8 +2364,8 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
filled=o1_amount,
remaining=0,
cost=o1_cost,
order_date=arrow.utcnow().shift(hours=-1).datetime,
order_filled_date=arrow.utcnow().shift(hours=-1).datetime,
order_date=dt_now() - timedelta(hours=1),
order_filled_date=dt_now() - timedelta(hours=1),
)
trade.orders.append(order4)
trade.recalc_trade_from_orders()
@@ -2592,7 +2592,7 @@ def test_recalc_trade_from_orders_dca(data) -> None:
open_rate=data['orders'][0][0][2],
amount=data['orders'][0][0][1],
is_open=True,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
fee_open=data['fee'],
fee_close=data['fee'],
exchange='binance',
@@ -2622,8 +2622,8 @@ def test_recalc_trade_from_orders_dca(data) -> None:
filled=amount,
remaining=0,
cost=amount * price,
order_date=arrow.utcnow().shift(hours=-10 + idx).datetime,
order_filled_date=arrow.utcnow().shift(hours=-10 + idx).datetime,
order_date=dt_now() - timedelta(hours=10 + idx),
order_filled_date=dt_now() - timedelta(hours=10 + idx),
)
trade.orders.append(order_obj)
trade.recalc_trade_from_orders()

View File

@@ -1,10 +1,10 @@
from datetime import datetime, timedelta, timezone
import arrow
import pytest
from freqtrade.persistence import PairLocks
from freqtrade.persistence.models import PairLock
from freqtrade.util import dt_now
@pytest.mark.parametrize('use_db', (False, True))
@@ -20,20 +20,20 @@ def test_PairLocks(use_db):
pair = 'ETH/BTC'
assert not PairLocks.is_pair_locked(pair)
PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime)
PairLocks.lock_pair(pair, dt_now() + timedelta(minutes=4))
# ETH/BTC locked for 4 minutes (on both sides)
assert PairLocks.is_pair_locked(pair)
assert PairLocks.is_pair_locked(pair, side='long')
assert PairLocks.is_pair_locked(pair, side='short')
pair = 'BNB/BTC'
PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime, side='long')
PairLocks.lock_pair(pair, dt_now() + timedelta(minutes=4), side='long')
assert not PairLocks.is_pair_locked(pair)
assert PairLocks.is_pair_locked(pair, side='long')
assert not PairLocks.is_pair_locked(pair, side='short')
pair = 'BNB/USDT'
PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime, side='short')
PairLocks.lock_pair(pair, dt_now() + timedelta(minutes=4), side='short')
assert not PairLocks.is_pair_locked(pair)
assert not PairLocks.is_pair_locked(pair, side='long')
assert PairLocks.is_pair_locked(pair, side='short')
@@ -44,7 +44,7 @@ def test_PairLocks(use_db):
# Unlocking a pair that's not locked should not raise an error
PairLocks.unlock_pair(pair)
PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime)
PairLocks.lock_pair(pair, dt_now() + timedelta(minutes=4))
assert PairLocks.is_pair_locked(pair)
# Get both locks from above
@@ -113,20 +113,20 @@ def test_PairLocks_getlongestlock(use_db):
pair = 'ETH/BTC'
assert not PairLocks.is_pair_locked(pair)
PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime)
PairLocks.lock_pair(pair, dt_now() + timedelta(minutes=4))
# ETH/BTC locked for 4 minutes
assert PairLocks.is_pair_locked(pair)
lock = PairLocks.get_pair_longest_lock(pair)
assert lock.lock_end_time.replace(tzinfo=timezone.utc) > arrow.utcnow().shift(minutes=3)
assert lock.lock_end_time.replace(tzinfo=timezone.utc) < arrow.utcnow().shift(minutes=14)
assert lock.lock_end_time.replace(tzinfo=timezone.utc) > dt_now() + timedelta(minutes=3)
assert lock.lock_end_time.replace(tzinfo=timezone.utc) < dt_now() + timedelta(minutes=14)
PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=15).datetime)
PairLocks.lock_pair(pair, dt_now() + timedelta(minutes=15))
assert PairLocks.is_pair_locked(pair)
lock = PairLocks.get_pair_longest_lock(pair)
# Must be longer than above
assert lock.lock_end_time.replace(tzinfo=timezone.utc) > arrow.utcnow().shift(minutes=14)
assert lock.lock_end_time.replace(tzinfo=timezone.utc) > dt_now() + timedelta(minutes=14)
PairLocks.reset_locks()
PairLocks.use_db = True
@@ -143,8 +143,8 @@ def test_PairLocks_reason(use_db):
assert PairLocks.use_db == use_db
PairLocks.lock_pair('XRP/USDT', arrow.utcnow().shift(minutes=4).datetime, 'TestLock1')
PairLocks.lock_pair('ETH/USDT', arrow.utcnow().shift(minutes=4).datetime, 'TestLock2')
PairLocks.lock_pair('XRP/USDT', dt_now() + timedelta(minutes=4), 'TestLock1')
PairLocks.lock_pair('ETH/USDT', dt_now() + timedelta(minutes=4), 'TestLock2')
assert PairLocks.is_pair_locked('XRP/USDT')
assert PairLocks.is_pair_locked('ETH/USDT')

View File

@@ -21,11 +21,13 @@ from freqtrade.__init__ import __version__
from freqtrade.enums import CandleType, RunMode, State, TradingMode
from freqtrade.exceptions import DependencyException, ExchangeError, OperationalException
from freqtrade.loggers import setup_logging, setup_logging_pre
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.persistence import PairLocks, Trade
from freqtrade.rpc import RPC
from freqtrade.rpc.api_server import ApiServer
from freqtrade.rpc.api_server.api_auth import create_token, get_user_from_token
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
from freqtrade.rpc.api_server.webserver_bgwork import ApiBG
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades, get_mock_coro,
get_patched_freqtradebot, log_has, log_has_re, patch_get_signal)
@@ -1665,137 +1667,140 @@ def test_sysinfo(botclient):
def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
ftbot, client = botclient
mocker.patch(f'{EXMS}.get_fee', fee)
try:
ftbot, client = botclient
mocker.patch(f'{EXMS}.get_fee', fee)
rc = client_get(client, f"{BASE_URI}/backtest")
# Backtest prevented in default mode
assert_response(rc, 502)
rc = client_get(client, f"{BASE_URI}/backtest")
# Backtest prevented in default mode
assert_response(rc, 502)
ftbot.config['runmode'] = RunMode.WEBSERVER
# Backtesting not started yet
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
ftbot.config['runmode'] = RunMode.WEBSERVER
# Backtesting not started yet
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'not_started'
assert not result['running']
assert result['status_msg'] == 'Backtest not yet executed'
assert result['progress'] == 0
result = rc.json()
assert result['status'] == 'not_started'
assert not result['running']
assert result['status_msg'] == 'Backtest not yet executed'
assert result['progress'] == 0
# Reset backtesting
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'reset'
assert not result['running']
assert result['status_msg'] == 'Backtest reset'
ftbot.config['export'] = 'trades'
ftbot.config['backtest_cache'] = 'day'
ftbot.config['user_data_dir'] = Path(tmpdir)
ftbot.config['exportfilename'] = Path(tmpdir) / "backtest_results"
ftbot.config['exportfilename'].mkdir()
# Reset backtesting
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'reset'
assert not result['running']
assert result['status_msg'] == 'Backtest reset'
ftbot.config['export'] = 'trades'
ftbot.config['backtest_cache'] = 'day'
ftbot.config['user_data_dir'] = Path(tmpdir)
ftbot.config['exportfilename'] = Path(tmpdir) / "backtest_results"
ftbot.config['exportfilename'].mkdir()
# start backtesting
data = {
"strategy": CURRENT_TEST_STRATEGY,
"timeframe": "5m",
"timerange": "20180110-20180111",
"max_open_trades": 3,
"stake_amount": 100,
"dry_run_wallet": 1000,
"enable_protections": False
}
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc)
result = rc.json()
# start backtesting
data = {
"strategy": CURRENT_TEST_STRATEGY,
"timeframe": "5m",
"timerange": "20180110-20180111",
"max_open_trades": 3,
"stake_amount": 100,
"dry_run_wallet": 1000,
"enable_protections": False
}
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc)
result = rc.json()
assert result['status'] == 'running'
assert result['progress'] == 0
assert result['running']
assert result['status_msg'] == 'Backtest started'
assert result['status'] == 'running'
assert result['progress'] == 0
assert result['running']
assert result['status_msg'] == 'Backtest started'
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'ended'
assert not result['running']
assert result['status_msg'] == 'Backtest ended'
assert result['progress'] == 1
assert result['backtest_result']
result = rc.json()
assert result['status'] == 'ended'
assert not result['running']
assert result['status_msg'] == 'Backtest ended'
assert result['progress'] == 1
assert result['backtest_result']
rc = client_get(client, f"{BASE_URI}/backtest/abort")
assert_response(rc)
result = rc.json()
assert result['status'] == 'not_running'
assert not result['running']
assert result['status_msg'] == 'Backtest ended'
rc = client_get(client, f"{BASE_URI}/backtest/abort")
assert_response(rc)
result = rc.json()
assert result['status'] == 'not_running'
assert not result['running']
assert result['status_msg'] == 'Backtest ended'
# Simulate running backtest
ApiServer._bgtask_running = True
rc = client_get(client, f"{BASE_URI}/backtest/abort")
assert_response(rc)
result = rc.json()
assert result['status'] == 'stopping'
assert not result['running']
assert result['status_msg'] == 'Backtest ended'
# Simulate running backtest
ApiBG.bgtask_running = True
rc = client_get(client, f"{BASE_URI}/backtest/abort")
assert_response(rc)
result = rc.json()
assert result['status'] == 'stopping'
assert not result['running']
assert result['status_msg'] == 'Backtest ended'
# Get running backtest...
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'running'
assert result['running']
assert result['step'] == "backtest"
assert result['status_msg'] == "Backtest running"
# Get running backtest...
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'running'
assert result['running']
assert result['step'] == "backtest"
assert result['status_msg'] == "Backtest running"
# Try delete with task still running
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'running'
# Try delete with task still running
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'running'
# Post to backtest that's still running
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc, 502)
result = rc.json()
assert 'Bot Background task already running' in result['error']
# Post to backtest that's still running
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc, 502)
result = rc.json()
assert 'Bot Background task already running' in result['error']
ApiServer._bgtask_running = False
ApiBG.bgtask_running = False
# Rerun backtest (should get previous result)
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc)
result = rc.json()
assert log_has_re('Reusing result of previous backtest.*', caplog)
# Rerun backtest (should get previous result)
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc)
result = rc.json()
assert log_has_re('Reusing result of previous backtest.*', caplog)
data['stake_amount'] = 101
data['stake_amount'] = 101
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy',
side_effect=DependencyException('DeadBeef'))
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert log_has("Backtesting caused an error: DeadBeef", caplog)
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy',
side_effect=DependencyException('DeadBeef'))
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert log_has("Backtesting caused an error: DeadBeef", caplog)
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'error'
assert 'Backtest failed' in result['status_msg']
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'error'
assert 'Backtest failed' in result['status_msg']
# Delete backtesting to avoid leakage since the backtest-object may stick around.
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
# Delete backtesting to avoid leakage since the backtest-object may stick around.
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'reset'
assert not result['running']
assert result['status_msg'] == 'Backtest reset'
result = rc.json()
assert result['status'] == 'reset'
assert not result['running']
assert result['status_msg'] == 'Backtest reset'
# Disallow base64 strategies
data['strategy'] = "xx:cHJpbnQoImhlbGxvIHdvcmxkIik="
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc, 500)
# Disallow base64 strategies
data['strategy'] = "xx:cHJpbnQoImhlbGxvIHdvcmxkIik="
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert_response(rc, 500)
finally:
Backtesting.cleanup()
def test_api_backtest_history(botclient, mocker, testdatadir):

View File

@@ -12,7 +12,6 @@ from random import choice, randint
from string import ascii_uppercase
from unittest.mock import ANY, AsyncMock, MagicMock
import arrow
import pytest
import time_machine
from pandas import DataFrame
@@ -33,6 +32,7 @@ from freqtrade.persistence.models import Order
from freqtrade.rpc import RPC
from freqtrade.rpc.rpc import RPCException
from freqtrade.rpc.telegram import Telegram, authorized_only
from freqtrade.util.datetime_helpers import dt_now
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades,
create_mock_trades_usdt, get_patched_freqtradebot, log_has, log_has_re,
patch_exchange, patch_get_signal, patch_whitelist)
@@ -259,7 +259,7 @@ async def test_telegram_status(default_conf, update, mocker) -> None:
'pair': 'ETH/BTC',
'base_currency': 'ETH',
'quote_currency': 'BTC',
'open_date': arrow.utcnow(),
'open_date': dt_now(),
'close_date': None,
'open_rate': 1.099e-05,
'close_rate': None,
@@ -1518,8 +1518,8 @@ async def test_telegram_lock_handle(default_conf, update, ticker, fee, mocker) -
msg_mock.reset_mock()
PairLocks.lock_pair('ETH/BTC', arrow.utcnow().shift(minutes=4).datetime, 'randreason')
PairLocks.lock_pair('XRP/BTC', arrow.utcnow().shift(minutes=20).datetime, 'deadbeef')
PairLocks.lock_pair('ETH/BTC', dt_now() + timedelta(minutes=4), 'randreason')
PairLocks.lock_pair('XRP/BTC', dt_now() + timedelta(minutes=20), 'deadbeef')
await telegram._locks(update=update, context=MagicMock())
@@ -1898,7 +1898,7 @@ def test_send_msg_enter_notification(default_conf, mocker, caplog, message_type,
'current_rate': 1.099e-05,
'amount': 1333.3333333333335,
'analyzed_candle': {'open': 1.1, 'high': 2.2, 'low': 1.0, 'close': 1.5},
'open_date': arrow.utcnow().shift(hours=-1)
'open_date': dt_now() + timedelta(hours=-1)
}
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
@@ -1959,7 +1959,7 @@ def test_send_msg_protection_notification(default_conf, mocker, time_machine) ->
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
time_machine.move_to("2021-09-01 05:00:00 +00:00")
lock = PairLocks.lock_pair('ETH/BTC', arrow.utcnow().shift(minutes=6).datetime, 'randreason')
lock = PairLocks.lock_pair('ETH/BTC', dt_now() + timedelta(minutes=6), 'randreason')
msg = {
'type': RPCMessageType.PROTECTION_TRIGGER,
}
@@ -1974,7 +1974,7 @@ def test_send_msg_protection_notification(default_conf, mocker, time_machine) ->
msg = {
'type': RPCMessageType.PROTECTION_TRIGGER_GLOBAL,
}
lock = PairLocks.lock_pair('*', arrow.utcnow().shift(minutes=100).datetime, 'randreason')
lock = PairLocks.lock_pair('*', dt_now() + timedelta(minutes=100), 'randreason')
msg.update(lock.to_json())
telegram.send_msg(msg)
assert (msg_mock.call_args[0][0] == "*Protection* triggered due to randreason. "
@@ -2005,7 +2005,7 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en
'fiat_currency': 'USD',
'open_rate': 1.099e-05,
'amount': 1333.3333333333335,
'open_date': arrow.utcnow().shift(hours=-1)
'open_date': dt_now() - timedelta(hours=1)
})
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage != 1.0 else ''
assert msg_mock.call_args[0][0] == (
@@ -2032,7 +2032,7 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en
'fiat_currency': 'USD',
'open_rate': 1.099e-05,
'amount': 1333.3333333333335,
'open_date': arrow.utcnow().shift(hours=-1)
'open_date': dt_now() - timedelta(hours=1)
})
assert msg_mock.call_args[0][0] == (
@@ -2071,8 +2071,8 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'fiat_currency': 'USD',
'enter_tag': 'buy_signal1',
'exit_reason': ExitType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(hours=-1),
'close_date': arrow.utcnow(),
'open_date': dt_now() - timedelta(hours=1),
'close_date': dt_now(),
})
assert msg_mock.call_args[0][0] == (
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
@@ -2107,8 +2107,8 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'fiat_currency': 'USD',
'enter_tag': 'buy_signal1',
'exit_reason': ExitType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
'close_date': arrow.utcnow(),
'open_date': dt_now() - timedelta(days=1, hours=2, minutes=30),
'close_date': dt_now(),
'stake_amount': 0.01,
'sub_trade': True,
})
@@ -2144,8 +2144,8 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'stake_currency': 'ETH',
'enter_tag': 'buy_signal1',
'exit_reason': ExitType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
'close_date': arrow.utcnow(),
'open_date': dt_now() - timedelta(days=1, hours=2, minutes=30),
'close_date': dt_now(),
})
assert msg_mock.call_args[0][0] == (
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
@@ -2226,8 +2226,8 @@ def test_send_msg_sell_fill_notification(default_conf, mocker, direction,
'stake_currency': 'ETH',
'enter_tag': enter_signal,
'exit_reason': ExitType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
'close_date': arrow.utcnow(),
'open_date': dt_now() - timedelta(days=1, hours=2, minutes=30),
'close_date': dt_now(),
})
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else ''
@@ -2317,7 +2317,7 @@ def test_send_msg_buy_notification_no_fiat(
'fiat_currency': None,
'current_rate': 1.099e-05,
'amount': 1333.3333333333335,
'open_date': arrow.utcnow().shift(hours=-1)
'open_date': dt_now() - timedelta(hours=1)
})
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else ''
@@ -2363,8 +2363,8 @@ def test_send_msg_sell_notification_no_fiat(
'fiat_currency': 'USD',
'enter_tag': enter_signal,
'exit_reason': ExitType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(hours=-2, minutes=-35, seconds=-3),
'close_date': arrow.utcnow(),
'open_date': dt_now() - timedelta(hours=2, minutes=35, seconds=3),
'close_date': dt_now(),
})
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else ''

View File

@@ -4,7 +4,6 @@ from datetime import datetime, timedelta, timezone
from pathlib import Path
from unittest.mock import MagicMock
import arrow
import pytest
from pandas import DataFrame
@@ -22,6 +21,7 @@ from freqtrade.strategy.hyper import detect_parameters
from freqtrade.strategy.parameters import (BaseParameter, BooleanParameter, CategoricalParameter,
DecimalParameter, IntParameter, RealParameter)
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
from freqtrade.util import dt_now
from tests.conftest import (CURRENT_TEST_STRATEGY, TRADE_SIDES, create_mock_trades, log_has,
log_has_re)
@@ -34,7 +34,7 @@ _STRATEGY.dp = DataProvider({}, None, None)
def test_returns_latest_signal(ohlcv_history):
ohlcv_history.loc[1, 'date'] = arrow.utcnow()
ohlcv_history.loc[1, 'date'] = dt_now()
# Take a copy to correctly modify the call
mocked_history = ohlcv_history.copy()
mocked_history['enter_long'] = 0
@@ -159,7 +159,7 @@ def test_get_signal_exception_valueerror(mocker, caplog, ohlcv_history):
def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history):
# default_conf defines a 5m interval. we check interval * 2 + 5m
# this is necessary as the last candle is removed (partial candles) by default
ohlcv_history.loc[1, 'date'] = arrow.utcnow().shift(minutes=-16)
ohlcv_history.loc[1, 'date'] = dt_now() - timedelta(minutes=16)
# Take a copy to correctly modify the call
mocked_history = ohlcv_history.copy()
mocked_history['exit_long'] = 0
@@ -180,7 +180,7 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history):
def test_get_signal_no_sell_column(default_conf, mocker, caplog, ohlcv_history):
# default_conf defines a 5m interval. we check interval * 2 + 5m
# this is necessary as the last candle is removed (partial candles) by default
ohlcv_history.loc[1, 'date'] = arrow.utcnow()
ohlcv_history.loc[1, 'date'] = dt_now()
# Take a copy to correctly modify the call
mocked_history = ohlcv_history.copy()
# Intentionally don't set sell column
@@ -224,7 +224,7 @@ def test_ignore_expired_candle(default_conf):
def test_assert_df_raise(mocker, caplog, ohlcv_history):
ohlcv_history.loc[1, 'date'] = arrow.utcnow().shift(minutes=-16)
ohlcv_history.loc[1, 'date'] = dt_now() - timedelta(minutes=16)
# Take a copy to correctly modify the call
mocked_history = ohlcv_history.copy()
mocked_history['sell'] = 0
@@ -323,21 +323,21 @@ def test_min_roi_reached(default_conf, fee) -> None:
pair='ETH/BTC',
stake_amount=0.001,
amount=5,
open_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=1),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
open_rate=1,
)
assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime)
assert strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime)
assert not strategy.min_roi_reached(trade, 0.02, dt_now() - timedelta(minutes=56))
assert strategy.min_roi_reached(trade, 0.12, dt_now() - timedelta(minutes=56))
assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime)
assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-39).datetime)
assert not strategy.min_roi_reached(trade, 0.04, dt_now() - timedelta(minutes=39))
assert strategy.min_roi_reached(trade, 0.06, dt_now() - timedelta(minutes=39))
assert not strategy.min_roi_reached(trade, -0.01, arrow.utcnow().shift(minutes=-1).datetime)
assert strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-1).datetime)
assert not strategy.min_roi_reached(trade, -0.01, dt_now() - timedelta(minutes=1))
assert strategy.min_roi_reached(trade, 0.02, dt_now() - timedelta(minutes=1))
def test_min_roi_reached2(default_conf, fee) -> None:
@@ -361,25 +361,25 @@ def test_min_roi_reached2(default_conf, fee) -> None:
pair='ETH/BTC',
stake_amount=0.001,
amount=5,
open_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=1),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
open_rate=1,
)
assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime)
assert strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime)
assert not strategy.min_roi_reached(trade, 0.02, dt_now() - timedelta(minutes=56))
assert strategy.min_roi_reached(trade, 0.12, dt_now() - timedelta(minutes=56))
assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime)
assert strategy.min_roi_reached(trade, 0.071, arrow.utcnow().shift(minutes=-39).datetime)
assert not strategy.min_roi_reached(trade, 0.04, dt_now() - timedelta(minutes=39))
assert strategy.min_roi_reached(trade, 0.071, dt_now() - timedelta(minutes=39))
assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-26).datetime)
assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-26).datetime)
assert not strategy.min_roi_reached(trade, 0.04, dt_now() - timedelta(minutes=26))
assert strategy.min_roi_reached(trade, 0.06, dt_now() - timedelta(minutes=26))
# Should not trigger with 20% profit since after 55 minutes only 30% is active.
assert not strategy.min_roi_reached(trade, 0.20, arrow.utcnow().shift(minutes=-2).datetime)
assert strategy.min_roi_reached(trade, 0.31, arrow.utcnow().shift(minutes=-2).datetime)
assert not strategy.min_roi_reached(trade, 0.20, dt_now() - timedelta(minutes=2))
assert strategy.min_roi_reached(trade, 0.31, dt_now() - timedelta(minutes=2))
def test_min_roi_reached3(default_conf, fee) -> None:
@@ -395,25 +395,25 @@ def test_min_roi_reached3(default_conf, fee) -> None:
pair='ETH/BTC',
stake_amount=0.001,
amount=5,
open_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=1),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
open_rate=1,
)
assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime)
assert not strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime)
assert not strategy.min_roi_reached(trade, 0.02, dt_now() - timedelta(minutes=56))
assert not strategy.min_roi_reached(trade, 0.12, dt_now() - timedelta(minutes=56))
assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime)
assert strategy.min_roi_reached(trade, 0.071, arrow.utcnow().shift(minutes=-39).datetime)
assert not strategy.min_roi_reached(trade, 0.04, dt_now() - timedelta(minutes=39))
assert strategy.min_roi_reached(trade, 0.071, dt_now() - timedelta(minutes=39))
assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-26).datetime)
assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-26).datetime)
assert not strategy.min_roi_reached(trade, 0.04, dt_now() - timedelta(minutes=26))
assert strategy.min_roi_reached(trade, 0.06, dt_now() - timedelta(minutes=26))
# Should not trigger with 20% profit since after 55 minutes only 30% is active.
assert not strategy.min_roi_reached(trade, 0.20, arrow.utcnow().shift(minutes=-2).datetime)
assert strategy.min_roi_reached(trade, 0.31, arrow.utcnow().shift(minutes=-2).datetime)
assert not strategy.min_roi_reached(trade, 0.20, dt_now() - timedelta(minutes=2))
assert strategy.min_roi_reached(trade, 0.31, dt_now() - timedelta(minutes=2))
@pytest.mark.parametrize(
@@ -449,7 +449,7 @@ def test_ft_stoploss_reached(default_conf, fee, profit, adjusted, expected, liq,
pair='ETH/BTC',
stake_amount=0.01,
amount=1,
open_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=1),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
@@ -464,7 +464,7 @@ def test_ft_stoploss_reached(default_conf, fee, profit, adjusted, expected, liq,
if custom_stop:
strategy.custom_stoploss = custom_stop
now = arrow.utcnow().datetime
now = dt_now()
current_rate = trade.open_rate * (1 + profit)
sl_flag = strategy.ft_stoploss_reached(current_rate=current_rate, trade=trade,
current_time=now, current_profit=profit,
@@ -498,14 +498,14 @@ def test_custom_exit(default_conf, fee, caplog) -> None:
pair='ETH/BTC',
stake_amount=0.01,
amount=1,
open_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=1),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
open_rate=1,
)
now = arrow.utcnow().datetime
now = dt_now()
res = strategy.should_exit(trade, 1, now,
enter=False, exit_=False,
low=None, high=None)
@@ -547,13 +547,13 @@ def test_should_sell(default_conf, fee) -> None:
pair='ETH/BTC',
stake_amount=0.01,
amount=1,
open_date=arrow.utcnow().shift(hours=-1).datetime,
open_date=dt_now() - timedelta(hours=1),
fee_open=fee.return_value,
fee_close=fee.return_value,
exchange='binance',
open_rate=1,
)
now = arrow.utcnow().datetime
now = dt_now()
res = strategy.should_exit(trade, 1, now,
enter=False, exit_=False,
low=None, high=None)
@@ -728,7 +728,7 @@ def test_is_pair_locked(default_conf):
pair = 'ETH/BTC'
assert not strategy.is_pair_locked(pair)
strategy.lock_pair(pair, arrow.now(timezone.utc).shift(minutes=4).datetime)
strategy.lock_pair(pair, dt_now() + timedelta(minutes=4))
# ETH/BTC locked for 4 minutes
assert strategy.is_pair_locked(pair)
@@ -746,7 +746,7 @@ def test_is_pair_locked(default_conf):
# Lock with reason
reason = "TestLockR"
strategy.lock_pair(pair, arrow.now(timezone.utc).shift(minutes=4).datetime, reason)
strategy.lock_pair(pair, dt_now() + timedelta(minutes=4), reason)
assert strategy.is_pair_locked(pair)
strategy.unlock_reason(reason)
assert not strategy.is_pair_locked(pair)

View File

@@ -4,10 +4,10 @@
import logging
import time
from copy import deepcopy
from datetime import timedelta
from typing import List
from unittest.mock import ANY, MagicMock, PropertyMock, patch
import arrow
import pytest
from pandas import DataFrame
from sqlalchemy import select
@@ -22,6 +22,7 @@ from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Order, PairLocks, Trade
from freqtrade.persistence.models import PairLock
from freqtrade.plugins.protections.iprotection import ProtectionReturn
from freqtrade.util.datetime_helpers import dt_now, dt_utc
from freqtrade.worker import Worker
from tests.conftest import (EXMS, create_mock_trades, create_mock_trades_usdt,
get_patched_freqtradebot, get_patched_worker, log_has, log_has_re,
@@ -473,7 +474,7 @@ def test_enter_positions_global_pairlock(default_conf_usdt, ticker_usdt, limit_b
assert not log_has_re(message, caplog)
caplog.clear()
PairLocks.lock_pair('*', arrow.utcnow().shift(minutes=20).datetime, 'Just because', side='*')
PairLocks.lock_pair('*', dt_now() + timedelta(minutes=20), 'Just because', side='*')
n = freqtrade.enter_positions()
assert n == 0
assert log_has_re(message, caplog)
@@ -494,7 +495,7 @@ def test_handle_protections(mocker, default_conf_usdt, fee, is_short):
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
freqtrade.protections._protection_handlers[1].global_stop = MagicMock(
return_value=ProtectionReturn(True, arrow.utcnow().shift(hours=1).datetime, "asdf"))
return_value=ProtectionReturn(True, dt_now() + timedelta(hours=1), "asdf"))
create_mock_trades(fee, is_short)
freqtrade.handle_protections('ETC/BTC', '*')
send_msg_mock = freqtrade.rpc.send_msg
@@ -1290,7 +1291,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
}])
trade.stoploss_order_id = "107"
trade.is_open = True
trade.stoploss_last_update = arrow.utcnow().shift(hours=-1).datetime
trade.stoploss_last_update = dt_now() - timedelta(hours=1)
trade.stop_loss = 24
trade.exit_reason = None
trade.orders.append(
@@ -1439,7 +1440,7 @@ def test_handle_stoploss_on_exchange_partial_cancel_here(
})
mocker.patch(f'{EXMS}.fetch_stoploss_order', stoploss_order_hit)
mocker.patch(f'{EXMS}.cancel_stoploss_order_with_result', stoploss_order_cancel)
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-10).datetime
trade.stoploss_last_update = dt_now() - timedelta(minutes=10)
assert freqtrade.handle_stoploss_on_exchange(trade) is False
# Canceled Stoploss filled partially ...
@@ -1659,7 +1660,7 @@ def test_handle_stoploss_on_exchange_trailing(
trade.is_open = True
trade.open_order_id = None
trade.stoploss_order_id = '100'
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-20).datetime
trade.stoploss_last_update = dt_now() - timedelta(minutes=20)
trade.orders.append(
Order(
ft_order_side='stoploss',
@@ -1790,7 +1791,7 @@ def test_handle_stoploss_on_exchange_trailing_error(
trade.open_order_id = None
trade.stoploss_order_id = "abcd"
trade.stop_loss = 0.2
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-601).datetime.replace(tzinfo=None)
trade.stoploss_last_update = (dt_now() - timedelta(minutes=601)).replace(tzinfo=None)
trade.is_short = is_short
stoploss_order_hanging = {
@@ -1814,7 +1815,7 @@ def test_handle_stoploss_on_exchange_trailing_error(
assert stoploss.call_count == 1
# Fail creating stoploss order
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-601).datetime
trade.stoploss_last_update = dt_now() - timedelta(minutes=601)
caplog.clear()
cancel_mock = mocker.patch(f'{EXMS}.cancel_stoploss_order')
mocker.patch(f'{EXMS}.create_stoploss', side_effect=ExchangeError())
@@ -1903,7 +1904,7 @@ def test_handle_stoploss_on_exchange_custom_stop(
trade.is_open = True
trade.open_order_id = None
trade.stoploss_order_id = '100'
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-601).datetime
trade.stoploss_last_update = dt_now() - timedelta(minutes=601)
trade.orders.append(
Order(
ft_order_side='stoploss',
@@ -2041,7 +2042,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, limit_orde
trade.is_open = True
trade.open_order_id = None
trade.stoploss_order_id = '100'
trade.stoploss_last_update = arrow.utcnow().datetime
trade.stoploss_last_update = dt_now()
trade.orders.append(
Order(
ft_order_side='stoploss',
@@ -2151,7 +2152,7 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog
fee_open=0.001,
fee_close=0.001,
open_rate=0.01,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
stake_amount=0.01,
amount=11,
exchange="binance",
@@ -2197,7 +2198,7 @@ def test_exit_positions_exception(mocker, default_conf_usdt, limit_order, caplog
fee_open=0.001,
fee_close=0.001,
open_rate=0.01,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
stake_amount=0.01,
amount=11,
exchange="binance",
@@ -2246,7 +2247,7 @@ def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, ca
fee_open=0.001,
fee_close=0.001,
open_rate=0.01,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
amount=11,
exchange="binance",
is_short=is_short,
@@ -2319,7 +2320,7 @@ def test_update_trade_state_withorderdict(
amount=amount,
exchange='binance',
open_rate=2.0,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
fee_open=fee.return_value,
fee_close=fee.return_value,
open_order_id=order_id,
@@ -2406,7 +2407,7 @@ def test_update_trade_state_sell(
open_rate=0.245441,
fee_open=0.0025,
fee_close=0.0025,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
open_order_id=open_order['id'],
is_open=True,
interest_rate=0.0005,
@@ -2992,8 +2993,8 @@ def test_manage_open_orders_exit_usercustom(
)
freqtrade = FreqtradeBot(default_conf_usdt)
open_trade_usdt.open_date = arrow.utcnow().shift(hours=-5).datetime
open_trade_usdt.close_date = arrow.utcnow().shift(minutes=-601).datetime
open_trade_usdt.open_date = dt_now() - timedelta(hours=5)
open_trade_usdt.close_date = dt_now() - timedelta(minutes=601)
open_trade_usdt.close_profit_abs = 0.001
Trade.session.add(open_trade_usdt)
@@ -3074,8 +3075,8 @@ def test_manage_open_orders_exit(
)
freqtrade = FreqtradeBot(default_conf_usdt)
open_trade_usdt.open_date = arrow.utcnow().shift(hours=-5).datetime
open_trade_usdt.close_date = arrow.utcnow().shift(minutes=-601).datetime
open_trade_usdt.open_date = dt_now() - timedelta(hours=5)
open_trade_usdt.close_date = dt_now() - timedelta(minutes=601)
open_trade_usdt.close_profit_abs = 0.001
open_trade_usdt.is_short = is_short
@@ -3115,8 +3116,8 @@ def test_check_handle_cancelled_exit(
)
freqtrade = FreqtradeBot(default_conf_usdt)
open_trade_usdt.open_date = arrow.utcnow().shift(hours=-5).datetime
open_trade_usdt.close_date = arrow.utcnow().shift(minutes=-601).datetime
open_trade_usdt.open_date = dt_now() - timedelta(hours=5)
open_trade_usdt.close_date = dt_now() - timedelta(minutes=601)
open_trade_usdt.is_short = is_short
Trade.session.add(open_trade_usdt)
@@ -3444,11 +3445,11 @@ def test_handle_cancel_exit_limit(mocker, default_conf_usdt, fee) -> None:
exchange='binance',
open_rate=0.245441,
open_order_id="sell_123456",
open_date=arrow.utcnow().shift(days=-2).datetime,
open_date=dt_now() - timedelta(days=2),
fee_open=fee.return_value,
fee_close=fee.return_value,
close_rate=0.555,
close_date=arrow.utcnow().datetime,
close_date=dt_now(),
exit_reason="sell_reason_whatever",
stake_amount=0.245441 * 2,
)
@@ -5465,7 +5466,7 @@ def test_reupdate_enter_order_fees(mocker, default_conf_usdt, fee, caplog, is_sh
stake_amount=60.0,
fee_open=fee.return_value,
fee_close=fee.return_value,
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
is_open=True,
amount=30,
open_rate=2.0,
@@ -5601,7 +5602,7 @@ def test_handle_onexchange_order(mocker, default_conf_usdt, limit_order, is_shor
fee_open=0.001,
fee_close=0.001,
open_rate=entry_order['price'],
open_date=arrow.utcnow().datetime,
open_date=dt_now(),
stake_amount=entry_order['cost'],
amount=entry_order['amount'],
exchange="binance",
@@ -5739,9 +5740,9 @@ def test_update_funding_fees(
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
date_midnight = arrow.get('2021-09-01 00:00:00').datetime
date_eight = arrow.get('2021-09-01 08:00:00').datetime
date_sixteen = arrow.get('2021-09-01 16:00:00').datetime
date_midnight = dt_utc(2021, 9, 1)
date_eight = dt_utc(2021, 9, 1, 8)
date_sixteen = dt_utc(2021, 9, 1, 16)
columns = ['date', 'open', 'high', 'low', 'close', 'volume']
# 16:00 entry is actually never used
# But should be kept in the test to ensure we're filtering correctly.
@@ -6030,7 +6031,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
'ft_is_open': False,
'id': '651',
'order_id': '651',
'datetime': arrow.utcnow().isoformat(),
'datetime': dt_now().isoformat(),
}
mocker.patch(f'{EXMS}.create_order', MagicMock(return_value=closed_dca_order_1))

View File

@@ -12,7 +12,7 @@ from freqtrade.misc import (dataframe_to_json, decimals_per_coin, deep_merge_dic
file_load_json, format_ms_time, 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, shorten_date)
safe_value_fallback2)
def test_decimals_per_coin():
@@ -39,12 +39,6 @@ def test_round_coin_value():
assert round_coin_value(222.2, 'USDT', False, True) == '222.200'
def test_shorten_date() -> None:
str_data = '1 day, 2 hours, 3 minutes, 4 seconds ago'
str_shorten_data = '1 d, 2 h, 3 min, 4 sec ago'
assert shorten_date(str_data) == str_shorten_data
def test_file_dump_json(mocker) -> None:
file_open = mocker.patch('freqtrade.misc.Path.open', MagicMock())
json_dump = mocker.patch('rapidjson.dump', MagicMock())

View File

@@ -1,7 +1,6 @@
# pragma pylint: disable=missing-docstring, C0103
from datetime import datetime, timezone
import arrow
import pytest
from freqtrade.configuration import TimeRange
@@ -69,7 +68,7 @@ def test_subtract_start():
def test_adjust_start_if_necessary():
min_date = arrow.Arrow(2017, 11, 14, 21, 15, 00)
min_date = datetime(2017, 11, 14, 21, 15, 00, tzinfo=timezone.utc)
x = TimeRange('date', 'date', 1510694100, 1510780500)
# Adjust by 20 candles - min_date == startts

View File

@@ -45,7 +45,7 @@ def test_sync_wallet_at_boot(mocker, default_conf):
assert freqtrade.wallets._wallets['GAS'].total == 0.260739
assert freqtrade.wallets.get_free('BNT') == 1.0
assert 'USDT' in freqtrade.wallets._wallets
assert freqtrade.wallets._last_wallet_refresh > 0
assert freqtrade.wallets._last_wallet_refresh is not None
mocker.patch.multiple(
EXMS,
get_balances=MagicMock(return_value={
@@ -332,7 +332,7 @@ def test_sync_wallet_futures_live(mocker, default_conf):
assert 'USDT' in freqtrade.wallets._wallets
assert 'ETH/USDT:USDT' in freqtrade.wallets._positions
assert freqtrade.wallets._last_wallet_refresh > 0
assert freqtrade.wallets._last_wallet_refresh is not None
# Remove ETH/USDT:USDT position
del mock_result[0]

View File

@@ -0,0 +1,59 @@
from datetime import datetime, timedelta, timezone
import pytest
import time_machine
from freqtrade.util import dt_floor_day, dt_from_ts, dt_now, dt_ts, dt_utc, shorten_date
from freqtrade.util.datetime_helpers import dt_humanize
def test_dt_now():
with time_machine.travel("2021-09-01 05:01:00 +00:00", tick=False) as t:
now = datetime.now(timezone.utc)
assert dt_now() == now
assert dt_ts() == int(now.timestamp() * 1000)
assert dt_ts(now) == int(now.timestamp() * 1000)
t.shift(timedelta(hours=5))
assert dt_now() >= now
assert dt_now() == datetime.now(timezone.utc)
assert dt_ts() == int(dt_now().timestamp() * 1000)
# Test with different time than now
assert dt_ts(now) == int(now.timestamp() * 1000)
def test_dt_utc():
assert dt_utc(2023, 5, 5) == datetime(2023, 5, 5, tzinfo=timezone.utc)
assert dt_utc(2023, 5, 5, 0, 0, 0, 555500) == datetime(2023, 5, 5, 0, 0, 0, 555500,
tzinfo=timezone.utc)
@pytest.mark.parametrize('as_ms', [True, False])
def test_dt_from_ts(as_ms):
multi = 1000 if as_ms else 1
assert dt_from_ts(1683244800.0 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
assert dt_from_ts(1683244800.5555 * multi) == datetime(2023, 5, 5, 0, 0, 0, 555500,
tzinfo=timezone.utc)
# As int
assert dt_from_ts(1683244800 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
# As milliseconds
assert dt_from_ts(1683244800 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
assert dt_from_ts(1683242400 * multi) == datetime(2023, 5, 4, 23, 20, tzinfo=timezone.utc)
def test_dt_floor_day():
now = datetime(2023, 9, 1, 5, 2, 3, 455555, tzinfo=timezone.utc)
assert dt_floor_day(now) == datetime(2023, 9, 1, tzinfo=timezone.utc)
def test_shorten_date() -> None:
str_data = '1 day, 2 hours, 3 minutes, 4 seconds ago'
str_shorten_data = '1 d, 2 h, 3 min, 4 sec ago'
assert shorten_date(str_data) == str_shorten_data
def test_dt_humanize() -> None:
assert dt_humanize(dt_now()) == 'just now'
assert dt_humanize(dt_now(), only_distance=True) == 'instantly'
assert dt_humanize(dt_now() - timedelta(hours=16), only_distance=True) == '16 hours'