diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index 5a18a922a..6088dba72 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -213,6 +213,27 @@ class Trade(_DECL_BASE): return (f'Trade(id={self.id}, pair={self.pair}, amount={self.amount:.8f}, ' f'open_rate={self.open_rate:.8f}, open_since={open_since})') + def to_json(self) -> Dict[str, Any]: + return { + 'trade_id': self.id, + 'pair': self.pair, + 'open_date_hum': arrow.get(self.open_date).humanize(), + 'open_date': self.open_date.strftime("%Y-%m-%d %H:%M:%S"), + 'close_date_hum': (arrow.get(self.close_date).humanize() + if self.close_date else None), + 'close_date': (self.close_date.strftime("%Y-%m-%d %H:%M:%S") + if self.close_date else None), + 'open_rate': self.open_rate, + 'close_rate': self.close_rate, + 'amount': round(self.amount, 8), + 'stake_amount': round(self.stake_amount, 8), + 'stop_loss': self.stop_loss, + 'stop_loss_pct': (self.stop_loss_pct * 100) if self.stop_loss_pct else None, + 'initial_stop_loss': self.initial_stop_loss, + 'initial_stop_loss_pct': (self.initial_stop_loss_pct * 100 + if self.initial_stop_loss_pct else None), + } + def adjust_min_max_rates(self, current_price: float): """ Adjust the max_rate and min_rate. diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index af384da45..37312318a 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -100,28 +100,17 @@ class RPC(object): current_profit = trade.calc_profit_percent(current_rate) fmt_close_profit = (f'{round(trade.close_profit * 100, 2):.2f}%' if trade.close_profit else None) - results.append(dict( - trade_id=trade.id, - pair=trade.pair, + trade_dict = trade.to_json() + trade_dict.update(dict( base_currency=self._freqtrade.config['stake_currency'], - date=arrow.get(trade.open_date), - open_rate=trade.open_rate, - close_rate=trade.close_rate, - current_rate=current_rate, - amount=round(trade.amount, 8), - stake_amount=round(trade.stake_amount, 8), close_profit=fmt_close_profit, + current_rate=current_rate, current_profit=round(current_profit * 100, 2), - stop_loss=trade.stop_loss, - stop_loss_pct=(trade.stop_loss_pct * 100) - if trade.stop_loss_pct else None, - initial_stop_loss=trade.initial_stop_loss, - initial_stop_loss_pct=(trade.initial_stop_loss_pct * 100) - if trade.initial_stop_loss_pct else None, open_order='({} {} rem={:.8f})'.format( order['type'], order['side'], order['remaining'] ) if order else None, )) + results.append(trade_dict) return results def _rpc_status_table(self) -> DataFrame: diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index dc0bad2b2..497c117ac 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -193,14 +193,11 @@ class Telegram(RPC): try: results = self._rpc_trade_status() - # pre format data - for result in results: - result['date'] = result['date'].humanize() messages = [] for r in results: lines = [ - "*Trade ID:* `{trade_id}` `(since {date})`", + "*Trade ID:* `{trade_id}` `(since {open_date_hum})`", "*Current Pair:* {pair}", "*Amount:* `{amount} ({stake_amount} {base_currency})`", "*Open Rate:* `{open_rate:.8f}`", diff --git a/freqtrade/tests/rpc/test_rpc.py b/freqtrade/tests/rpc/test_rpc.py index 93de6ef89..6ce543f3d 100644 --- a/freqtrade/tests/rpc/test_rpc.py +++ b/freqtrade/tests/rpc/test_rpc.py @@ -47,12 +47,14 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None: freqtradebot.create_trade() results = rpc._rpc_trade_status() - assert { 'trade_id': 1, 'pair': 'ETH/BTC', 'base_currency': 'BTC', - 'date': ANY, + 'open_date': ANY, + 'open_date_hum': ANY, + 'close_date': None, + 'close_date_hum': None, 'open_rate': 1.099e-05, 'close_rate': None, 'current_rate': 1.098e-05, @@ -78,7 +80,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None: 'trade_id': 1, 'pair': 'ETH/BTC', 'base_currency': 'BTC', - 'date': ANY, + 'open_date': ANY, + 'open_date_hum': ANY, + 'close_date': None, + 'close_date_hum': None, 'open_rate': 1.099e-05, 'close_rate': None, 'current_rate': ANY, diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py index f2f3f3945..86d728290 100644 --- a/freqtrade/tests/rpc/test_rpc_telegram.py +++ b/freqtrade/tests/rpc/test_rpc_telegram.py @@ -192,7 +192,10 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None: 'trade_id': 1, 'pair': 'ETH/BTC', 'base_currency': 'BTC', - 'date': arrow.utcnow(), + 'open_date': arrow.utcnow(), + 'open_date_hum': arrow.utcnow().humanize, + 'close_date': None, + 'close_date_hum': None, 'open_rate': 1.099e-05, 'close_rate': None, 'current_rate': 1.098e-05, diff --git a/freqtrade/tests/test_persistence.py b/freqtrade/tests/test_persistence.py index f57a466e3..8c15fa8e8 100644 --- a/freqtrade/tests/test_persistence.py +++ b/freqtrade/tests/test_persistence.py @@ -1,7 +1,8 @@ # pragma pylint: disable=missing-docstring, C0103 -from unittest.mock import MagicMock import logging +from unittest.mock import MagicMock +import arrow import pytest from sqlalchemy import create_engine @@ -710,3 +711,69 @@ def test_get_open(default_conf, fee): Trade.session.add(trade) assert len(Trade.get_open_trades()) == 2 + + +def test_to_json(default_conf, fee): + init(default_conf) + + # Simulate dry_run entries + trade = Trade( + pair='ETH/BTC', + stake_amount=0.001, + amount=123.0, + fee_open=fee.return_value, + fee_close=fee.return_value, + open_date=arrow.utcnow().shift(hours=-2).datetime, + open_rate=0.123, + exchange='bittrex', + open_order_id='dry_run_buy_12345' + ) + result = trade.to_json() + assert isinstance(result, dict) + print(result) + + assert result == {'trade_id': None, + 'pair': 'ETH/BTC', + 'open_date_hum': '2 hours ago', + 'open_date': trade.open_date.strftime("%Y-%m-%d %H:%M:%S"), + 'close_date_hum': None, + 'close_date': None, + 'open_rate': 0.123, + 'close_rate': None, + 'amount': 123.0, + 'stake_amount': 0.001, + 'stop_loss': None, + 'stop_loss_pct': None, + 'initial_stop_loss': None, + 'initial_stop_loss_pct': None} + + # Simulate dry_run entries + trade = Trade( + pair='XRP/BTC', + stake_amount=0.001, + amount=100.0, + fee_open=fee.return_value, + fee_close=fee.return_value, + open_date=arrow.utcnow().shift(hours=-2).datetime, + close_date=arrow.utcnow().shift(hours=-1).datetime, + open_rate=0.123, + close_rate=0.125, + exchange='bittrex', + ) + result = trade.to_json() + assert isinstance(result, dict) + + assert result == {'trade_id': None, + 'pair': 'XRP/BTC', + 'open_date_hum': '2 hours ago', + 'open_date': trade.open_date.strftime("%Y-%m-%d %H:%M:%S"), + 'close_date_hum': 'an hour ago', + 'close_date': trade.close_date.strftime("%Y-%m-%d %H:%M:%S"), + 'open_rate': 0.123, + 'close_rate': 0.125, + 'amount': 100.0, + 'stake_amount': 0.001, + 'stop_loss': None, + 'stop_loss_pct': None, + 'initial_stop_loss': None, + 'initial_stop_loss_pct': None}