Improve some telegram terminology
This commit is contained in:
parent
157f8f8139
commit
cd78792f48
@ -180,7 +180,9 @@ official commands. You can ask at any moment for help with `/help`.
|
|||||||
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)
|
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)
|
||||||
| `/weekly <n>` | Shows profit or loss per week, over the last n weeks (n defaults to 8)
|
| `/weekly <n>` | Shows profit or loss per week, over the last n weeks (n defaults to 8)
|
||||||
| `/monthly <n>` | Shows profit or loss per month, over the last n months (n defaults to 6)
|
| `/monthly <n>` | Shows profit or loss per month, over the last n months (n defaults to 6)
|
||||||
| `/stats` | Shows Wins / losses by Sell reason as well as Avg. holding durations for buys and sells
|
| `/stats` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells
|
||||||
|
| `/exits` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells
|
||||||
|
| `/entries` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells
|
||||||
| `/whitelist` | Show the current whitelist
|
| `/whitelist` | Show the current whitelist
|
||||||
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
|
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
|
||||||
| `/edge` | Show validated pairs by Edge if it is enabled.
|
| `/edge` | Show validated pairs by Edge if it is enabled.
|
||||||
|
@ -234,7 +234,7 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
|
|||||||
# Migrates both trades and orders table!
|
# Migrates both trades and orders table!
|
||||||
# if ('orders' not in previous_tables
|
# if ('orders' not in previous_tables
|
||||||
# or not has_column(cols_orders, 'leverage')):
|
# or not has_column(cols_orders, 'leverage')):
|
||||||
if not has_column(cols, 'liquidation_price'):
|
if not has_column(cols, 'exit_reason'):
|
||||||
logger.info(f"Running database migration for trades - "
|
logger.info(f"Running database migration for trades - "
|
||||||
f"backup: {table_back_name}, {order_table_bak_name}")
|
f"backup: {table_back_name}, {order_table_bak_name}")
|
||||||
migrate_trades_and_orders_table(
|
migrate_trades_and_orders_table(
|
||||||
|
@ -1289,7 +1289,7 @@ class Trade(_DECL_BASE, LocalTrade):
|
|||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_sell_reason_performance(pair: Optional[str]) -> List[Dict[str, Any]]:
|
def get_exit_reason_performance(pair: Optional[str]) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Returns List of dicts containing all Trades, based on sell reason performance
|
Returns List of dicts containing all Trades, based on sell reason performance
|
||||||
Can either be average for all pairs or a specific pair provided
|
Can either be average for all pairs or a specific pair provided
|
||||||
@ -1312,13 +1312,13 @@ class Trade(_DECL_BASE, LocalTrade):
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
'sell_reason': sell_reason if sell_reason is not None else "Other",
|
'exit_reason': exit_reason if exit_reason is not None else "Other",
|
||||||
'profit_ratio': profit,
|
'profit_ratio': profit,
|
||||||
'profit_pct': round(profit * 100, 2),
|
'profit_pct': round(profit * 100, 2),
|
||||||
'profit_abs': profit_abs,
|
'profit_abs': profit_abs,
|
||||||
'count': count
|
'count': count
|
||||||
}
|
}
|
||||||
for sell_reason, profit, profit_abs, count in sell_tag_perf
|
for exit_reason, profit, profit_abs, count in sell_tag_perf
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -848,12 +848,12 @@ class RPC:
|
|||||||
"""
|
"""
|
||||||
return Trade.get_enter_tag_performance(pair)
|
return Trade.get_enter_tag_performance(pair)
|
||||||
|
|
||||||
def _rpc_sell_reason_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]:
|
def _rpc_exit_reason_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Handler for sell reason performance.
|
Handler for sell reason performance.
|
||||||
Shows a performance statistic from finished trades
|
Shows a performance statistic from finished trades
|
||||||
"""
|
"""
|
||||||
return Trade.get_sell_reason_performance(pair)
|
return Trade.get_exit_reason_performance(pair)
|
||||||
|
|
||||||
def _rpc_mix_tag_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]:
|
def _rpc_mix_tag_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
|
@ -108,7 +108,8 @@ class Telegram(RPCHandler):
|
|||||||
# this needs refactoring of the whole telegram module (same
|
# this needs refactoring of the whole telegram module (same
|
||||||
# problem in _help()).
|
# problem in _help()).
|
||||||
valid_keys: List[str] = [r'/start$', r'/stop$', r'/status$', r'/status table$',
|
valid_keys: List[str] = [r'/start$', r'/stop$', r'/status$', r'/status table$',
|
||||||
r'/trades$', r'/performance$', r'/buys', r'/sells', r'/mix_tags',
|
r'/trades$', r'/performance$', r'/buys', r'/entries',
|
||||||
|
r'/sells', r'/exits', r'/mix_tags',
|
||||||
r'/daily$', r'/daily \d+$', r'/profit$', r'/profit \d+',
|
r'/daily$', r'/daily \d+$', r'/profit$', r'/profit \d+',
|
||||||
r'/stats$', r'/count$', r'/locks$', r'/balance$',
|
r'/stats$', r'/count$', r'/locks$', r'/balance$',
|
||||||
r'/stopbuy$', r'/reload_config$', r'/show_config$',
|
r'/stopbuy$', r'/reload_config$', r'/show_config$',
|
||||||
@ -161,7 +162,7 @@ class Telegram(RPCHandler):
|
|||||||
CommandHandler('delete', self._delete_trade),
|
CommandHandler('delete', self._delete_trade),
|
||||||
CommandHandler('performance', self._performance),
|
CommandHandler('performance', self._performance),
|
||||||
CommandHandler(['buys', 'entries'], self._enter_tag_performance),
|
CommandHandler(['buys', 'entries'], self._enter_tag_performance),
|
||||||
CommandHandler('sells', self._sell_reason_performance),
|
CommandHandler(['sells', 'exits'], self._exit_reason_performance),
|
||||||
CommandHandler('mix_tags', self._mix_tag_performance),
|
CommandHandler('mix_tags', self._mix_tag_performance),
|
||||||
CommandHandler('stats', self._stats),
|
CommandHandler('stats', self._stats),
|
||||||
CommandHandler('daily', self._daily),
|
CommandHandler('daily', self._daily),
|
||||||
@ -192,8 +193,8 @@ class Telegram(RPCHandler):
|
|||||||
CallbackQueryHandler(self._performance, pattern='update_performance'),
|
CallbackQueryHandler(self._performance, pattern='update_performance'),
|
||||||
CallbackQueryHandler(self._enter_tag_performance,
|
CallbackQueryHandler(self._enter_tag_performance,
|
||||||
pattern='update_enter_tag_performance'),
|
pattern='update_enter_tag_performance'),
|
||||||
CallbackQueryHandler(self._sell_reason_performance,
|
CallbackQueryHandler(self._exit_reason_performance,
|
||||||
pattern='update_sell_reason_performance'),
|
pattern='update_exit_reason_performance'),
|
||||||
CallbackQueryHandler(self._mix_tag_performance, pattern='update_mix_tag_performance'),
|
CallbackQueryHandler(self._mix_tag_performance, pattern='update_mix_tag_performance'),
|
||||||
CallbackQueryHandler(self._count, pattern='update_count'),
|
CallbackQueryHandler(self._count, pattern='update_count'),
|
||||||
CallbackQueryHandler(self._forceenter_inline),
|
CallbackQueryHandler(self._forceenter_inline),
|
||||||
@ -1101,7 +1102,7 @@ class Telegram(RPCHandler):
|
|||||||
pair = context.args[0]
|
pair = context.args[0]
|
||||||
|
|
||||||
trades = self._rpc._rpc_enter_tag_performance(pair)
|
trades = self._rpc._rpc_enter_tag_performance(pair)
|
||||||
output = "<b>Buy Tag Performance:</b>\n"
|
output = "<b>Entry Tag Performance:</b>\n"
|
||||||
for i, trade in enumerate(trades):
|
for i, trade in enumerate(trades):
|
||||||
stat_line = (
|
stat_line = (
|
||||||
f"{i+1}.\t <code>{trade['enter_tag']}\t"
|
f"{i+1}.\t <code>{trade['enter_tag']}\t"
|
||||||
@ -1122,7 +1123,7 @@ class Telegram(RPCHandler):
|
|||||||
self._send_msg(str(e))
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _sell_reason_performance(self, update: Update, context: CallbackContext) -> None:
|
def _exit_reason_performance(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /sells.
|
Handler for /sells.
|
||||||
Shows a performance statistic from finished trades
|
Shows a performance statistic from finished trades
|
||||||
@ -1135,11 +1136,11 @@ class Telegram(RPCHandler):
|
|||||||
if context.args and isinstance(context.args[0], str):
|
if context.args and isinstance(context.args[0], str):
|
||||||
pair = context.args[0]
|
pair = context.args[0]
|
||||||
|
|
||||||
trades = self._rpc._rpc_sell_reason_performance(pair)
|
trades = self._rpc._rpc_exit_reason_performance(pair)
|
||||||
output = "<b>Sell Reason Performance:</b>\n"
|
output = "<b>Exit Reason Performance:</b>\n"
|
||||||
for i, trade in enumerate(trades):
|
for i, trade in enumerate(trades):
|
||||||
stat_line = (
|
stat_line = (
|
||||||
f"{i+1}.\t <code>{trade['sell_reason']}\t"
|
f"{i+1}.\t <code>{trade['exit_reason']}\t"
|
||||||
f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} "
|
f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} "
|
||||||
f"({trade['profit_ratio']:.2%}) "
|
f"({trade['profit_ratio']:.2%}) "
|
||||||
f"({trade['count']})</code>\n")
|
f"({trade['count']})</code>\n")
|
||||||
@ -1151,7 +1152,7 @@ class Telegram(RPCHandler):
|
|||||||
output += stat_line
|
output += stat_line
|
||||||
|
|
||||||
self._send_msg(output, parse_mode=ParseMode.HTML,
|
self._send_msg(output, parse_mode=ParseMode.HTML,
|
||||||
reload_able=True, callback_path="update_sell_reason_performance",
|
reload_able=True, callback_path="update_exit_reason_performance",
|
||||||
query=update.callback_query)
|
query=update.callback_query)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e))
|
self._send_msg(str(e))
|
||||||
|
@ -1010,7 +1010,7 @@ def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee):
|
|||||||
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
||||||
|
|
||||||
|
|
||||||
def test_sell_reason_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
def test_exit_reason_performance_handle(default_conf, ticker, limit_buy_order, fee,
|
||||||
limit_sell_order, mocker) -> None:
|
limit_sell_order, mocker) -> None:
|
||||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
@ -1039,23 +1039,23 @@ def test_sell_reason_performance_handle(default_conf, ticker, limit_buy_order, f
|
|||||||
|
|
||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
res = rpc._rpc_sell_reason_performance(None)
|
res = rpc._rpc_exit_reason_performance(None)
|
||||||
|
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0]['sell_reason'] == 'Other'
|
assert res[0]['exit_reason'] == 'Other'
|
||||||
assert res[0]['count'] == 1
|
assert res[0]['count'] == 1
|
||||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||||
|
|
||||||
trade.exit_reason = "TEST1"
|
trade.exit_reason = "TEST1"
|
||||||
res = rpc._rpc_sell_reason_performance(None)
|
res = rpc._rpc_exit_reason_performance(None)
|
||||||
|
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0]['sell_reason'] == 'TEST1'
|
assert res[0]['exit_reason'] == 'TEST1'
|
||||||
assert res[0]['count'] == 1
|
assert res[0]['count'] == 1
|
||||||
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
assert prec_satoshi(res[0]['profit_pct'], 6.2)
|
||||||
|
|
||||||
|
|
||||||
def test_sell_reason_performance_handle_2(mocker, default_conf, markets, fee):
|
def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
|
||||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
@ -1066,21 +1066,21 @@ def test_sell_reason_performance_handle_2(mocker, default_conf, markets, fee):
|
|||||||
create_mock_trades(fee)
|
create_mock_trades(fee)
|
||||||
rpc = RPC(freqtradebot)
|
rpc = RPC(freqtradebot)
|
||||||
|
|
||||||
res = rpc._rpc_sell_reason_performance(None)
|
res = rpc._rpc_exit_reason_performance(None)
|
||||||
|
|
||||||
assert len(res) == 2
|
assert len(res) == 2
|
||||||
assert res[0]['sell_reason'] == 'sell_signal'
|
assert res[0]['exit_reason'] == 'sell_signal'
|
||||||
assert res[0]['count'] == 1
|
assert res[0]['count'] == 1
|
||||||
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
||||||
assert res[1]['sell_reason'] == 'roi'
|
assert res[1]['exit_reason'] == 'roi'
|
||||||
assert res[1]['count'] == 1
|
assert res[1]['count'] == 1
|
||||||
assert prec_satoshi(res[1]['profit_pct'], 1.0)
|
assert prec_satoshi(res[1]['profit_pct'], 1.0)
|
||||||
|
|
||||||
# Test for a specific pair
|
# Test for a specific pair
|
||||||
res = rpc._rpc_sell_reason_performance('ETC/BTC')
|
res = rpc._rpc_exit_reason_performance('ETC/BTC')
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0]['count'] == 1
|
assert res[0]['count'] == 1
|
||||||
assert res[0]['sell_reason'] == 'sell_signal'
|
assert res[0]['exit_reason'] == 'sell_signal'
|
||||||
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
assert prec_satoshi(res[0]['profit_pct'], 0.5)
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ def test_telegram_init(default_conf, mocker, caplog) -> None:
|
|||||||
"['balance'], ['start'], ['stop'], "
|
"['balance'], ['start'], ['stop'], "
|
||||||
"['forcesell', 'forceexit'], ['forcebuy', 'forcelong'], ['forceshort'], "
|
"['forcesell', 'forceexit'], ['forcebuy', 'forcelong'], ['forceshort'], "
|
||||||
"['trades'], ['delete'], ['performance'], "
|
"['trades'], ['delete'], ['performance'], "
|
||||||
"['buys', 'entries'], ['sells'], ['mix_tags'], "
|
"['buys', 'entries'], ['sells', 'exits'], ['mix_tags'], "
|
||||||
"['stats'], ['daily'], ['weekly'], ['monthly'], "
|
"['stats'], ['daily'], ['weekly'], ['monthly'], "
|
||||||
"['count'], ['locks'], ['unlock', 'delete_locks'], "
|
"['count'], ['locks'], ['unlock', 'delete_locks'], "
|
||||||
"['reload_config', 'reload_conf'], ['show_config', 'show_conf'], "
|
"['reload_config', 'reload_conf'], ['show_config', 'show_conf'], "
|
||||||
@ -1337,8 +1337,8 @@ def test_telegram_performance_handle(default_conf, update, ticker, fee,
|
|||||||
assert '<code>ETH/BTC\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
assert '<code>ETH/BTC\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
|
|
||||||
def test_telegram_buy_tag_performance_handle(default_conf, update, ticker, fee,
|
def test_telegram_entry_tag_performance_handle(
|
||||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
default_conf, update, ticker, fee, limit_buy_order, limit_sell_order, mocker) -> None:
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
fetch_ticker=ticker,
|
fetch_ticker=ticker,
|
||||||
@ -1366,7 +1366,7 @@ def test_telegram_buy_tag_performance_handle(default_conf, update, ticker, fee,
|
|||||||
context = MagicMock()
|
context = MagicMock()
|
||||||
telegram._enter_tag_performance(update=update, context=context)
|
telegram._enter_tag_performance(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Buy Tag Performance' in msg_mock.call_args_list[0][0][0]
|
assert 'Entry Tag Performance' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '<code>TESTBUY\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
assert '<code>TESTBUY\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
context.args = [trade.pair]
|
context.args = [trade.pair]
|
||||||
@ -1382,7 +1382,7 @@ def test_telegram_buy_tag_performance_handle(default_conf, update, ticker, fee,
|
|||||||
assert "Error" in msg_mock.call_args_list[0][0][0]
|
assert "Error" in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
|
|
||||||
def test_telegram_sell_reason_performance_handle(default_conf, update, ticker, fee,
|
def test_telegram_exit_reason_performance_handle(default_conf, update, ticker, fee,
|
||||||
limit_buy_order, limit_sell_order, mocker) -> None:
|
limit_buy_order, limit_sell_order, mocker) -> None:
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
@ -1408,19 +1408,19 @@ def test_telegram_sell_reason_performance_handle(default_conf, update, ticker, f
|
|||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
context = MagicMock()
|
context = MagicMock()
|
||||||
telegram._sell_reason_performance(update=update, context=context)
|
telegram._exit_reason_performance(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Sell Reason Performance' in msg_mock.call_args_list[0][0][0]
|
assert 'Exit Reason Performance' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '<code>TESTSELL\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
assert '<code>TESTSELL\t0.00006217 BTC (6.20%) (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||||
context.args = [trade.pair]
|
context.args = [trade.pair]
|
||||||
|
|
||||||
telegram._sell_reason_performance(update=update, context=context)
|
telegram._exit_reason_performance(update=update, context=context)
|
||||||
assert msg_mock.call_count == 2
|
assert msg_mock.call_count == 2
|
||||||
|
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_sell_reason_performance',
|
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_exit_reason_performance',
|
||||||
side_effect=RPCException('Error'))
|
side_effect=RPCException('Error'))
|
||||||
telegram._sell_reason_performance(update=update, context=MagicMock())
|
telegram._exit_reason_performance(update=update, context=MagicMock())
|
||||||
|
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert "Error" in msg_mock.call_args_list[0][0][0]
|
assert "Error" in msg_mock.call_args_list[0][0][0]
|
||||||
|
@ -2197,7 +2197,7 @@ def test_Trade_object_idem():
|
|||||||
'get_open_trades_without_assigned_fees',
|
'get_open_trades_without_assigned_fees',
|
||||||
'get_open_order_trades',
|
'get_open_order_trades',
|
||||||
'get_trades',
|
'get_trades',
|
||||||
'get_sell_reason_performance',
|
'get_exit_reason_performance',
|
||||||
'get_enter_tag_performance',
|
'get_enter_tag_performance',
|
||||||
'get_mix_tag_performance',
|
'get_mix_tag_performance',
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user