Added daily profit telegram command

This commit is contained in:
Stephen Dade 2017-12-10 17:32:40 +11:00
parent 82bf0be3e2
commit ccb8c3c352
3 changed files with 76 additions and 4 deletions

View File

@ -25,6 +25,7 @@ Persistence is achieved through sqlite.
* /forcesell <trade_id>|all: Instantly sells the given trade (Ignoring `minimum_roi`). * /forcesell <trade_id>|all: Instantly sells the given trade (Ignoring `minimum_roi`).
* /performance: Show performance of each finished trade grouped by pair * /performance: Show performance of each finished trade grouped by pair
* /balance: Show account balance per currency * /balance: Show account balance per currency
* /daily [n]: Shows profit or loss per day, over the last n (default 7) days
* /help: Show help message * /help: Show help message
* /version: Show version * /version: Show version

View File

@ -1,11 +1,11 @@
import logging import logging
import re import re
from datetime import timedelta from datetime import timedelta, date
from typing import Callable, Any from typing import Callable, Any
import arrow import arrow
from pandas import DataFrame from pandas import DataFrame
from sqlalchemy import and_, func, text from sqlalchemy import and_, func, text, between
from tabulate import tabulate from tabulate import tabulate
from telegram import ParseMode, Bot, Update, ReplyKeyboardMarkup from telegram import ParseMode, Bot, Update, ReplyKeyboardMarkup
from telegram.error import NetworkError, TelegramError from telegram.error import NetworkError, TelegramError
@ -49,6 +49,7 @@ def init(config: dict) -> None:
CommandHandler('stop', _stop), CommandHandler('stop', _stop),
CommandHandler('forcesell', _forcesell), CommandHandler('forcesell', _forcesell),
CommandHandler('performance', _performance), CommandHandler('performance', _performance),
CommandHandler('daily', _daily),
CommandHandler('count', _count), CommandHandler('count', _count),
CommandHandler('help', _help), CommandHandler('help', _help),
CommandHandler('version', _version), CommandHandler('version', _version),
@ -206,7 +207,44 @@ def _status_table(bot: Bot, update: Update) -> None:
send_msg(message, parse_mode=ParseMode.HTML) send_msg(message, parse_mode=ParseMode.HTML)
@authorized_only
def _daily(bot: Bot, update: Update) -> None:
"""
Handler for /daily <n>
Returns a daily profit (in BTC) over the last n days.
Default is 7 days
:param bot: telegram bot
:param update: message update
:return: None
"""
trades = Trade.query.order_by(Trade.close_date).all()
today = date.today().toordinal()
profit_days = {}
try:
timescale = update.message.text.replace('/daily', '').strip()
except:
timescale = 7
for day in range(0, timescale):
#need to query between day+1 and day-1
nextdate = date.fromordinal(today-day+1)
prevdate = date.fromordinal(today-day-1)
trades = Trade.query.filter(between(Trade.close_date, prevdate, nextdate)).all()
curdayprofit = 0
for trade in trades:
curdayprofit += trade.close_profit * trade.stake_amount
profit_days[date.fromordinal(today-day)] = curdayprofit
stats = '\n'.join('{index}\t{profit} BTC'.format(
index=key,
profit=value,
) for key, value in profit_days.items())
message = '<b>Daily Profit:</b>\n{}'.format(stats)
send_msg(message, bot=bot)
@authorized_only @authorized_only
def _profit(bot: Bot, update: Update) -> None: def _profit(bot: Bot, update: Update) -> None:
""" """

View File

@ -1,6 +1,6 @@
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors, C0103 # pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors, C0103
import re import re
from datetime import datetime from datetime import datetime, date
from random import randint from random import randint
from unittest.mock import MagicMock from unittest.mock import MagicMock
@ -14,7 +14,7 @@ from freqtrade.misc import update_state, State, get_state
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.rpc import telegram from freqtrade.rpc import telegram
from freqtrade.rpc.telegram import authorized_only, is_enabled, send_msg, _status, _status_table, \ from freqtrade.rpc.telegram import authorized_only, is_enabled, send_msg, _status, _status_table, \
_profit, _forcesell, _performance, _count, _start, _stop, _balance, _version, _help _profit, _forcesell, _performance, _daily, _count, _start, _stop, _balance, _version, _help
def test_is_enabled(default_conf, mocker): def test_is_enabled(default_conf, mocker):
@ -316,7 +316,40 @@ def test_performance_handle(
assert 'Performance' in msg_mock.call_args_list[0][0][0] assert 'Performance' in msg_mock.call_args_list[0][0][0]
assert '<code>BTC_ETH\t10.05%</code>' in msg_mock.call_args_list[0][0][0] assert '<code>BTC_ETH\t10.05%</code>' in msg_mock.call_args_list[0][0][0]
def test_daily_handle(
default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
msg_mock = MagicMock()
mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
mocker.patch.multiple('freqtrade.rpc.telegram',
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker)
init(default_conf, create_engine('sqlite://'))
# Create some test data
create_trade(15.0)
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
_daily(bot=MagicMock(), update=update)
assert msg_mock.call_count == 1
assert 'Daily' in msg_mock.call_args_list[0][0][0]
assert str(date.today()) + '\t1.50701325 BTC' in msg_mock.call_args_list[0][0][0]
def test_count_handle(default_conf, update, ticker, mocker): def test_count_handle(default_conf, update, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)