WIP Add /weekly and /monthly to Telegram RPC

Related to "Show average profit in overview" (#5527)

Signed-off-by: Antoine Merino <antoine.merino.dev@gmail.com>
This commit is contained in:
Antoine Merino
2021-11-04 20:47:01 +01:00
parent d99eaccb5a
commit 5f40158c0b
4 changed files with 409 additions and 6 deletions

View File

@@ -4,7 +4,8 @@
import logging
import re
from datetime import datetime
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from functools import reduce
from random import choice, randint
from string import ascii_uppercase
@@ -94,10 +95,11 @@ 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'], ['buys'], ['sells'], ['mix_tags'], "
"['stats'], ['daily'], ['count'], ['locks'], "
"['unlock', 'delete_locks'], ['reload_config', 'reload_conf'], "
"['show_config', 'show_conf'], ['stopbuy'], "
"['whitelist'], ['blacklist'], ['logs'], ['edge'], ['help'], ['version']"
"['stats'], ['daily'], ['weekly'], ['monthly'], "
"['count'], ['locks'], ['unlock', 'delete_locks'], "
"['reload_config', 'reload_conf'], ['show_config', 'show_conf'], "
"['stopbuy'], ['whitelist'], ['blacklist'], "
"['logs'], ['edge'], ['help'], ['version']"
"]")
assert log_has(message_str, caplog)
@@ -425,6 +427,239 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
assert str('Daily Profit over the last 7 days') in msg_mock.call_args_list[0][0][0]
def test_weekly_handle(default_conf, update, ticker, limit_buy_order, fee,
limit_sell_order, mocker) -> None:
default_conf['max_open_trades'] = 1
mocker.patch(
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
return_value=15000.0
)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker,
get_fee=fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
# Create some test data
freqtradebot.enter_positions()
trade = Trade.query.first()
assert trade
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
# Simulate fulfilled LIMIT_SELL order for trade
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
# Try valid data
# /weekly 2
context = MagicMock()
context.args = ["2"]
telegram._weekly(update=update, context=context)
assert msg_mock.call_count == 1
assert 'Weekly' in msg_mock.call_args_list[0][0][0]
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
# Reset msg_mock
msg_mock.reset_mock()
context.args = []
telegram._weekly(update=update, context=context)
assert msg_mock.call_count == 1
assert 'Weekly' in msg_mock.call_args_list[0][0][0]
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
# Reset msg_mock
msg_mock.reset_mock()
freqtradebot.config['max_open_trades'] = 2
# Add two other trades
n = freqtradebot.enter_positions()
assert n == 2
trades = Trade.query.all()
for trade in trades:
trade.update(limit_buy_order)
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
# Make like the first trade was open and closed more than 8 weeks ago
trades[0].open_date = datetime.utcnow() - timedelta(weeks=8, days=2)
trades[0].close_date = datetime.utcnow() - timedelta(weeks=8, days=1)
# /weekly
# By default, the 8 previous weeks are shown
# So the previous modified trade should be excluded from the stats
context = MagicMock()
context.args = []
telegram._weekly(update=update, context=context)
# assert str(' 0.00012434 BTC') in msg_mock.call_args_list[0][0][0]
# assert str(' 1.865 USD') in msg_mock.call_args_list[0][0][0]
# assert str(' 2 trades') in msg_mock.call_args_list[0][0][0]
# The time-shifted trade should not appear
assert str(' 0.00006217 BTC') not in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') not in msg_mock.call_args_list[0][0][0]
assert str(' 1 trades') not in msg_mock.call_args_list[0][0][0]
# Reset msg_mock
msg_mock.reset_mock()
context.args = ["10"]
telegram._weekly(update=update, context=context)
assert msg_mock.call_count == 1
a = msg_mock.call_args_list[0][0][0]
# Now, the time-shifted trade should be included
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
assert str(' 1 trades') in msg_mock.call_args_list[0][0][0]
def test_weekly_wrong_input(default_conf, update, ticker, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
# Try invalid data
msg_mock.reset_mock()
freqtradebot.state = State.RUNNING
# /daily -2
context = MagicMock()
context.args = ["-3"]
telegram._weekly(update=update, context=context)
assert msg_mock.call_count == 1
assert 'must be an integer greater than 0' in msg_mock.call_args_list[0][0][0]
# Try invalid data
msg_mock.reset_mock()
freqtradebot.state = State.RUNNING
# /daily today
context = MagicMock()
context.args = ["this week"]
telegram._weekly(update=update, context=context)
assert str('Weekly Profit over the last 8 weeks') in msg_mock.call_args_list[0][0][0]
def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee,
limit_sell_order, mocker) -> None:
default_conf['max_open_trades'] = 1
mocker.patch(
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
return_value=15000.0
)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker,
get_fee=fee,
)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
# Create some test data
freqtradebot.enter_positions()
trade = Trade.query.first()
assert trade
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
# Simulate fulfilled LIMIT_SELL order for trade
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
# Try valid data
# /monthly 2
context = MagicMock()
context.args = ["2"]
telegram._monthly(update=update, context=context)
assert msg_mock.call_count == 1
assert 'Monthly' in msg_mock.call_args_list[0][0][0]
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
# Reset msg_mock
msg_mock.reset_mock()
context.args = []
telegram._monthly(update=update, context=context)
assert msg_mock.call_count == 1
assert 'Monthly' in msg_mock.call_args_list[0][0][0]
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
assert str(' 1 trade') in msg_mock.call_args_list[0][0][0]
assert str(' 0 trade') in msg_mock.call_args_list[0][0][0]
# Reset msg_mock
msg_mock.reset_mock()
freqtradebot.config['max_open_trades'] = 2
# Add two other trades
n = freqtradebot.enter_positions()
assert n == 2
trades = Trade.query.all()
for trade in trades:
trade.update(limit_buy_order)
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
# Make like the first trade was open and closed more than 6 months ago
trades[0].open_date = datetime.utcnow() - relativedelta(months=6, days=5)
trades[0].close_date = datetime.utcnow() - relativedelta(months=6, days=3)
# /weekly
# By default, the 6 previous months are shown
# So the previous modified trade should be excluded from the stats
context = MagicMock()
context.args = []
telegram._monthly(update=update, context=context)
# assert str(' 0.00012434 BTC') in msg_mock.call_args_list[0][0][0]
# assert str(' 1.865 USD') in msg_mock.call_args_list[0][0][0]
# assert str(' 2 trades') in msg_mock.call_args_list[0][0][0]
# The time-shifted trade should not appear
assert str(' 0.00006217 BTC') not in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') not in msg_mock.call_args_list[0][0][0]
assert str(' 1 trades') not in msg_mock.call_args_list[0][0][0]
# Reset msg_mock
msg_mock.reset_mock()
context.args = ["8"]
telegram._monthly(update=update, context=context)
assert msg_mock.call_count == 1
a = msg_mock.call_args_list[0][0][0]
# Now, the time-shifted trade should be included
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
assert str(' 1 trades') in msg_mock.call_args_list[0][0][0]
def test_profit_handle(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)