Merge branch 'lev-strat' into lev-freqtradebot
This commit is contained in:
@@ -42,5 +42,6 @@ def test_strategy_test_v2(result, fee):
|
||||
rate=20000, time_in_force='gtc', sell_reason='roi',
|
||||
current_time=datetime.utcnow()) is True
|
||||
|
||||
# TODO-lev: Test for shorts?
|
||||
assert strategy.custom_stoploss(pair='ETH/BTC', trade=trade, current_time=datetime.now(),
|
||||
current_rate=20_000, current_profit=0.05) == strategy.stoploss
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# pragma pylint: disable=missing-docstring, C0103
|
||||
from freqtrade.enums.signaltype import SignalDirection
|
||||
import logging
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
@@ -30,28 +31,56 @@ _STRATEGY = StrategyTestV2(config={})
|
||||
_STRATEGY.dp = DataProvider({}, None, None)
|
||||
|
||||
|
||||
def test_returns_latest_signal(mocker, default_conf, ohlcv_history):
|
||||
def test_returns_latest_signal(ohlcv_history):
|
||||
ohlcv_history.loc[1, 'date'] = arrow.utcnow()
|
||||
# Take a copy to correctly modify the call
|
||||
mocked_history = ohlcv_history.copy()
|
||||
mocked_history['sell'] = 0
|
||||
mocked_history['buy'] = 0
|
||||
mocked_history.loc[1, 'sell'] = 1
|
||||
mocked_history['enter_long'] = 0
|
||||
mocked_history['exit_long'] = 0
|
||||
mocked_history['enter_short'] = 0
|
||||
mocked_history['exit_short'] = 0
|
||||
mocked_history.loc[1, 'exit_long'] = 1
|
||||
|
||||
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, True, None)
|
||||
mocked_history.loc[1, 'sell'] = 0
|
||||
mocked_history.loc[1, 'buy'] = 1
|
||||
assert _STRATEGY.get_entry_signal('ETH/BTC', '5m', mocked_history) == (None, None)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (False, True)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (False, False)
|
||||
mocked_history.loc[1, 'exit_long'] = 0
|
||||
mocked_history.loc[1, 'enter_long'] = 1
|
||||
|
||||
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, None)
|
||||
mocked_history.loc[1, 'sell'] = 0
|
||||
mocked_history.loc[1, 'buy'] = 0
|
||||
assert _STRATEGY.get_entry_signal('ETH/BTC', '5m', mocked_history
|
||||
) == (SignalDirection.LONG, None)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (True, False)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (False, False)
|
||||
mocked_history.loc[1, 'exit_long'] = 0
|
||||
mocked_history.loc[1, 'enter_long'] = 0
|
||||
|
||||
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False, None)
|
||||
mocked_history.loc[1, 'sell'] = 0
|
||||
mocked_history.loc[1, 'buy'] = 1
|
||||
assert _STRATEGY.get_entry_signal('ETH/BTC', '5m', mocked_history) == (None, None)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (False, False)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (False, False)
|
||||
mocked_history.loc[1, 'exit_long'] = 0
|
||||
mocked_history.loc[1, 'enter_long'] = 1
|
||||
mocked_history.loc[1, 'buy_tag'] = 'buy_signal_01'
|
||||
|
||||
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, 'buy_signal_01')
|
||||
assert _STRATEGY.get_entry_signal(
|
||||
'ETH/BTC', '5m', mocked_history) == (SignalDirection.LONG, 'buy_signal_01')
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (True, False)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (False, False)
|
||||
|
||||
mocked_history.loc[1, 'exit_long'] = 0
|
||||
mocked_history.loc[1, 'enter_long'] = 0
|
||||
mocked_history.loc[1, 'enter_short'] = 1
|
||||
mocked_history.loc[1, 'exit_short'] = 0
|
||||
assert _STRATEGY.get_entry_signal(
|
||||
'ETH/BTC', '5m', mocked_history) == (SignalDirection.SHORT, None)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (False, False)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (True, False)
|
||||
|
||||
mocked_history.loc[1, 'enter_short'] = 0
|
||||
mocked_history.loc[1, 'exit_short'] = 1
|
||||
assert _STRATEGY.get_entry_signal(
|
||||
'ETH/BTC', '5m', mocked_history) == (None, None)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (False, False)
|
||||
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (False, True)
|
||||
|
||||
|
||||
def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
|
||||
@@ -67,18 +96,18 @@ def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
|
||||
assert log_has('Empty dataframe for pair ETH/BTC', caplog)
|
||||
|
||||
|
||||
def test_get_signal_empty(default_conf, mocker, caplog):
|
||||
assert (False, False, None) == _STRATEGY.get_signal(
|
||||
def test_get_signal_empty(default_conf, caplog):
|
||||
assert (None, None) == _STRATEGY.get_latest_candle(
|
||||
'foo', default_conf['timeframe'], DataFrame()
|
||||
)
|
||||
assert log_has('Empty candle (OHLCV) data for pair foo', caplog)
|
||||
caplog.clear()
|
||||
|
||||
assert (False, False, None) == _STRATEGY.get_signal('bar', default_conf['timeframe'], None)
|
||||
assert (None, None) == _STRATEGY.get_latest_candle('bar', default_conf['timeframe'], None)
|
||||
assert log_has('Empty candle (OHLCV) data for pair bar', caplog)
|
||||
caplog.clear()
|
||||
|
||||
assert (False, False, None) == _STRATEGY.get_signal(
|
||||
assert (None, None) == _STRATEGY.get_latest_candle(
|
||||
'baz',
|
||||
default_conf['timeframe'],
|
||||
DataFrame([])
|
||||
@@ -86,7 +115,7 @@ def test_get_signal_empty(default_conf, mocker, caplog):
|
||||
assert log_has('Empty candle (OHLCV) data for pair baz', caplog)
|
||||
|
||||
|
||||
def test_get_signal_exception_valueerror(default_conf, mocker, caplog, ohlcv_history):
|
||||
def test_get_signal_exception_valueerror(mocker, caplog, ohlcv_history):
|
||||
caplog.set_level(logging.INFO)
|
||||
mocker.patch.object(_STRATEGY.dp, 'ohlcv', return_value=ohlcv_history)
|
||||
mocker.patch.object(
|
||||
@@ -111,14 +140,14 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history):
|
||||
ohlcv_history.loc[1, 'date'] = arrow.utcnow().shift(minutes=-16)
|
||||
# Take a copy to correctly modify the call
|
||||
mocked_history = ohlcv_history.copy()
|
||||
mocked_history['sell'] = 0
|
||||
mocked_history['buy'] = 0
|
||||
mocked_history.loc[1, 'buy'] = 1
|
||||
mocked_history['exit_long'] = 0
|
||||
mocked_history['enter_long'] = 0
|
||||
mocked_history.loc[1, 'enter_long'] = 1
|
||||
|
||||
caplog.set_level(logging.INFO)
|
||||
mocker.patch.object(_STRATEGY, 'assert_df')
|
||||
|
||||
assert (False, False, None) == _STRATEGY.get_signal(
|
||||
assert (None, None) == _STRATEGY.get_latest_candle(
|
||||
'xyz',
|
||||
default_conf['timeframe'],
|
||||
mocked_history
|
||||
@@ -134,13 +163,13 @@ def test_get_signal_no_sell_column(default_conf, mocker, caplog, ohlcv_history):
|
||||
mocked_history = ohlcv_history.copy()
|
||||
# Intentionally don't set sell column
|
||||
# mocked_history['sell'] = 0
|
||||
mocked_history['buy'] = 0
|
||||
mocked_history.loc[1, 'buy'] = 1
|
||||
mocked_history['enter_long'] = 0
|
||||
mocked_history.loc[1, 'enter_long'] = 1
|
||||
|
||||
caplog.set_level(logging.INFO)
|
||||
mocker.patch.object(_STRATEGY, 'assert_df')
|
||||
|
||||
assert (True, False, None) == _STRATEGY.get_signal(
|
||||
assert (SignalDirection.LONG, None) == _STRATEGY.get_entry_signal(
|
||||
'xyz',
|
||||
default_conf['timeframe'],
|
||||
mocked_history
|
||||
@@ -452,27 +481,35 @@ def test_custom_sell(default_conf, fee, caplog) -> None:
|
||||
)
|
||||
|
||||
now = arrow.utcnow().datetime
|
||||
res = strategy.should_sell(trade, 1, now, False, False, None, None, 0)
|
||||
res = strategy.should_exit(trade, 1, now,
|
||||
enter=False, exit_=False,
|
||||
low=None, high=None)
|
||||
|
||||
assert res.sell_flag is False
|
||||
assert res.sell_type == SellType.NONE
|
||||
|
||||
strategy.custom_sell = MagicMock(return_value=True)
|
||||
res = strategy.should_sell(trade, 1, now, False, False, None, None, 0)
|
||||
res = strategy.should_exit(trade, 1, now,
|
||||
enter=False, exit_=False,
|
||||
low=None, high=None)
|
||||
assert res.sell_flag is True
|
||||
assert res.sell_type == SellType.CUSTOM_SELL
|
||||
assert res.sell_reason == 'custom_sell'
|
||||
|
||||
strategy.custom_sell = MagicMock(return_value='hello world')
|
||||
|
||||
res = strategy.should_sell(trade, 1, now, False, False, None, None, 0)
|
||||
res = strategy.should_exit(trade, 1, now,
|
||||
enter=False, exit_=False,
|
||||
low=None, high=None)
|
||||
assert res.sell_type == SellType.CUSTOM_SELL
|
||||
assert res.sell_flag is True
|
||||
assert res.sell_reason == 'hello world'
|
||||
|
||||
caplog.clear()
|
||||
strategy.custom_sell = MagicMock(return_value='h' * 100)
|
||||
res = strategy.should_sell(trade, 1, now, False, False, None, None, 0)
|
||||
res = strategy.should_exit(trade, 1, now,
|
||||
enter=False, exit_=False,
|
||||
low=None, high=None)
|
||||
assert res.sell_type == SellType.CUSTOM_SELL
|
||||
assert res.sell_flag is True
|
||||
assert res.sell_reason == 'h' * 64
|
||||
|
@@ -118,10 +118,12 @@ def test_strategy(result, default_conf):
|
||||
assert 'adx' in df_indicators
|
||||
|
||||
dataframe = strategy.advise_buy(df_indicators, metadata=metadata)
|
||||
assert 'buy' in dataframe.columns
|
||||
assert 'buy' not in dataframe.columns
|
||||
assert 'enter_long' in dataframe.columns
|
||||
|
||||
dataframe = strategy.advise_sell(df_indicators, metadata=metadata)
|
||||
assert 'sell' in dataframe.columns
|
||||
assert 'sell' not in dataframe.columns
|
||||
assert 'exit_long' in dataframe.columns
|
||||
|
||||
|
||||
def test_strategy_override_minimal_roi(caplog, default_conf):
|
||||
@@ -394,7 +396,7 @@ def test_call_deprecated_function(result, monkeypatch, default_conf, caplog):
|
||||
caplog)
|
||||
|
||||
|
||||
def test_strategy_interface_versioning(result, monkeypatch, default_conf):
|
||||
def test_strategy_interface_versioning(result, default_conf):
|
||||
default_conf.update({'strategy': 'StrategyTestV2'})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
metadata = {'pair': 'ETH/BTC'}
|
||||
@@ -411,8 +413,11 @@ def test_strategy_interface_versioning(result, monkeypatch, default_conf):
|
||||
|
||||
enterdf = strategy.advise_buy(result, metadata=metadata)
|
||||
assert isinstance(enterdf, DataFrame)
|
||||
assert 'buy' in enterdf.columns
|
||||
|
||||
assert 'buy' not in enterdf.columns
|
||||
assert 'enter_long' in enterdf.columns
|
||||
|
||||
exitdf = strategy.advise_sell(result, metadata=metadata)
|
||||
assert isinstance(exitdf, DataFrame)
|
||||
assert 'sell' in exitdf
|
||||
assert 'sell' not in exitdf
|
||||
assert 'exit_long' in exitdf
|
||||
|
Reference in New Issue
Block a user