Merge pull request #5299 from kevinjulian/feat/kevinjulian/add-buy-signal-name

Add buy signal name
This commit is contained in:
Matthias
2021-07-30 08:23:11 +02:00
committed by GitHub
23 changed files with 261 additions and 115 deletions

View File

@@ -182,7 +182,7 @@ def get_patched_worker(mocker, config) -> Worker:
return Worker(args=None, config=config)
def patch_get_signal(freqtrade: FreqtradeBot, value=(True, False)) -> None:
def patch_get_signal(freqtrade: FreqtradeBot, value=(True, False, None)) -> None:
"""
:param mocker: mocker to patch IStrategy class
:param value: which value IStrategy.get_signal() must return

View File

@@ -29,7 +29,6 @@ from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe,
tests_start_time = arrow.get(2018, 10, 3)
timeframe_in_minute = 60
_ohlc = {'date': 0, 'buy': 1, 'open': 2, 'high': 3, 'low': 4, 'close': 5, 'sell': 6, 'volume': 7}
# Helpers for this test file

View File

@@ -18,6 +18,7 @@ class BTrade(NamedTuple):
sell_reason: SellType
open_tick: int
close_tick: int
buy_tag: Optional[str] = None
class BTContainer(NamedTuple):
@@ -44,6 +45,7 @@ def _get_frame_time_from_offset(offset):
def _build_backtest_dataframe(data):
columns = ['date', 'open', 'high', 'low', 'close', 'volume', 'buy', 'sell']
columns = columns + ['buy_tag'] if len(data[0]) == 9 else columns
frame = DataFrame.from_records(data, columns=columns)
frame['date'] = frame['date'].apply(_get_frame_time_from_offset)

View File

@@ -516,6 +516,26 @@ tc32 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)]
)
# Test 33: trailing_stop should be triggered immediately on trade open candle.
# stop-loss: 1%, ROI: 10% (should not apply)
tc33 = BTContainer(data=[
# D O H L C V B S BT
[0, 5000, 5050, 4950, 5000, 6172, 1, 0, 'buy_signal_01'],
[1, 5000, 5500, 5000, 4900, 6172, 0, 0, None], # enter trade (signal on last candle) and stop
[2, 4900, 5250, 4500, 5100, 6172, 0, 0, None],
[3, 5100, 5100, 4650, 4750, 6172, 0, 0, None],
[4, 4750, 4950, 4350, 4750, 6172, 0, 0, None]],
stop_loss=-0.01, roi={"0": 0.10}, profit_perc=-0.01, trailing_stop=True,
trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.02,
trailing_stop_positive=0.01, use_custom_stoploss=True,
trades=[BTrade(
sell_reason=SellType.TRAILING_STOP_LOSS,
open_tick=1,
close_tick=1,
buy_tag='buy_signal_01'
)]
)
TESTS = [
tc0,
tc1,
@@ -550,6 +570,7 @@ TESTS = [
tc30,
tc31,
tc32,
tc33,
]
@@ -599,5 +620,6 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
for c, trade in enumerate(data.trades):
res = results.iloc[c]
assert res.sell_reason == trade.sell_reason.value
assert res.buy_tag == trade.buy_tag
assert res.open_date == _get_frame_time_from_offset(trade.open_tick)
assert res.close_date == _get_frame_time_from_offset(trade.close_tick)

View File

@@ -496,6 +496,7 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
0, # Sell
0.00099, # Low
0.0012, # High
'', # Buy Signal Name
]
trade = backtesting._enter_trade(pair, row=row)
assert isinstance(trade, LocalTrade)
@@ -583,6 +584,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
'min_rate': [0.1038, 0.10302485],
'max_rate': [0.10501, 0.1038888],
'is_open': [False, False],
'buy_tag': [None, None],
})
pd.testing.assert_frame_equal(results, expected)
data_pair = processed[pair]
@@ -858,7 +860,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
'locks': [],
'rejected_signals': 20,
'final_balance': 1000,
})
})
mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist',
PropertyMock(return_value=['UNITTEST/BTC']))
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', backtestmock)

View File

@@ -35,7 +35,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -69,6 +69,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'min_rate': ANY,
'max_rate': ANY,
'strategy': ANY,
'buy_tag': ANY,
'timeframe': 5,
'open_order_id': ANY,
'close_date': None,
@@ -135,6 +136,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'min_rate': ANY,
'max_rate': ANY,
'strategy': ANY,
'buy_tag': ANY,
'timeframe': ANY,
'open_order_id': ANY,
'close_date': None,
@@ -190,7 +192,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
)
del default_conf['fiat_display_currency']
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -237,7 +239,7 @@ def test_rpc_daily_profit(default_conf, update, ticker, fee,
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
stake_currency = default_conf['stake_currency']
fiat_display_currency = default_conf['fiat_display_currency']
@@ -369,7 +371,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
stake_currency = default_conf['stake_currency']
fiat_display_currency = default_conf['fiat_display_currency']
@@ -457,7 +459,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee,
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
stake_currency = default_conf['stake_currency']
fiat_display_currency = default_conf['fiat_display_currency']
@@ -524,7 +526,7 @@ def test_rpc_balance_handle_error(default_conf, mocker):
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
rpc._fiat_converter = CryptoToFiatConverter()
with pytest.raises(RPCException, match="Error getting current tickers."):
@@ -565,7 +567,7 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
)
default_conf['dry_run'] = False
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
rpc._fiat_converter = CryptoToFiatConverter()
@@ -610,7 +612,7 @@ def test_rpc_start(mocker, default_conf) -> None:
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -631,7 +633,7 @@ def test_rpc_stop(mocker, default_conf) -> None:
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -653,7 +655,7 @@ def test_rpc_stopbuy(mocker, default_conf) -> None:
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -685,7 +687,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
mocker.patch('freqtrade.wallets.Wallets.get_free', return_value=1000)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -803,7 +805,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
# Create some test data
@@ -836,7 +838,7 @@ def test_rpc_count(mocker, default_conf, ticker, fee) -> None:
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
counts = rpc._rpc_count()
@@ -861,7 +863,7 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order_open) ->
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
pair = 'ETH/BTC'
trade = rpc._rpc_forcebuy(pair, None)
@@ -887,7 +889,7 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order_open) ->
# Test not buying
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
freqtradebot.config['stake_amount'] = 0
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
pair = 'TKN/BTC'
trade = rpc._rpc_forcebuy(pair, None)
@@ -900,7 +902,7 @@ def test_rpcforcebuy_stopped(mocker, default_conf) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
pair = 'ETH/BTC'
with pytest.raises(RPCException, match=r'trader is not running'):
@@ -911,7 +913,7 @@ def test_rpcforcebuy_disabled(mocker, default_conf) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
rpc = RPC(freqtradebot)
pair = 'ETH/BTC'
with pytest.raises(RPCException, match=r'Forcebuy not enabled.'):

View File

@@ -442,7 +442,7 @@ def test_api_balance(botclient, mocker, rpc_balance):
def test_api_count(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@@ -504,7 +504,7 @@ def test_api_locks(botclient):
def test_api_show_config(botclient, mocker):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
rc = client_get(client, f"{BASE_URI}/show_config")
assert_response(rc)
@@ -522,7 +522,7 @@ def test_api_show_config(botclient, mocker):
def test_api_daily(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@@ -540,7 +540,7 @@ def test_api_daily(botclient, mocker, ticker, fee, markets):
def test_api_trades(botclient, mocker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets)
@@ -568,7 +568,7 @@ def test_api_trades(botclient, mocker, fee, markets):
def test_api_trade_single(botclient, mocker, fee, ticker, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets),
@@ -588,7 +588,7 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets):
def test_api_delete_trade(botclient, mocker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
stoploss_mock = MagicMock()
cancel_mock = MagicMock()
mocker.patch.multiple(
@@ -662,7 +662,7 @@ def test_api_logs(botclient):
def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@@ -678,7 +678,7 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
@pytest.mark.usefixtures("init_persistence")
def test_api_profit(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@@ -729,7 +729,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets):
@pytest.mark.usefixtures("init_persistence")
def test_api_stats(botclient, mocker, ticker, fee, markets,):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@@ -757,7 +757,7 @@ def test_api_stats(botclient, mocker, ticker, fee, markets,):
def test_api_performance(botclient, fee):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
trade = Trade(
pair='LTC/ETH',
@@ -803,7 +803,7 @@ def test_api_performance(botclient, fee):
def test_api_status(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
@@ -875,6 +875,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
'sell_reason': None,
'sell_order_status': None,
'strategy': 'DefaultStrategy',
'buy_tag': None,
'timeframe': 5,
'exchange': 'binance',
}
@@ -1029,6 +1030,7 @@ def test_api_forcebuy(botclient, mocker, fee):
'sell_reason': None,
'sell_order_status': None,
'strategy': 'DefaultStrategy',
'buy_tag': None,
'timeframe': 5,
'exchange': 'binance',
}
@@ -1044,7 +1046,7 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets):
markets=PropertyMock(return_value=markets),
_is_dry_limit_order_filled=MagicMock(return_value=False),
)
patch_get_signal(ftbot, (True, False))
patch_get_signal(ftbot, (True, False, None))
rc = client_post(client, f"{BASE_URI}/forcesell",
data='{"tradeid": "1"}')
@@ -1185,8 +1187,10 @@ def test_api_plot_config(botclient):
assert_response(rc)
assert rc.json() == {}
ftbot.strategy.plot_config = {'main_plot': {'sma': {}},
'subplots': {'RSI': {'rsi': {'color': 'red'}}}}
ftbot.strategy.plot_config = {
'main_plot': {'sma': {}},
'subplots': {'RSI': {'rsi': {'color': 'red'}}}
}
rc = client_get(client, f"{BASE_URI}/plot_config")
assert_response(rc)
assert rc.json() == ftbot.strategy.plot_config

View File

@@ -119,7 +119,7 @@ def test_authorized_only(default_conf, mocker, caplog, update) -> None:
rpc = RPC(bot)
dummy = DummyCls(rpc, default_conf)
patch_get_signal(bot, (True, False))
patch_get_signal(bot, (True, False, None))
dummy.dummy_handler(update=update, context=MagicMock())
assert dummy.state['called'] is True
assert log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
@@ -139,7 +139,7 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
rpc = RPC(bot)
dummy = DummyCls(rpc, default_conf)
patch_get_signal(bot, (True, False))
patch_get_signal(bot, (True, False, None))
dummy.dummy_handler(update=update, context=MagicMock())
assert dummy.state['called'] is False
assert not log_has('Executing handler: dummy_handler for chat_id: 3735928559', caplog)
@@ -155,7 +155,7 @@ def test_authorized_only_exception(default_conf, mocker, caplog, update) -> None
bot = FreqtradeBot(default_conf)
rpc = RPC(bot)
dummy = DummyCls(rpc, default_conf)
patch_get_signal(bot, (True, False))
patch_get_signal(bot, (True, False, None))
dummy.dummy_exception(update=update, context=MagicMock())
assert dummy.state['called'] is False
@@ -185,6 +185,7 @@ def test_telegram_status(default_conf, update, mocker) -> None:
'current_rate': 1.098e-05,
'amount': 90.99181074,
'stake_amount': 90.99181074,
'buy_tag': None,
'close_profit_pct': None,
'profit': -0.0059,
'profit_pct': -0.59,
@@ -228,7 +229,7 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None:
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
freqtradebot.state = State.STOPPED
# Status is also enabled when stopped
@@ -285,7 +286,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None:
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
freqtradebot.state = State.STOPPED
# Status table is also enabled when stopped
@@ -329,7 +330,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Create some test data
freqtradebot.enter_positions()
@@ -400,7 +401,7 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Try invalid data
msg_mock.reset_mock()
@@ -432,7 +433,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
telegram._profit(update=update, context=MagicMock())
assert msg_mock.call_count == 1
@@ -487,7 +488,7 @@ def test_telegram_stats(default_conf, update, ticker, ticker_sell_up, fee,
get_fee=fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
telegram._stats(update=update, context=MagicMock())
assert msg_mock.call_count == 1
@@ -513,7 +514,7 @@ def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tick
side_effect=lambda a, b: f"{a}/{b}")
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
telegram._balance(update=update, context=MagicMock())
result = msg_mock.call_args_list[0][0][0]
@@ -536,7 +537,7 @@ def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value={})
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
freqtradebot.config['dry_run'] = False
telegram._balance(update=update, context=MagicMock())
@@ -549,7 +550,7 @@ def test_balance_handle_empty_response_dry(default_conf, update, mocker) -> None
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value={})
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
telegram._balance(update=update, context=MagicMock())
result = msg_mock.call_args_list[0][0][0]
@@ -578,7 +579,7 @@ def test_balance_handle_too_large_response(default_conf, update, mocker) -> None
})
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
telegram._balance(update=update, context=MagicMock())
assert msg_mock.call_count > 1
@@ -677,7 +678,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
telegram = Telegram(rpc, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Create some test data
freqtradebot.enter_positions()
@@ -736,7 +737,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
telegram = Telegram(rpc, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Create some test data
freqtradebot.enter_positions()
@@ -797,7 +798,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
telegram = Telegram(rpc, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Create some test data
freqtradebot.enter_positions()
@@ -838,7 +839,7 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
return_value=15000.0)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Trader is not running
freqtradebot.state = State.STOPPED
@@ -876,7 +877,7 @@ def test_forcebuy_handle(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.rpc.RPC._rpc_forcebuy', fbuy_mock)
telegram, freqtradebot, _ = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# /forcebuy ETH/BTC
context = MagicMock()
@@ -905,7 +906,7 @@ def test_forcebuy_handle_exception(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
update.message.text = '/forcebuy ETH/Nonepair'
telegram._forcebuy(update=update, context=MagicMock())
@@ -922,7 +923,7 @@ def test_forcebuy_no_pair(default_conf, update, mocker) -> None:
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
context = MagicMock()
context.args = []
@@ -950,7 +951,7 @@ def test_performance_handle(default_conf, update, ticker, fee,
get_fee=fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
# Create some test data
freqtradebot.enter_positions()
@@ -978,7 +979,7 @@ def test_count_handle(default_conf, update, ticker, fee, mocker) -> None:
get_fee=fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
freqtradebot.state = State.STOPPED
telegram._count(update=update, context=MagicMock())
@@ -1007,7 +1008,7 @@ def test_telegram_lock_handle(default_conf, update, ticker, fee, mocker) -> None
get_fee=fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
patch_get_signal(freqtradebot, (True, False, None))
telegram._locks(update=update, context=MagicMock())
assert msg_mock.call_count == 1
assert 'No active locks.' in msg_mock.call_args_list[0][0][0]
@@ -1253,6 +1254,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog) -> None:
msg = {
'type': RPCMessageType.BUY,
'trade_id': 1,
'buy_tag': 'buy_signal_01',
'exchange': 'Binance',
'pair': 'ETH/BTC',
'limit': 1.099e-05,
@@ -1270,6 +1272,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog) -> None:
telegram.send_msg(msg)
assert msg_mock.call_args[0][0] \
== '\N{LARGE BLUE CIRCLE} *Binance:* Buying ETH/BTC (#1)\n' \
'*Buy Tag:* `buy_signal_01`\n' \
'*Amount:* `1333.33333333`\n' \
'*Open Rate:* `0.00001099`\n' \
'*Current Rate:* `0.00001099`\n' \
@@ -1297,6 +1300,7 @@ def test_send_msg_buy_cancel_notification(default_conf, mocker) -> None:
telegram.send_msg({
'type': RPCMessageType.BUY_CANCEL,
'buy_tag': 'buy_signal_01',
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/BTC',
@@ -1314,6 +1318,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker) -> None:
telegram.send_msg({
'type': RPCMessageType.BUY_FILL,
'buy_tag': 'buy_signal_01',
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/USDT',
@@ -1498,6 +1503,7 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None:
telegram.send_msg({
'type': RPCMessageType.BUY,
'buy_tag': 'buy_signal_01',
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/BTC',
@@ -1512,6 +1518,7 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None:
'open_date': arrow.utcnow().shift(hours=-1)
})
assert msg_mock.call_args[0][0] == ('\N{LARGE BLUE CIRCLE} *Binance:* Buying ETH/BTC (#1)\n'
'*Buy Tag:* `buy_signal_01`\n'
'*Amount:* `1333.33333333`\n'
'*Open Rate:* `0.00001099`\n'
'*Current Rate:* `0.00001099`\n'

View File

@@ -38,15 +38,20 @@ def test_returns_latest_signal(mocker, default_conf, ohlcv_history):
mocked_history['buy'] = 0
mocked_history.loc[1, 'sell'] = 1
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, True)
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_signal('ETH/BTC', '5m', mocked_history) == (True, False)
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_signal('ETH/BTC', '5m', mocked_history) == (False, False)
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False, None)
mocked_history.loc[1, 'sell'] = 0
mocked_history.loc[1, 'buy'] = 1
mocked_history.loc[1, 'buy_tag'] = 'buy_signal_01'
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, 'buy_signal_01')
def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
@@ -63,15 +68,21 @@ def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
def test_get_signal_empty(default_conf, mocker, caplog):
assert (False, False) == _STRATEGY.get_signal('foo', default_conf['timeframe'], DataFrame())
assert (False, False, None) == _STRATEGY.get_signal(
'foo', default_conf['timeframe'], DataFrame()
)
assert log_has('Empty candle (OHLCV) data for pair foo', caplog)
caplog.clear()
assert (False, False) == _STRATEGY.get_signal('bar', default_conf['timeframe'], None)
assert (False, False, None) == _STRATEGY.get_signal('bar', default_conf['timeframe'], None)
assert log_has('Empty candle (OHLCV) data for pair bar', caplog)
caplog.clear()
assert (False, False) == _STRATEGY.get_signal('baz', default_conf['timeframe'], DataFrame([]))
assert (False, False, None) == _STRATEGY.get_signal(
'baz',
default_conf['timeframe'],
DataFrame([])
)
assert log_has('Empty candle (OHLCV) data for pair baz', caplog)
@@ -107,7 +118,11 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history):
caplog.set_level(logging.INFO)
mocker.patch.object(_STRATEGY, 'assert_df')
assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['timeframe'], mocked_history)
assert (False, False, None) == _STRATEGY.get_signal(
'xyz',
default_conf['timeframe'],
mocked_history
)
assert log_has('Outdated history for pair xyz. Last tick is 16 minutes old', caplog)

View File

@@ -536,7 +536,7 @@ def test_create_trade_no_signal(default_conf, fee, mocker) -> None:
)
default_conf['stake_amount'] = 10
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade, value=(False, False))
patch_get_signal(freqtrade, value=(False, False, None))
Trade.query = MagicMock()
Trade.query.filter = MagicMock()
@@ -757,7 +757,10 @@ def test_process_informative_pairs_added(default_conf, ticker, mocker) -> None:
refresh_latest_ohlcv=refresh_mock,
)
inf_pairs = MagicMock(return_value=[("BTC/ETH", '1m'), ("ETH/USDT", "1h")])
mocker.patch('freqtrade.strategy.interface.IStrategy.get_signal', return_value=(False, False))
mocker.patch(
'freqtrade.strategy.interface.IStrategy.get_signal',
return_value=(False, False, '')
)
mocker.patch('time.sleep', return_value=None)
freqtrade = FreqtradeBot(default_conf)
@@ -1857,7 +1860,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order_open, limi
assert trade.is_open is True
freqtrade.wallets.update()
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is True
assert trade.open_order_id == limit_sell_order['id']
@@ -1882,7 +1885,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open,
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade, value=(True, True))
patch_get_signal(freqtrade, value=(True, True, None))
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.enter_positions()
@@ -1893,7 +1896,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open,
assert nb_trades == 0
# Buy is triggering, so buying ...
patch_get_signal(freqtrade, value=(True, False))
patch_get_signal(freqtrade, value=(True, False, None))
freqtrade.enter_positions()
trades = Trade.query.all()
nb_trades = len(trades)
@@ -1901,7 +1904,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open,
assert trades[0].is_open is True
# Buy and Sell are not triggering, so doing nothing ...
patch_get_signal(freqtrade, value=(False, False))
patch_get_signal(freqtrade, value=(False, False, None))
assert freqtrade.handle_trade(trades[0]) is False
trades = Trade.query.all()
nb_trades = len(trades)
@@ -1909,7 +1912,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open,
assert trades[0].is_open is True
# Buy and Sell are triggering, so doing nothing ...
patch_get_signal(freqtrade, value=(True, True))
patch_get_signal(freqtrade, value=(True, True, None))
assert freqtrade.handle_trade(trades[0]) is False
trades = Trade.query.all()
nb_trades = len(trades)
@@ -1917,7 +1920,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open,
assert trades[0].is_open is True
# Sell is triggering, guess what : we are Selling!
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
trades = Trade.query.all()
assert freqtrade.handle_trade(trades[0]) is True
@@ -1935,7 +1938,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open,
)
freqtrade = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtrade, value=(True, False))
patch_get_signal(freqtrade, value=(True, False, None))
freqtrade.strategy.min_roi_reached = MagicMock(return_value=True)
freqtrade.enter_positions()
@@ -1948,7 +1951,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open,
# we might just want to check if we are in a sell condition without
# executing
# if ROI is reached we must sell
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade)
assert log_has("ETH/BTC - Required profit reached. sell_type=SellType.ROI",
caplog)
@@ -1974,10 +1977,10 @@ def test_handle_trade_use_sell_signal(
trade = Trade.query.first()
trade.is_open = True
patch_get_signal(freqtrade, value=(False, False))
patch_get_signal(freqtrade, value=(False, False, None))
assert not freqtrade.handle_trade(trade)
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade)
assert log_has("ETH/BTC - Sell signal received. sell_type=SellType.SELL_SIGNAL",
caplog)
@@ -3013,7 +3016,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, limit_buy
trade = Trade.query.first()
trade.update(limit_buy_order)
freqtrade.wallets.update()
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is False
freqtrade.strategy.sell_profit_offset = 0.0
@@ -3048,7 +3051,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, limit_bu
trade = Trade.query.first()
trade.update(limit_buy_order)
freqtrade.wallets.update()
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.SELL_SIGNAL.value
@@ -3079,7 +3082,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, limit_buy_o
trade = Trade.query.first()
trade.update(limit_buy_order)
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is False
@@ -3111,7 +3114,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, limit_buy_
trade = Trade.query.first()
trade.update(limit_buy_order)
freqtrade.wallets.update()
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.SELL_SIGNAL.value
@@ -3140,7 +3143,7 @@ def test_sell_not_enough_balance(default_conf, limit_buy_order, limit_buy_order_
trade = Trade.query.first()
amnt = trade.amount
trade.update(limit_buy_order)
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=trade.amount * 0.985))
assert freqtrade.handle_trade(trade) is True
@@ -3259,11 +3262,11 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, limit_buy_order
trade = Trade.query.first()
trade.update(limit_buy_order)
freqtrade.wallets.update()
patch_get_signal(freqtrade, value=(True, True))
patch_get_signal(freqtrade, value=(True, True, None))
assert freqtrade.handle_trade(trade) is False
# Test if buy-signal is absent (should sell due to roi = true)
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.ROI.value
@@ -3524,11 +3527,11 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order, limit_b
trade = Trade.query.first()
trade.update(limit_buy_order)
# Sell due to min_roi_reached
patch_get_signal(freqtrade, value=(True, True))
patch_get_signal(freqtrade, value=(True, True, None))
assert freqtrade.handle_trade(trade) is True
# Test if buy-signal is absent
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is True
assert trade.sell_reason == SellType.SELL_SIGNAL.value
@@ -4056,7 +4059,7 @@ def test_order_book_ask_strategy(default_conf, limit_buy_order_open, limit_buy_o
freqtrade.wallets.update()
assert trade.is_open is True
patch_get_signal(freqtrade, value=(False, True))
patch_get_signal(freqtrade, value=(False, True, None))
assert freqtrade.handle_trade(trade) is True
assert trade.close_rate_requested == order_book_l2.return_value['asks'][0][0]

View File

@@ -861,6 +861,7 @@ def test_to_json(default_conf, fee):
open_date=arrow.utcnow().shift(hours=-2).datetime,
open_rate=0.123,
exchange='binance',
buy_tag=None,
open_order_id='dry_run_buy_12345'
)
result = trade.to_json()
@@ -910,6 +911,7 @@ def test_to_json(default_conf, fee):
'min_rate': None,
'max_rate': None,
'strategy': None,
'buy_tag': None,
'timeframe': None,
'exchange': 'binance',
}
@@ -926,6 +928,7 @@ def test_to_json(default_conf, fee):
close_date=arrow.utcnow().shift(hours=-1).datetime,
open_rate=0.123,
close_rate=0.125,
buy_tag='buys_signal_001',
exchange='binance',
)
result = trade.to_json()
@@ -975,6 +978,7 @@ def test_to_json(default_conf, fee):
'sell_reason': None,
'sell_order_status': None,
'strategy': None,
'buy_tag': 'buys_signal_001',
'timeframe': None,
'exchange': 'binance',
}
@@ -1319,7 +1323,7 @@ def test_Trade_object_idem():
'get_open_trades_without_assigned_fees',
'get_open_order_trades',
'get_trades',
)
)
# Parent (LocalTrade) should have the same attributes
for item in trade: