Merge branch 'develop' into plugins/protections_backtest

This commit is contained in:
Matthias
2020-12-13 10:31:33 +01:00
24 changed files with 332 additions and 93 deletions

View File

@@ -1588,16 +1588,7 @@ def fetch_trades_result():
@pytest.fixture(scope="function")
def trades_for_order2():
return [{'info': {'id': 34567,
'orderId': 123456,
'price': '0.24544100',
'qty': '8.00000000',
'commission': '0.00800000',
'commissionAsset': 'LTC',
'time': 1521663363189,
'isBuyer': True,
'isMaker': False,
'isBestMatch': True},
return [{'info': {},
'timestamp': 1521663363189,
'datetime': '2018-03-21T20:16:03.189Z',
'symbol': 'LTC/ETH',
@@ -1609,16 +1600,7 @@ def trades_for_order2():
'cost': 1.963528,
'amount': 4.0,
'fee': {'cost': 0.004, 'currency': 'LTC'}},
{'info': {'id': 34567,
'orderId': 123456,
'price': '0.24544100',
'qty': '8.00000000',
'commission': '0.00800000',
'commissionAsset': 'LTC',
'time': 1521663363189,
'isBuyer': True,
'isMaker': False,
'isBestMatch': True},
{'info': {},
'timestamp': 1521663363189,
'datetime': '2018-03-21T20:16:03.189Z',
'symbol': 'LTC/ETH',
@@ -1632,6 +1614,14 @@ def trades_for_order2():
'fee': {'cost': 0.004, 'currency': 'LTC'}}]
@pytest.fixture(scope="function")
def trades_for_order3(trades_for_order2):
# Different fee currencies for each trade
trades_for_order = deepcopy(trades_for_order2)
trades_for_order[0]['fee'] = {'cost': 0.02, 'currency': 'BNB'}
return trades_for_order
@pytest.fixture
def buy_order_fee():
return {

View File

@@ -1,3 +1,5 @@
from datetime import datetime, timedelta, timezone
from freqtrade.persistence.models import Order, Trade
@@ -82,6 +84,9 @@ def mock_trade_2(fee):
is_open=False,
open_order_id='dry_run_sell_12345',
strategy='DefaultStrategy',
sell_reason='sell_signal',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
close_date=datetime.now(tz=timezone.utc),
)
o = Order.parse_from_ccxt_object(mock_order_2(), 'ETC/BTC', 'buy')
trade.orders.append(o)
@@ -134,6 +139,9 @@ def mock_trade_3(fee):
close_profit=0.01,
exchange='bittrex',
is_open=False,
sell_reason='roi',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
close_date=datetime.now(tz=timezone.utc),
)
o = Order.parse_from_ccxt_object(mock_order_3(), 'XRP/BTC', 'buy')
trade.orders.append(o)

View File

@@ -62,7 +62,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'fee_close_cost': ANY,
'fee_close_currency': ANY,
'open_rate_requested': ANY,
'open_trade_price': 0.0010025,
'open_trade_value': 0.0010025,
'close_rate_requested': ANY,
'sell_reason': ANY,
'sell_order_status': ANY,
@@ -127,7 +127,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'fee_close_cost': ANY,
'fee_close_currency': ANY,
'open_rate_requested': ANY,
'open_trade_price': ANY,
'open_trade_value': ANY,
'close_rate_requested': ANY,
'sell_reason': ANY,
'sell_order_status': ANY,

View File

@@ -559,6 +559,35 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, limit_buy_order, li
}
@pytest.mark.usefixtures("init_persistence")
def test_api_stats(botclient, mocker, ticker, fee, markets,):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
markets=PropertyMock(return_value=markets)
)
rc = client_get(client, f"{BASE_URI}/stats")
assert_response(rc, 200)
assert 'durations' in rc.json
assert 'sell_reasons' in rc.json
create_mock_trades(fee)
rc = client_get(client, f"{BASE_URI}/stats")
assert_response(rc, 200)
assert 'durations' in rc.json
assert 'sell_reasons' in rc.json
assert 'wins' in rc.json['durations']
assert 'losses' in rc.json['durations']
assert 'draws' in rc.json['durations']
def test_api_performance(botclient, mocker, ticker, fee):
ftbot, client = botclient
patch_get_signal(ftbot, (True, False))
@@ -678,7 +707,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
'min_rate': 1.098e-05,
'open_order_id': None,
'open_rate_requested': 1.098e-05,
'open_trade_price': 0.0010025,
'open_trade_value': 0.0010025,
'sell_reason': None,
'sell_order_status': None,
'strategy': 'DefaultStrategy',
@@ -805,7 +834,7 @@ def test_api_forcebuy(botclient, mocker, fee):
'min_rate': None,
'open_order_id': '123456',
'open_rate_requested': None,
'open_trade_price': 0.24605460,
'open_trade_value': 0.24605460,
'sell_reason': None,
'sell_order_status': None,
'strategy': None,

View File

@@ -74,9 +74,10 @@ def test_telegram_init(default_conf, mocker, caplog) -> None:
message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], "
"['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], ['trades'], "
"['delete'], ['performance'], ['daily'], ['count'], ['locks'], "
"['delete'], ['performance'], ['stats'], ['daily'], ['count'], ['locks'], "
"['reload_config', 'reload_conf'], ['show_config', 'show_conf'], ['stopbuy'], "
"['whitelist'], ['blacklist'], ['logs'], ['edge'], ['help'], ['version']]")
"['whitelist'], ['blacklist'], ['logs'], ['edge'], ['help'], ['version']"
"]")
assert log_has(message_str, caplog)
@@ -468,6 +469,41 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
assert '*Best Performing:* `ETH/BTC: 6.20%`' in msg_mock.call_args_list[-1][0][0]
def test_telegram_stats(default_conf, update, ticker, ticker_sell_up, fee,
limit_buy_order, limit_sell_order, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker,
get_fee=fee,
)
msg_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.rpc.telegram.Telegram',
_init=MagicMock(),
_send_msg=msg_mock
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot, (True, False))
telegram = Telegram(freqtradebot)
telegram._stats(update=update, context=MagicMock())
assert msg_mock.call_count == 1
# assert 'No trades yet.' in msg_mock.call_args_list[0][0][0]
msg_mock.reset_mock()
# Create some test data
create_mock_trades(fee)
telegram._stats(update=update, context=MagicMock())
assert msg_mock.call_count == 1
assert 'Sell Reason' in msg_mock.call_args_list[-1][0][0]
assert 'ROI' in msg_mock.call_args_list[-1][0][0]
assert 'Avg. Duration' in msg_mock.call_args_list[-1][0][0]
msg_mock.reset_mock()
def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tickers) -> None:
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)

View File

@@ -3744,6 +3744,48 @@ def test_get_real_amount_multi(default_conf, trades_for_order2, buy_order_fee, c
'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992).',
caplog)
assert trade.fee_open == 0.001
assert trade.fee_close == 0.001
assert trade.fee_open_cost is not None
assert trade.fee_open_currency is not None
assert trade.fee_close_cost is None
assert trade.fee_close_currency is None
def test_get_real_amount_multi2(default_conf, trades_for_order3, buy_order_fee, caplog, fee,
mocker, markets):
# Different fee currency on both trades
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order3)
amount = float(sum(x['amount'] for x in trades_for_order3))
default_conf['stake_currency'] = 'ETH'
trade = Trade(
pair='LTC/ETH',
amount=amount,
exchange='binance',
fee_open=fee.return_value,
fee_close=fee.return_value,
open_rate=0.245441,
open_order_id="123456"
)
# Fake markets entry to enable fee parsing
markets['BNB/ETH'] = markets['ETH/BTC']
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets))
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
return_value={'ask': 0.19, 'last': 0.2})
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount - (amount * 0.0005)
assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.996).',
caplog)
# Overall fee is average of both trade's fee
assert trade.fee_open == 0.001518575
assert trade.fee_open_cost is not None
assert trade.fee_open_currency is not None
assert trade.fee_close_cost is None
assert trade.fee_close_currency is None
def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee, fee,
caplog, mocker):
@@ -4290,7 +4332,7 @@ def test_update_closed_trades_without_assigned_fees(mocker, default_conf, fee):
freqtrade = get_patched_freqtradebot(mocker, default_conf)
def patch_with_fee(order):
order.update({'fee': {'cost': 0.1, 'rate': 0.2,
order.update({'fee': {'cost': 0.1, 'rate': 0.01,
'currency': order['symbol'].split('/')[0]}})
return order

View File

@@ -177,10 +177,10 @@ def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order, fee):
trade.open_order_id = 'something'
trade.update(limit_buy_order)
assert trade._calc_open_trade_price() == 0.0010024999999225068
assert trade._calc_open_trade_value() == 0.0010024999999225068
trade.update(limit_sell_order)
assert trade.calc_close_trade_price() == 0.0010646656050132426
assert trade.calc_close_trade_value() == 0.0010646656050132426
# Profit in BTC
assert trade.calc_profit() == 0.00006217
@@ -233,7 +233,7 @@ def test_calc_close_trade_price_exception(limit_buy_order, fee):
trade.open_order_id = 'something'
trade.update(limit_buy_order)
assert trade.calc_close_trade_price() == 0.0
assert trade.calc_close_trade_value() == 0.0
@pytest.mark.usefixtures("init_persistence")
@@ -277,7 +277,7 @@ def test_update_invalid_order(limit_buy_order):
@pytest.mark.usefixtures("init_persistence")
def test_calc_open_trade_price(limit_buy_order, fee):
def test_calc_open_trade_value(limit_buy_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
@@ -291,10 +291,10 @@ def test_calc_open_trade_price(limit_buy_order, fee):
trade.update(limit_buy_order) # Buy @ 0.00001099
# Get the open rate price with the standard fee rate
assert trade._calc_open_trade_price() == 0.0010024999999225068
assert trade._calc_open_trade_value() == 0.0010024999999225068
trade.fee_open = 0.003
# Get the open rate price with a custom fee rate
assert trade._calc_open_trade_price() == 0.001002999999922468
assert trade._calc_open_trade_value() == 0.001002999999922468
@pytest.mark.usefixtures("init_persistence")
@@ -312,14 +312,14 @@ def test_calc_close_trade_price(limit_buy_order, limit_sell_order, fee):
trade.update(limit_buy_order) # Buy @ 0.00001099
# Get the close rate price with a custom close rate and a regular fee rate
assert trade.calc_close_trade_price(rate=0.00001234) == 0.0011200318470471794
assert trade.calc_close_trade_value(rate=0.00001234) == 0.0011200318470471794
# Get the close rate price with a custom close rate and a custom fee rate
assert trade.calc_close_trade_price(rate=0.00001234, fee=0.003) == 0.0011194704275749754
assert trade.calc_close_trade_value(rate=0.00001234, fee=0.003) == 0.0011194704275749754
# Test when we apply a Sell order, and ask price with a custom fee rate
trade.update(limit_sell_order)
assert trade.calc_close_trade_price(fee=0.005) == 0.0010619972701635854
assert trade.calc_close_trade_value(fee=0.005) == 0.0010619972701635854
@pytest.mark.usefixtures("init_persistence")
@@ -499,7 +499,7 @@ def test_migrate_old(mocker, default_conf, fee):
assert trade.max_rate == 0.0
assert trade.stop_loss == 0.0
assert trade.initial_stop_loss == 0.0
assert trade.open_trade_price == trade._calc_open_trade_price()
assert trade.open_trade_value == trade._calc_open_trade_value()
assert trade.close_profit_abs is None
assert trade.fee_open_cost is None
assert trade.fee_open_currency is None
@@ -607,7 +607,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog):
assert log_has("trying trades_bak1", caplog)
assert log_has("trying trades_bak2", caplog)
assert log_has("Running database migration for trades - backup: trades_bak2", caplog)
assert trade.open_trade_price == trade._calc_open_trade_price()
assert trade.open_trade_value == trade._calc_open_trade_value()
assert trade.close_profit_abs is None
assert log_has("Moving open orders to Orders table.", caplog)
@@ -677,7 +677,7 @@ def test_migrate_mid_state(mocker, default_conf, fee, caplog):
assert trade.max_rate == 0.0
assert trade.stop_loss == 0.0
assert trade.initial_stop_loss == 0.0
assert trade.open_trade_price == trade._calc_open_trade_price()
assert trade.open_trade_value == trade._calc_open_trade_value()
assert log_has("trying trades_bak0", caplog)
assert log_has("Running database migration for trades - backup: trades_bak0", caplog)
@@ -803,7 +803,7 @@ def test_to_json(default_conf, fee):
'close_timestamp': None,
'open_rate': 0.123,
'open_rate_requested': None,
'open_trade_price': 15.1668225,
'open_trade_value': 15.1668225,
'fee_close': 0.0025,
'fee_close_cost': None,
'fee_close_currency': None,
@@ -896,7 +896,7 @@ def test_to_json(default_conf, fee):
'min_rate': None,
'open_order_id': None,
'open_rate_requested': None,
'open_trade_price': 12.33075,
'open_trade_value': 12.33075,
'sell_reason': None,
'sell_order_status': None,
'strategy': None,