From b7a648753387ed491ef5f6bcb321f8b6993e6295 Mon Sep 17 00:00:00 2001 From: kryofly Date: Wed, 17 Jan 2018 07:23:25 +0100 Subject: [PATCH] telegram refactor 2/ move out rpc_trade_status --- freqtrade/rpc/__init__.py | 49 +++++++++++++++++++++++++++++++++ freqtrade/rpc/telegram.py | 47 ++++--------------------------- freqtrade/tests/rpc/test_rpc.py | 33 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 42 deletions(-) diff --git a/freqtrade/rpc/__init__.py b/freqtrade/rpc/__init__.py index 6981aa350..6f1bea53f 100644 --- a/freqtrade/rpc/__init__.py +++ b/freqtrade/rpc/__init__.py @@ -67,6 +67,55 @@ def shorten_date(_date): # a remotely exposed function +def rpc_trade_status(): + # Fetch open trade + trades = Trade.query.filter(Trade.is_open.is_(True)).all() + if get_state() != State.RUNNING: + return (True, '*Status:* `trader is not running`') + elif not trades: + return (True, '*Status:* `no active trade`') + else: + result = [] + for trade in trades: + order = None + if trade.open_order_id: + order = exchange.get_order(trade.open_order_id) + # calculate profit and send message to user + current_rate = exchange.get_ticker(trade.pair, False)['bid'] + current_profit = trade.calc_profit_percent(current_rate) + fmt_close_profit = '{:.2f}%'.format( + round(trade.close_profit * 100, 2) + ) if trade.close_profit else None + message = """ +*Trade ID:* `{trade_id}` +*Current Pair:* [{pair}]({market_url}) +*Open Since:* `{date}` +*Amount:* `{amount}` +*Open Rate:* `{open_rate:.8f}` +*Close Rate:* `{close_rate}` +*Current Rate:* `{current_rate:.8f}` +*Close Profit:* `{close_profit}` +*Current Profit:* `{current_profit:.2f}%` +*Open Order:* `{open_order}` + """.format( + trade_id=trade.id, + pair=trade.pair, + market_url=exchange.get_pair_detail_url(trade.pair), + date=arrow.get(trade.open_date).humanize(), + open_rate=trade.open_rate, + close_rate=trade.close_rate, + current_rate=current_rate, + amount=round(trade.amount, 8), + close_profit=fmt_close_profit, + current_profit=round(current_profit * 100, 2), + open_order='({} rem={:.8f})'.format( + order['type'], order['remaining'] + ) if order else None, + ) + result.append(message) + return (False, result) + + def rpc_status_table(): trades = Trade.query.filter(Trade.is_open.is_(True)).all() if get_state() != State.RUNNING: diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index f393416c0..d15f971c2 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -10,7 +10,7 @@ from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update from telegram.error import NetworkError, TelegramError from telegram.ext import CommandHandler, Updater -from freqtrade.rpc.__init__ import rpc_status_table +from freqtrade.rpc.__init__ import rpc_status_table, rpc_trade_status from freqtrade import __version__, exchange from freqtrade.fiat_convert import CryptoToFiatConverter from freqtrade.misc import State, get_state, update_state @@ -129,48 +129,11 @@ def _status(bot: Bot, update: Update) -> None: return # Fetch open trade - trades = Trade.query.filter(Trade.is_open.is_(True)).all() - if get_state() != State.RUNNING: - send_msg('*Status:* `trader is not running`', bot=bot) - elif not trades: - send_msg('*Status:* `no active trade`', bot=bot) + (error, trades) = rpc_trade_status() + if error: + send_msg(trades, bot=bot) else: - for trade in trades: - order = None - if trade.open_order_id: - order = exchange.get_order(trade.open_order_id) - # calculate profit and send message to user - current_rate = exchange.get_ticker(trade.pair, False)['bid'] - current_profit = trade.calc_profit_percent(current_rate) - fmt_close_profit = '{:.2f}%'.format( - round(trade.close_profit * 100, 2) - ) if trade.close_profit else None - message = """ -*Trade ID:* `{trade_id}` -*Current Pair:* [{pair}]({market_url}) -*Open Since:* `{date}` -*Amount:* `{amount}` -*Open Rate:* `{open_rate:.8f}` -*Close Rate:* `{close_rate}` -*Current Rate:* `{current_rate:.8f}` -*Close Profit:* `{close_profit}` -*Current Profit:* `{current_profit:.2f}%` -*Open Order:* `{open_order}` - """.format( - trade_id=trade.id, - pair=trade.pair, - market_url=exchange.get_pair_detail_url(trade.pair), - date=arrow.get(trade.open_date).humanize(), - open_rate=trade.open_rate, - close_rate=trade.close_rate, - current_rate=current_rate, - amount=round(trade.amount, 8), - close_profit=fmt_close_profit, - current_profit=round(current_profit * 100, 2), - open_order='({} rem={:.8f})'.format( - order['type'], order['remaining'] - ) if order else None, - ) + for message in trades: send_msg(message, bot=bot) diff --git a/freqtrade/tests/rpc/test_rpc.py b/freqtrade/tests/rpc/test_rpc.py index 9235cc674..a8d00551d 100644 --- a/freqtrade/tests/rpc/test_rpc.py +++ b/freqtrade/tests/rpc/test_rpc.py @@ -3,6 +3,10 @@ from copy import deepcopy from unittest.mock import MagicMock from freqtrade.rpc import init, cleanup, send_msg +from sqlalchemy import create_engine +import freqtrade.main as main +import freqtrade.misc as misc +import freqtrade.rpc as rpc def test_init_telegram_enabled(default_conf, mocker): @@ -55,3 +59,32 @@ def test_send_msg_telegram_disabled(mocker): telegram_mock = mocker.patch('freqtrade.rpc.telegram.send_msg', MagicMock()) send_msg('test') assert telegram_mock.call_count == 0 + + +def test_rpc_trade_status(default_conf, update, ticker, mocker): + mocker.patch.dict('freqtrade.main._CONF', default_conf) + mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True) + mocker.patch('freqtrade.main.rpc.send_msg', MagicMock()) + mocker.patch.multiple('freqtrade.rpc.telegram', + _CONF=default_conf, + init=MagicMock()) + mocker.patch.multiple('freqtrade.main.exchange', + validate_pairs=MagicMock(), + get_ticker=ticker) + main.init(default_conf, create_engine('sqlite://')) + + misc.update_state(misc.State.STOPPED) + (error, result) = rpc.rpc_trade_status() + assert error + assert result.find('trader is not running') >= 0 + + misc.update_state(misc.State.RUNNING) + (error, result) = rpc.rpc_trade_status() + assert error + assert result.find('no active trade') >= 0 + + main.create_trade(0.001) + (error, result) = rpc.rpc_trade_status() + assert not error + trade = result[0] + assert trade.find('[BTC_ETH]') >= 0