Merge pull request #2628 from freqtrade/rpc/sell_duration
Telegram / sell duration
This commit is contained in:
commit
d8b2d39f2f
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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%`'
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user