Merge pull request #2628 from freqtrade/rpc/sell_duration

Telegram / sell duration
This commit is contained in:
Matthias 2019-12-11 07:15:00 +01:00 committed by GitHub
commit d8b2d39f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 14 deletions

View File

@ -63,6 +63,8 @@ Possible parameters are:
* `fiat_currency` * `fiat_currency`
* `sell_reason` * `sell_reason`
* `order_type` * `order_type`
* `open_date`
* `close_date`
### Webhookstatus ### Webhookstatus

View File

@ -962,7 +962,9 @@ class FreqtradeBot:
'current_rate': current_rate, 'current_rate': current_rate,
'profit_amount': profit_trade, 'profit_amount': profit_trade,
'profit_percent': profit_percent, 'profit_percent': profit_percent,
'sell_reason': trade.sell_reason 'sell_reason': trade.sell_reason,
'open_date': trade.open_date,
'close_date': trade.close_date or datetime.utcnow()
} }
# For regular case, when the configuration exists # For regular case, when the configuration exists

View File

@ -9,7 +9,7 @@ from typing import Any, Callable, Dict
from tabulate import tabulate from tabulate import tabulate
from telegram import ParseMode, ReplyKeyboardMarkup, Update from telegram import ParseMode, ReplyKeyboardMarkup, Update
from telegram.error import NetworkError, TelegramError from telegram.error import NetworkError, TelegramError
from telegram.ext import CommandHandler, Updater, CallbackContext from telegram.ext import CallbackContext, CommandHandler, Updater
from freqtrade.__init__ import __version__ from freqtrade.__init__ import __version__
from freqtrade.rpc import RPC, RPCException, RPCMessageType from freqtrade.rpc import RPC, RPCException, RPCMessageType
@ -144,6 +144,9 @@ class Telegram(RPC):
elif msg['type'] == RPCMessageType.SELL_NOTIFICATION: elif msg['type'] == RPCMessageType.SELL_NOTIFICATION:
msg['amount'] = round(msg['amount'], 8) msg['amount'] = round(msg['amount'], 8)
msg['profit_percent'] = round(msg['profit_percent'] * 100, 2) msg['profit_percent'] = round(msg['profit_percent'] * 100, 2)
msg['duration'] = msg['close_date'].replace(
microsecond=0) - msg['open_date'].replace(microsecond=0)
msg['duration_min'] = msg['duration'].total_seconds() / 60
message = ("*{exchange}:* Selling {pair}\n" message = ("*{exchange}:* Selling {pair}\n"
"*Rate:* `{limit:.8f}`\n" "*Rate:* `{limit:.8f}`\n"
@ -151,6 +154,7 @@ class Telegram(RPC):
"*Open Rate:* `{open_rate:.8f}`\n" "*Open Rate:* `{open_rate:.8f}`\n"
"*Current Rate:* `{current_rate:.8f}`\n" "*Current Rate:* `{current_rate:.8f}`\n"
"*Sell Reason:* `{sell_reason}`\n" "*Sell Reason:* `{sell_reason}`\n"
"*Duration:* `{duration} ({duration_min:.1f} min)`\n"
"*Profit:* `{profit_percent:.2f}%`").format(**msg) "*Profit:* `{profit_percent:.2f}%`").format(**msg)
# Check if all sell properties are available. # Check if all sell properties are available.

View File

@ -6,7 +6,7 @@ import re
from datetime import datetime from datetime import datetime
from random import choice, randint from random import choice, randint
from string import ascii_uppercase from string import ascii_uppercase
from unittest.mock import MagicMock, PropertyMock from unittest.mock import ANY, MagicMock, PropertyMock
import arrow import arrow
import pytest import pytest
@ -736,7 +736,9 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
'profit_percent': 0.0611052, 'profit_percent': 0.0611052,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.FORCE_SELL.value 'sell_reason': SellType.FORCE_SELL.value,
'open_date': ANY,
'close_date': ANY,
} == last_msg } == last_msg
@ -793,7 +795,9 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
'profit_percent': -0.05478342, 'profit_percent': -0.05478342,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.FORCE_SELL.value 'sell_reason': SellType.FORCE_SELL.value,
'open_date': ANY,
'close_date': ANY,
} == last_msg } == last_msg
@ -839,7 +843,9 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
'profit_percent': -0.00589291, 'profit_percent': -0.00589291,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.FORCE_SELL.value 'sell_reason': SellType.FORCE_SELL.value,
'open_date': ANY,
'close_date': ANY,
} == msg } == msg
@ -1224,7 +1230,9 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'profit_percent': -0.57405275, 'profit_percent': -0.57405275,
'stake_currency': 'ETH', 'stake_currency': 'ETH',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.STOP_LOSS.value 'sell_reason': SellType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(hours=-1),
'close_date': arrow.utcnow(),
}) })
assert msg_mock.call_args[0][0] \ assert msg_mock.call_args[0][0] \
== ('*Binance:* Selling KEY/ETH\n' == ('*Binance:* Selling KEY/ETH\n'
@ -1233,6 +1241,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'*Open Rate:* `0.00007500`\n' '*Open Rate:* `0.00007500`\n'
'*Current Rate:* `0.00003201`\n' '*Current Rate:* `0.00003201`\n'
'*Sell Reason:* `stop_loss`\n' '*Sell Reason:* `stop_loss`\n'
'*Duration:* `1:00:00 (60.0 min)`\n'
'*Profit:* `-57.41%`` (loss: -0.05746268 ETH`` / -24.812 USD)`') '*Profit:* `-57.41%`` (loss: -0.05746268 ETH`` / -24.812 USD)`')
msg_mock.reset_mock() msg_mock.reset_mock()
@ -1249,7 +1258,9 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'profit_amount': -0.05746268, 'profit_amount': -0.05746268,
'profit_percent': -0.57405275, 'profit_percent': -0.57405275,
'stake_currency': 'ETH', 'stake_currency': 'ETH',
'sell_reason': SellType.STOP_LOSS.value 'sell_reason': SellType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
'close_date': arrow.utcnow(),
}) })
assert msg_mock.call_args[0][0] \ assert msg_mock.call_args[0][0] \
== ('*Binance:* Selling KEY/ETH\n' == ('*Binance:* Selling KEY/ETH\n'
@ -1258,6 +1269,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'*Open Rate:* `0.00007500`\n' '*Open Rate:* `0.00007500`\n'
'*Current Rate:* `0.00003201`\n' '*Current Rate:* `0.00003201`\n'
'*Sell Reason:* `stop_loss`\n' '*Sell Reason:* `stop_loss`\n'
'*Duration:* `1 day, 2:30:00 (1590.0 min)`\n'
'*Profit:* `-57.41%`') '*Profit:* `-57.41%`')
# Reset singleton function to avoid random breaks # Reset singleton function to avoid random breaks
telegram._fiat_converter.convert_amount = old_convamount telegram._fiat_converter.convert_amount = old_convamount
@ -1377,7 +1389,9 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
'profit_percent': -0.57405275, 'profit_percent': -0.57405275,
'stake_currency': 'ETH', 'stake_currency': 'ETH',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.STOP_LOSS.value 'sell_reason': SellType.STOP_LOSS.value,
'open_date': arrow.utcnow().shift(hours=-2, minutes=-35, seconds=-3),
'close_date': arrow.utcnow(),
}) })
assert msg_mock.call_args[0][0] \ assert msg_mock.call_args[0][0] \
== '*Binance:* Selling KEY/ETH\n' \ == '*Binance:* Selling KEY/ETH\n' \
@ -1386,6 +1400,7 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
'*Open Rate:* `0.00007500`\n' \ '*Open Rate:* `0.00007500`\n' \
'*Current Rate:* `0.00003201`\n' \ '*Current Rate:* `0.00003201`\n' \
'*Sell Reason:* `stop_loss`\n' \ '*Sell Reason:* `stop_loss`\n' \
'*Duration:* `2:35:03 (155.1 min)`\n' \
'*Profit:* `-57.41%`' '*Profit:* `-57.41%`'

View File

@ -5,7 +5,7 @@ import logging
import time import time
from copy import deepcopy from copy import deepcopy
from math import isclose from math import isclose
from unittest.mock import MagicMock, PropertyMock from unittest.mock import ANY, MagicMock, PropertyMock
import arrow import arrow
import pytest import pytest
@ -2199,7 +2199,9 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> N
'profit_percent': 0.0611052, 'profit_percent': 0.0611052,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.ROI.value 'sell_reason': SellType.ROI.value,
'open_date': ANY,
'close_date': ANY,
} == last_msg } == last_msg
@ -2246,7 +2248,9 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker)
'profit_percent': -0.05478342, 'profit_percent': -0.05478342,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.STOP_LOSS.value 'sell_reason': SellType.STOP_LOSS.value,
'open_date': ANY,
'close_date': ANY,
} == last_msg } == last_msg
@ -2300,7 +2304,9 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
'profit_percent': -0.01493766, 'profit_percent': -0.01493766,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.STOP_LOSS.value 'sell_reason': SellType.STOP_LOSS.value,
'open_date': ANY,
'close_date': ANY,
} == last_msg } == last_msg
@ -2497,7 +2503,9 @@ def test_execute_sell_market_order(default_conf, ticker, fee,
'profit_percent': 0.0611052, 'profit_percent': 0.0611052,
'stake_currency': 'BTC', 'stake_currency': 'BTC',
'fiat_currency': 'USD', 'fiat_currency': 'USD',
'sell_reason': SellType.ROI.value 'sell_reason': SellType.ROI.value,
'open_date': ANY,
'close_date': ANY,
} == last_msg } == last_msg