Refactor most of the logic to rpc.py

this way /stats can be used by other RPC methods too
This commit is contained in:
Matthias 2020-12-05 14:38:42 +01:00
parent c556d1b37e
commit 143423145c
2 changed files with 54 additions and 36 deletions

View File

@ -276,8 +276,37 @@ class RPC:
} }
def _rpc_stats(self): def _rpc_stats(self):
"""
Generate generic stats for trades in database
"""
def trade_win_loss(trade):
if trade.close_profit_abs > 0:
return 'Wins'
elif trade.close_profit_abs < 0:
return 'Losses'
else:
return 'Draws'
trades = trades = Trade.get_trades([Trade.is_open.is_(False)]) trades = trades = Trade.get_trades([Trade.is_open.is_(False)])
return trades # Sell reason
sell_reasons = {}
for trade in trades:
if trade.sell_reason not in sell_reasons:
sell_reasons[trade.sell_reason] = {'Wins': 0, 'Losses': 0, 'Draws': 0}
sell_reasons[trade.sell_reason][trade_win_loss(trade)] += 1
# Duration
dur: Dict[str, List[int]] = {'Wins': [], 'Draws': [], 'Losses': []}
for trade in trades:
if trade.close_date is not None and trade.open_date is not None:
trade_dur = (trade.close_date - trade.open_date).total_seconds()
dur[trade_win_loss(trade)].append(trade_dur)
wins_dur = sum(dur['Wins']) / len(dur['Wins']) if len(dur['Wins']) > 0 else 'N/A'
draws_dur = sum(dur['Draws']) / len(dur['Draws']) if len(dur['Draws']) > 0 else 'N/A'
losses_dur = sum(dur['Losses']) / len(dur['Losses']) if len(dur['Losses']) > 0 else 'N/A'
durations = {'wins': wins_dur, 'draws': draws_dur, 'losses': losses_dur}
return sell_reasons, durations
def _rpc_trade_statistics( def _rpc_trade_statistics(
self, stake_currency: str, fiat_display_currency: str) -> Dict[str, Any]: self, stake_currency: str, fiat_display_currency: str) -> Dict[str, Any]:

View File

@ -3,6 +3,7 @@
""" """
This module manage Telegram communication This module manage Telegram communication
""" """
from datetime import timedelta
import json import json
import logging import logging
from typing import Any, Callable, Dict, List, Union from typing import Any, Callable, Dict, List, Union
@ -775,56 +776,44 @@ class Telegram(RPC):
def _stats(self, update: Update, context: CallbackContext) -> None: def _stats(self, update: Update, context: CallbackContext) -> None:
""" """
Handler for /stats Handler for /stats
https://github.com/freqtrade/freqtrade/issues/3783
Show stats of recent trades Show stats of recent trades
:param update: message update
:return: None :return: None
""" """
# TODO: self._send_msg(...) sell_reasons, durations = self._rpc_stats()
def trade_win_loss(trade):
if trade.close_profit_abs > 0:
return 'Wins'
elif trade.close_profit_abs < 0:
return 'Losses'
else:
return 'Draws'
trades = self._rpc_stats()
trades_closed = [trade for trade in trades if not trade.is_open]
# Sell reason
sell_reasons = {}
for trade in trades_closed:
if trade.sell_reason not in sell_reasons:
sell_reasons[trade.sell_reason] = {'Wins': 0, 'Losses': 0, 'Draws': 0}
sell_reasons[trade.sell_reason][trade_win_loss(trade)] += 1
sell_reasons_tabulate = [] sell_reasons_tabulate = []
reason_map = {
'roi': 'ROI',
'stop_loss': 'Stoploss',
'trailing_stop_loss': 'Trail. Stop',
'stoploss_on_exchange': 'Stoploss',
'sell_signal': 'Sell Signal',
'force_sell': 'Forcesell',
'emergency_sell': 'Emergency Sell',
}
for reason, count in sell_reasons.items(): for reason, count in sell_reasons.items():
sell_reasons_tabulate.append([ sell_reasons_tabulate.append([
reason, sum(count.values()), reason_map.get(reason, reason),
sum(count.values()),
count['Wins'], count['Wins'],
count['Draws'], # count['Draws'],
count['Losses'] count['Losses']
]) ])
sell_reasons_msg = tabulate( sell_reasons_msg = tabulate(
sell_reasons_tabulate, sell_reasons_tabulate,
headers=['Sell Reason', 'Sells', 'Wins', 'Draws', 'Losses'] headers=['Sell Reason', 'Sells', 'Wins', 'Losses']
) )
# Duration duration_msg = tabulate([
dur: Dict[str, List[int]] = {'Wins': [], 'Draws': [], 'Losses': []} ['Wins', str(timedelta(seconds=durations['wins']))
for trade in trades_closed: if durations['wins'] != 'N/A' else 'N/A'],
if trade.close_date is not None and trade.open_date is not None: # ['Draws', str(timedelta(seconds=durations['draws']))],
trade_dur = (trade.close_date - trade.open_date).total_seconds() ['Losses', str(timedelta(seconds=durations['losses']))
dur[trade_win_loss(trade)].append(trade_dur) if durations['losses'] != 'N/A' else 'N/A']
wins_dur = sum(dur['Wins']) / len(dur['Wins']) if len(dur['Wins']) > 0 else 'N/A' ],
draws_dur = sum(dur['Draws']) / len(dur['Draws']) if len(dur['Draws']) > 0 else 'N/A' headers=['', 'Avg. Duration']
losses_dur = sum(dur['Losses']) / len(dur['Losses']) if len(dur['Losses']) > 0 else 'N/A'
duration_msg = tabulate(
[['Wins', str(wins_dur)], ['Draws', str(draws_dur)], ['Losses', str(losses_dur)]],
headers=['', 'Duration']
) )
msg = (f"""```{sell_reasons_msg}```\n```{duration_msg}```""") msg = (f"""```\n{sell_reasons_msg}```\n```\n{duration_msg}```""")
self._send_msg(msg, ParseMode.MARKDOWN) self._send_msg(msg, ParseMode.MARKDOWN)