Make Pylint Happy chapter 1

This commit is contained in:
Gerald Lonlas
2018-03-02 23:22:00 +08:00
parent d274f13480
commit 390501bac0
13 changed files with 161 additions and 147 deletions

View File

@@ -2,9 +2,9 @@
This module contains class to define a RPC communications
"""
import arrow
from decimal import Decimal
from datetime import datetime, timedelta
import arrow
from pandas import DataFrame
import sqlalchemy as sql
from freqtrade.logger import Logger
@@ -18,7 +18,6 @@ class RPC(object):
"""
RPC class can be used to have extra feature, like bot data, and access to DB data
"""
def __init__(self, freqtrade) -> None:
"""
Initializes all enabled rpc modules
@@ -65,21 +64,21 @@ class RPC(object):
"*Close Profit:* `{close_profit}`\n" \
"*Current Profit:* `{current_profit:.2f}%`\n" \
"*Open Order:* `{open_order}`"\
.format(
trade_id=trade.id,
pair=trade.pair,
market_url=exchange.get_pair_detail_url(trade.pair),
date=arrow.get(trade.open_date).humanize(),
open_rate=trade.open_rate,
close_rate=trade.close_rate,
current_rate=current_rate,
amount=round(trade.amount, 8),
close_profit=fmt_close_profit,
current_profit=round(current_profit * 100, 2),
open_order='({} rem={:.8f})'.format(
order['type'], order['remaining']
) if order else None,
)
.format(
trade_id=trade.id,
pair=trade.pair,
market_url=exchange.get_pair_detail_url(trade.pair),
date=arrow.get(trade.open_date).humanize(),
open_rate=trade.open_rate,
close_rate=trade.close_rate,
current_rate=current_rate,
amount=round(trade.amount, 8),
close_profit=fmt_close_profit,
current_profit=round(current_profit * 100, 2),
open_order='({} rem={:.8f})'.format(
order['type'], order['remaining']
) if order else None,
)
result.append(message)
return (False, result)
@@ -100,7 +99,7 @@ class RPC(object):
shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)),
'{:.2f}%'.format(100 * trade.calc_profit_percent(current_rate))
])
columns = ['ID', 'Pair', 'Since', 'Profit']
df_statuses = DataFrame.from_records(trades_list, columns=columns)
df_statuses = df_statuses.set_index(columns[0])
@@ -113,10 +112,10 @@ class RPC(object):
def rpc_daily_profit(self, timescale, stake_currency, fiat_display_currency):
today = datetime.utcnow().date()
profit_days = {}
if not (isinstance(timescale, int) and timescale > 0):
return (True, '*Daily [n]:* `must be an integer greater than 0`')
fiat = self.freqtrade.fiat_converter
for day in range(0, timescale):
profitday = today - timedelta(days=day)
@@ -131,7 +130,7 @@ class RPC(object):
'amount': format(curdayprofit, '.8f'),
'trades': len(trades)
}
stats = [
[
key,
@@ -147,7 +146,10 @@ class RPC(object):
),
symbol=fiat_display_currency
),
'{value} trade{s}'.format(value=value['trades'], s='' if value['trades'] < 2 else 's'),
'{value} trade{s}'.format(
value=value['trades'],
s='' if value['trades'] < 2 else 's'
),
]
for key, value in profit_days.items()
]
@@ -158,21 +160,21 @@ class RPC(object):
:return: cumulative profit statistics.
"""
trades = Trade.query.order_by(Trade.id).all()
profit_all_coin = []
profit_all_percent = []
profit_closed_coin = []
profit_closed_percent = []
durations = []
for trade in trades:
current_rate = None
if not trade.open_rate:
continue
if trade.close_date:
durations.append((trade.close_date - trade.open_date).total_seconds())
if not trade.is_open:
profit_percent = trade.calc_profit_percent()
profit_closed_coin.append(trade.calc_profit())
@@ -181,22 +183,25 @@ class RPC(object):
# Get current rate
current_rate = exchange.get_ticker(trade.pair, False)['bid']
profit_percent = trade.calc_profit_percent(rate=current_rate)
profit_all_coin.append(trade.calc_profit(rate=Decimal(trade.close_rate or current_rate)))
profit_all_coin.append(
trade.calc_profit(rate=Decimal(trade.close_rate or current_rate))
)
profit_all_percent.append(profit_percent)
best_pair = Trade.session.query(Trade.pair,
sql.func.sum(Trade.close_profit).label('profit_sum')) \
.filter(Trade.is_open.is_(False)) \
.group_by(Trade.pair) \
.order_by(sql.text('profit_sum DESC')) \
.first()
best_pair = Trade.session.query(
Trade.pair,
sql.func.sum(Trade.close_profit).label('profit_sum')
)\
.filter(Trade.is_open.is_(False))\
.group_by(Trade.pair)\
.order_by(sql.text('profit_sum DESC')).first()
if not best_pair:
return (True, '*Status:* `no closed trade`')
bp_pair, bp_rate = best_pair
# FIX: we want to keep fiatconverter in a state/environment,
# doing this will utilize its caching functionallity, instead we reinitialize it here
fiat = self.freqtrade.fiat_converter
@@ -244,7 +249,7 @@ class RPC(object):
]
if not balances:
return (True, '`All balances are zero.`')
output = []
total = 0.0
for currency in balances:
@@ -258,12 +263,15 @@ class RPC(object):
currency["Rate"] = exchange.get_ticker('BTC_' + coin, False)['bid']
currency['BTC'] = currency["Rate"] * currency["Balance"]
total = total + currency['BTC']
output.append({'currency': currency['Currency'],
'available': currency['Available'],
'balance': currency['Balance'],
'pending': currency['Pending'],
'est_btc': currency['BTC']
})
output.append(
{
'currency': currency['Currency'],
'available': currency['Available'],
'balance': currency['Balance'],
'pending': currency['Pending'],
'est_btc': currency['BTC']
}
)
fiat = self.freqtrade.fiat_converter
symbol = fiat_display_currency
value = fiat.convert_amount(total, 'BTC', symbol)
@@ -275,9 +283,9 @@ class RPC(object):
"""
if self.freqtrade.get_state() == State.RUNNING:
return (True, '*Status:* `already running`')
else:
self.freqtrade.update_state(State.RUNNING)
return (False, '`Starting trader ...`')
self.freqtrade.update_state(State.RUNNING)
return (False, '`Starting trader ...`')
def rpc_stop(self) -> (bool, str):
"""
@@ -286,8 +294,8 @@ class RPC(object):
if self.freqtrade.get_state() == State.RUNNING:
self.freqtrade.update_state(State.STOPPED)
return (False, '`Stopping trader ...`')
else:
return (True, '*Status:* `already stopped`')
return (True, '*Status:* `already stopped`')
# FIX: no test for this!!!!
def rpc_forcesell(self, trade_id) -> None:
@@ -300,18 +308,18 @@ class RPC(object):
# Check if there is there is an open order
if trade.open_order_id:
order = exchange.get_order(trade.open_order_id)
# Cancel open LIMIT_BUY orders and close trade
if order and not order['closed'] and order['type'] == 'LIMIT_BUY':
exchange.cancel_order(trade.open_order_id)
trade.close(order.get('rate') or trade.open_rate)
# TODO: sell amount which has been bought already
return
# Ignore trades with an attached LIMIT_SELL order
if order and not order['closed'] and order['type'] == 'LIMIT_SELL':
return
# Get current rate and execute sell
current_rate = exchange.get_ticker(trade.pair, False)['bid']
self.freqtrade.execute_sell(trade, current_rate)
@@ -319,13 +327,13 @@ class RPC(object):
if self.freqtrade.get_state() != State.RUNNING:
return (True, '`trader is not running`')
if trade_id == 'all':
# Execute sell for all open orders
for trade in Trade.query.filter(Trade.is_open.is_(True)).all():
_exec_forcesell(trade)
return (False, '')
# Query for trade
trade = Trade.query.filter(
sql.and_(
@@ -336,7 +344,7 @@ class RPC(object):
if not trade:
self.logger.warning('forcesell: Invalid argument received')
return (True, 'Invalid argument.')
_exec_forcesell(trade)
return (False, '')
@@ -347,7 +355,7 @@ class RPC(object):
"""
if self.freqtrade.get_state() != State.RUNNING:
return (True, '`trader is not running`')
pair_rates = Trade.session.query(Trade.pair,
sql.func.sum(Trade.close_profit).label('profit_sum'),
sql.func.count(Trade.pair).label('count')) \
@@ -358,9 +366,9 @@ class RPC(object):
trades = []
for (pair, rate, count) in pair_rates:
trades.append({'pair': pair, 'profit': round(rate * 100, 2), 'count': count})
return (False, trades)
def rpc_count(self) -> None:
"""
Returns the number of trades running
@@ -368,6 +376,6 @@ class RPC(object):
"""
if self.freqtrade.get_state() != State.RUNNING:
return (True, '`trader is not running`')
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
return (False, trades)

View File

@@ -10,7 +10,6 @@ class RPCManager(object):
"""
Class to manage RPC objects (Telegram, Slack, ...)
"""
def __init__(self, freqtrade) -> None:
"""
Initializes all enabled rpc modules

View File

@@ -1,14 +1,16 @@
# pragma pylint: disable=unused-argument, unused-variable, protected-access, invalid-name
"""
This module manage Telegram communication
"""
from typing import Any, Callable
from freqtrade.rpc.rpc import RPC
from tabulate import tabulate
from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update
from telegram.error import NetworkError, TelegramError
from telegram.ext import CommandHandler, Updater
from freqtrade.__init__ import __version__
from freqtrade.rpc.rpc import RPC
def authorized_only(command_handler: Callable[[Bot, Update], None]) -> Callable[..., Any]:
@@ -17,10 +19,10 @@ def authorized_only(command_handler: Callable[[Bot, Update], None]) -> Callable[
:param command_handler: Telegram CommandHandler
:return: decorated function
"""
#def wrapper(self, bot: Bot, update: Update):
def wrapper(self, *args, **kwargs):
"""
Decorator logic
"""
update = kwargs.get('update') or args[1]
# Reject unauthorized messages
@@ -45,6 +47,7 @@ def authorized_only(command_handler: Callable[[Bot, Update], None]) -> Callable[
return wrapper
class Telegram(RPC):
"""
Telegram, this class send messages to Telegram
@@ -57,7 +60,7 @@ class Telegram(RPC):
"""
super().__init__(freqtrade)
self._updater = Updater = None
self._updater = None
self._config = freqtrade.config
self._init()
@@ -190,10 +193,10 @@ class Telegram(RPC):
],
tablefmt='simple')
message = '<b>Daily Profit over the last {} days</b>:\n<pre>{}</pre>'\
.format(
timescale,
stats
)
.format(
timescale,
stats
)
self.send_msg(message, bot=bot, parse_mode=ParseMode.HTML)
@authorized_only
@@ -225,22 +228,22 @@ class Telegram(RPC):
"*Latest Trade opened:* `{latest_trade_date}`\n" \
"*Avg. Duration:* `{avg_duration}`\n" \
"*Best Performing:* `{best_pair}: {best_rate:.2f}%`"\
.format(
coin=self._config['stake_currency'],
fiat=self._config['fiat_display_currency'],
profit_closed_coin=stats['profit_closed_coin'],
profit_closed_percent=stats['profit_closed_percent'],
profit_closed_fiat=stats['profit_closed_fiat'],
profit_all_coin=stats['profit_all_coin'],
profit_all_percent=stats['profit_all_percent'],
profit_all_fiat=stats['profit_all_fiat'],
trade_count=stats['trade_count'],
first_trade_date=stats['first_trade_date'],
latest_trade_date=stats['latest_trade_date'],
avg_duration=stats['avg_duration'],
best_pair=stats['best_pair'],
best_rate=stats['best_rate']
)
.format(
coin=self._config['stake_currency'],
fiat=self._config['fiat_display_currency'],
profit_closed_coin=stats['profit_closed_coin'],
profit_closed_percent=stats['profit_closed_percent'],
profit_closed_fiat=stats['profit_closed_fiat'],
profit_all_coin=stats['profit_all_coin'],
profit_all_percent=stats['profit_all_percent'],
profit_all_fiat=stats['profit_all_fiat'],
trade_count=stats['trade_count'],
first_trade_date=stats['first_trade_date'],
latest_trade_date=stats['latest_trade_date'],
avg_duration=stats['avg_duration'],
best_pair=stats['best_pair'],
best_rate=stats['best_rate']
)
self.send_msg(markdown_msg, bot=bot)
@authorized_only
@@ -294,7 +297,6 @@ class Telegram(RPC):
(error, msg) = self.rpc_stop()
self.send_msg(msg, bot=bot)
# FIX: no test for this!!!!
@authorized_only
def _forcesell(self, bot: Bot, update: Update) -> None:
"""
@@ -370,10 +372,12 @@ class Telegram(RPC):
"*/status [table]:* `Lists all open trades`\n" \
" *table :* `will display trades in a table`\n" \
"*/profit:* `Lists cumulative profit from all finished trades`\n" \
"*/forcesell <trade_id>|all:* `Instantly sells the given trade or all trades, regardless of profit`\n" \
"*/forcesell <trade_id>|all:* `Instantly sells the given trade or all trades, " \
"regardless of profit`\n" \
"*/performance:* `Show performance of each finished trade grouped by pair`\n" \
"*/daily <n>:* `Shows profit or loss per day, over the last n days`\n" \
"*/count:* `Show number of trades running compared to allowed number of trades`\n" \
"*/count:* `Show number of trades running compared to allowed number of trades`" \
"\n" \
"*/balance:* `Show account balance per currency`\n" \
"*/help:* `This help message`\n" \
"*/version:* `Show version`"
@@ -391,7 +395,8 @@ class Telegram(RPC):
"""
self.send_msg('*Version:* `{}`'.format(__version__), bot=bot)
def send_msg(self, msg: str, bot: Bot = None, parse_mode: ParseMode = ParseMode.MARKDOWN) -> None:
def send_msg(self, msg: str, bot: Bot = None,
parse_mode: ParseMode = ParseMode.MARKDOWN) -> None:
"""
Send given markdown message
:param msg: message