implement /performance command
This commit is contained in:
parent
53e71e09f7
commit
0fc46378fc
3
main.py
3
main.py
@ -25,7 +25,7 @@ from utils import get_conf
|
|||||||
__author__ = "gcarq"
|
__author__ = "gcarq"
|
||||||
__copyright__ = "gcarq 2017"
|
__copyright__ = "gcarq 2017"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
__version__ = "0.7.0"
|
__version__ = "0.8.0"
|
||||||
|
|
||||||
|
|
||||||
conf = get_conf()
|
conf = get_conf()
|
||||||
@ -131,6 +131,7 @@ def close_trade_if_fulfilled(trade):
|
|||||||
# we can close this trade.
|
# we can close this trade.
|
||||||
if trade.close_profit and trade.close_date and trade.close_rate and not trade.open_order_id:
|
if trade.close_profit and trade.close_date and trade.close_rate and not trade.open_order_id:
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
|
Session.flush()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import logging
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_, func
|
||||||
from telegram.error import NetworkError
|
from telegram.error import NetworkError
|
||||||
from telegram.ext import CommandHandler, Updater
|
from telegram.ext import CommandHandler, Updater
|
||||||
from telegram import ParseMode, Bot, Update
|
from telegram import ParseMode, Bot, Update
|
||||||
@ -105,31 +105,46 @@ class TelegramHandler(object):
|
|||||||
:param update: message update
|
:param update: message update
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
trades = Trade.query.filter(Trade.is_open.is_(False)).all()
|
trades = Trade.query.order_by(Trade.id).all()
|
||||||
trade_count = len(trades)
|
|
||||||
profit_amount = sum((t.close_profit / 100) * t.btc_amount for t in trades)
|
profit_amounts = []
|
||||||
profit = sum(t.close_profit for t in trades)
|
profits = []
|
||||||
if trades:
|
durations = []
|
||||||
avg_stake_amount = round(sum(t.btc_amount for t in trades) / float(trade_count), 8)
|
for trade in trades:
|
||||||
else:
|
if trade.close_date:
|
||||||
avg_stake_amount = None
|
durations.append((trade.close_date - trade.open_date).total_seconds())
|
||||||
durations_hours = [(t.close_date - t.open_date).total_seconds() / 3600.0 for t in trades]
|
if trade.close_profit:
|
||||||
avg_duration = sum(durations_hours) / float(len(durations_hours))
|
profit = trade.close_profit
|
||||||
|
else:
|
||||||
|
# Get current rate
|
||||||
|
current_rate = api_wrapper.get_ticker(trade.pair)['bid']
|
||||||
|
profit = 100 * ((current_rate - trade.open_rate) / trade.open_rate)
|
||||||
|
|
||||||
|
profit_amounts.append((profit / 100) * trade.btc_amount)
|
||||||
|
profits.append(profit)
|
||||||
|
|
||||||
|
bp_pair, bp_rate = Session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
|
||||||
|
.filter(Trade.is_open.is_(False)) \
|
||||||
|
.group_by(Trade.pair) \
|
||||||
|
.order_by('profit_sum DESC') \
|
||||||
|
.first()
|
||||||
|
|
||||||
markdown_msg = """
|
markdown_msg = """
|
||||||
*ROI:* `{profit_btc} ({profit}%)`
|
*ROI:* `{profit_btc} ({profit}%)`
|
||||||
*Trade Count:* `{trade_count}`
|
*Trade Count:* `{trade_count}`
|
||||||
*First Trade completed:* `{first_trade_date}`
|
*First Trade opened:* `{first_trade_date}`
|
||||||
*Latest Trade completed:* `{latest_trade_date}`
|
*Latest Trade opened:* `{latest_trade_date}`
|
||||||
*Avg. Stake Amount:* `{avg_stake_amount}`
|
*Avg. Duration:* `{avg_duration}`
|
||||||
*Avg. Duration:* `{avg_duration}`
|
*Best Performing:* `{best_pair}: {best_rate}%`
|
||||||
""".format(
|
""".format(
|
||||||
profit_btc=round(profit_amount, 8),
|
profit_btc=round(sum(profit_amounts), 8),
|
||||||
profit=round(profit, 2),
|
profit=round(sum(profits), 2),
|
||||||
trade_count=trade_count,
|
trade_count=len(trades),
|
||||||
first_trade_date=arrow.get(trades[0].open_date).humanize(),
|
first_trade_date=arrow.get(trades[0].open_date).humanize(),
|
||||||
latest_trade_date=arrow.get(trades[-1].open_date).humanize(),
|
latest_trade_date=arrow.get(trades[-1].open_date).humanize(),
|
||||||
avg_stake_amount=avg_stake_amount,
|
avg_duration=str(timedelta(seconds=sum(durations) / float(len(durations)))).split('.')[0],
|
||||||
avg_duration=str(timedelta(hours=avg_duration)).split('.')[0],
|
best_pair=bp_pair,
|
||||||
|
best_rate=round(bp_rate, 2),
|
||||||
)
|
)
|
||||||
TelegramHandler.send_msg(markdown_msg, bot=bot)
|
TelegramHandler.send_msg(markdown_msg, bot=bot)
|
||||||
|
|
||||||
@ -214,6 +229,33 @@ class TelegramHandler(object):
|
|||||||
TelegramHandler.send_msg('Invalid argument. Usage: `/forcesell <trade_id>`')
|
TelegramHandler.send_msg('Invalid argument. Usage: `/forcesell <trade_id>`')
|
||||||
logger.warning('/forcesell: Invalid argument received')
|
logger.warning('/forcesell: Invalid argument received')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@authorized_only
|
||||||
|
def _performance(bot, update):
|
||||||
|
"""
|
||||||
|
Handler for /performance.
|
||||||
|
Shows a performance statistic from finished trades
|
||||||
|
:param bot: telegram bot
|
||||||
|
:param update: message update
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
from main import get_instance
|
||||||
|
if not get_instance().is_alive():
|
||||||
|
TelegramHandler.send_msg('`trader is not running`', bot=bot)
|
||||||
|
return
|
||||||
|
|
||||||
|
pair_rates = Session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
|
||||||
|
.filter(Trade.is_open.is_(False)) \
|
||||||
|
.group_by(Trade.pair) \
|
||||||
|
.order_by('profit_sum DESC') \
|
||||||
|
.all()
|
||||||
|
|
||||||
|
stats = '\n'.join('{}. <code>{}\t{}%</code>'.format(i + 1, pair, round(rate, 2)) for i, (pair, rate) in enumerate(pair_rates))
|
||||||
|
|
||||||
|
message = '<b>Performance:</b>\n{}\n'.format(stats)
|
||||||
|
logger.debug(message)
|
||||||
|
TelegramHandler.send_msg(message, parse_mode=ParseMode.HTML)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@synchronized
|
@synchronized
|
||||||
def get_updater(conf):
|
def get_updater(conf):
|
||||||
@ -240,6 +282,7 @@ class TelegramHandler(object):
|
|||||||
CommandHandler('start', TelegramHandler._start),
|
CommandHandler('start', TelegramHandler._start),
|
||||||
CommandHandler('stop', TelegramHandler._stop),
|
CommandHandler('stop', TelegramHandler._stop),
|
||||||
CommandHandler('forcesell', TelegramHandler._forcesell),
|
CommandHandler('forcesell', TelegramHandler._forcesell),
|
||||||
|
CommandHandler('performance', TelegramHandler._performance),
|
||||||
]
|
]
|
||||||
for handle in handles:
|
for handle in handles:
|
||||||
TelegramHandler.get_updater(conf).dispatcher.add_handler(handle)
|
TelegramHandler.get_updater(conf).dispatcher.add_handler(handle)
|
||||||
|
Loading…
Reference in New Issue
Block a user