Add explicit test for get_sell_trade_entry
This commit is contained in:
parent
3406b889b6
commit
fa4ec9f83e
@ -376,7 +376,7 @@ class Backtesting:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_sell_trade_entry(self, trade: LocalTrade, sell_row: Tuple) -> Optional[LocalTrade]:
|
def _get_sell_trade_entry(self, trade: LocalTrade, sell_row: Tuple) -> Optional[LocalTrade]:
|
||||||
if self.timeframe_detail:
|
if self.timeframe_detail and trade.pair in self.detail_data:
|
||||||
sell_candle_time = sell_row[DATE_IDX].to_pydatetime()
|
sell_candle_time = sell_row[DATE_IDX].to_pydatetime()
|
||||||
sell_candle_end = sell_candle_time + timedelta(minutes=self.timeframe_min)
|
sell_candle_end = sell_candle_time + timedelta(minutes=self.timeframe_min)
|
||||||
|
|
||||||
@ -385,6 +385,9 @@ class Backtesting:
|
|||||||
(detail_data['date'] >= sell_candle_time) &
|
(detail_data['date'] >= sell_candle_time) &
|
||||||
(detail_data['date'] < sell_candle_end)
|
(detail_data['date'] < sell_candle_end)
|
||||||
]
|
]
|
||||||
|
if len(detail_data) == 0:
|
||||||
|
# Fall back to "regular" data if no detail data was found for this candle
|
||||||
|
return self._get_sell_trade_entry_for_candle(trade, sell_row)
|
||||||
detail_data['buy'] = sell_row[BUY_IDX]
|
detail_data['buy'] = sell_row[BUY_IDX]
|
||||||
detail_data['sell'] = sell_row[SELL_IDX]
|
detail_data['sell'] = sell_row[SELL_IDX]
|
||||||
headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high']
|
headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high']
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument
|
# pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument
|
||||||
|
|
||||||
import random
|
import random
|
||||||
from datetime import timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import MagicMock, PropertyMock
|
from unittest.mock import MagicMock, PropertyMock
|
||||||
|
|
||||||
@ -500,7 +500,7 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
|
|||||||
pair = 'UNITTEST/BTC'
|
pair = 'UNITTEST/BTC'
|
||||||
row = [
|
row = [
|
||||||
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=0),
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=0),
|
||||||
1, # Sell
|
1, # Buy
|
||||||
0.001, # Open
|
0.001, # Open
|
||||||
0.0011, # Close
|
0.0011, # Close
|
||||||
0, # Sell
|
0, # Sell
|
||||||
@ -548,6 +548,88 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
|
|||||||
backtesting.cleanup()
|
backtesting.cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None:
|
||||||
|
default_conf['use_sell_signal'] = False
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||||
|
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||||
|
patch_exchange(mocker)
|
||||||
|
default_conf['timeframe_detail'] = '1m'
|
||||||
|
default_conf['max_open_trades'] = 2
|
||||||
|
backtesting = Backtesting(default_conf)
|
||||||
|
backtesting._set_strategy(backtesting.strategylist[0])
|
||||||
|
pair = 'UNITTEST/BTC'
|
||||||
|
row = [
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=4, minute=55, tzinfo=timezone.utc),
|
||||||
|
1, # Buy
|
||||||
|
200, # Open
|
||||||
|
201, # Close
|
||||||
|
0, # Sell
|
||||||
|
195, # Low
|
||||||
|
201.5, # High
|
||||||
|
'', # Buy Signal Name
|
||||||
|
]
|
||||||
|
|
||||||
|
trade = backtesting._enter_trade(pair, row=row)
|
||||||
|
assert isinstance(trade, LocalTrade)
|
||||||
|
|
||||||
|
row_sell = [
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=0, tzinfo=timezone.utc),
|
||||||
|
0, # Buy
|
||||||
|
200, # Open
|
||||||
|
201, # Close
|
||||||
|
0, # Sell
|
||||||
|
195, # Low
|
||||||
|
210.5, # High
|
||||||
|
'', # Buy Signal Name
|
||||||
|
]
|
||||||
|
row_detail = pd.DataFrame(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=0, tzinfo=timezone.utc),
|
||||||
|
1, 200, 199, 0, 197, 200.1, '',
|
||||||
|
], [
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=1, tzinfo=timezone.utc),
|
||||||
|
0, 199, 199.5, 0, 199, 199.7, '',
|
||||||
|
], [
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=2, tzinfo=timezone.utc),
|
||||||
|
0, 199.5, 200.5, 0, 199, 200.8, '',
|
||||||
|
], [
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=3, tzinfo=timezone.utc),
|
||||||
|
0, 200.5, 210.5, 0, 193, 210.5, '', # ROI sell (?)
|
||||||
|
], [
|
||||||
|
pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=4, tzinfo=timezone.utc),
|
||||||
|
0, 200, 199, 0, 193, 200.1, '',
|
||||||
|
],
|
||||||
|
], columns=["date", "buy", "open", "close", "sell", "low", "high", "buy_tag"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# No data available.
|
||||||
|
res = backtesting._get_sell_trade_entry(trade, row_sell)
|
||||||
|
assert res is not None
|
||||||
|
assert res.sell_reason == SellType.ROI.value
|
||||||
|
assert res.close_date_utc == datetime(2020, 1, 1, 5, 0, tzinfo=timezone.utc)
|
||||||
|
|
||||||
|
# Enter new trade
|
||||||
|
trade = backtesting._enter_trade(pair, row=row)
|
||||||
|
assert isinstance(trade, LocalTrade)
|
||||||
|
# Assign empty ... no result.
|
||||||
|
backtesting.detail_data[pair] = pd.DataFrame(
|
||||||
|
[], columns=["date", "buy", "open", "close", "sell", "low", "high", "buy_tag"])
|
||||||
|
|
||||||
|
res = backtesting._get_sell_trade_entry(trade, row)
|
||||||
|
assert res is None
|
||||||
|
|
||||||
|
# Assign backtest-detail data
|
||||||
|
backtesting.detail_data[pair] = row_detail
|
||||||
|
|
||||||
|
res = backtesting._get_sell_trade_entry(trade, row_sell)
|
||||||
|
assert res is not None
|
||||||
|
assert res.sell_reason == SellType.ROI.value
|
||||||
|
# Sell at minute 3 (not available above!)
|
||||||
|
assert res.close_date_utc == datetime(2020, 1, 1, 5, 3, tzinfo=timezone.utc)
|
||||||
|
assert round(res.close_rate, 3) == round(209.0225, 3)
|
||||||
|
|
||||||
|
|
||||||
def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||||
default_conf['use_sell_signal'] = False
|
default_conf['use_sell_signal'] = False
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||||
@ -1127,7 +1209,7 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker,
|
|||||||
'--timeframe-detail', '1m',
|
'--timeframe-detail', '1m',
|
||||||
'--strategy-list',
|
'--strategy-list',
|
||||||
'DefaultStrategy'
|
'DefaultStrategy'
|
||||||
]
|
]
|
||||||
args = get_args(args)
|
args = get_args(args)
|
||||||
start_backtesting(args)
|
start_backtesting(args)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user