Merge pull request #8661 from freqtrade/feat/datetimehelpers

Add datetime helpers, reduce arrow usage to a minimum
This commit is contained in:
Matthias
2023-05-22 18:22:29 +02:00
committed by GitHub
39 changed files with 501 additions and 390 deletions
+30 -29
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))