Make Pylint Happy chapter 1
This commit is contained in:
		| @@ -1,11 +1,11 @@ | ||||
| """ | ||||
| Functions to analyze ticker data with indicators and produce buy and sell signals | ||||
| """ | ||||
| import arrow | ||||
| from datetime import datetime, timedelta | ||||
| from enum import Enum | ||||
| from pandas import DataFrame, to_datetime | ||||
| from typing import Dict, List | ||||
| import arrow | ||||
| from pandas import DataFrame, to_datetime | ||||
| from freqtrade.exchange import get_ticker_history | ||||
| from freqtrade.logger import Logger | ||||
| from freqtrade.strategy.strategy import Strategy | ||||
| @@ -188,10 +188,9 @@ class Analyze(object): | ||||
|         ) | ||||
|         return False | ||||
|  | ||||
|  | ||||
|     def tickerdata_to_dataframe(self, tickerdata: Dict[str, List]) -> Dict[str, DataFrame]: | ||||
|         """ | ||||
|         Creates a dataframe and populates indicators for given ticker data | ||||
|         """ | ||||
|         return {pair: self.populate_indicators(self.parse_ticker_dataframe(pair_data)) | ||||
|                 for pair, pair_data in tickerdata.items()} | ||||
|                 for pair, pair_data in tickerdata.items()} | ||||
|   | ||||
| @@ -2,16 +2,15 @@ | ||||
| Freqtrade is the main module of this bot. It contains the class Freqtrade() | ||||
| """ | ||||
|  | ||||
| import logging | ||||
| import arrow | ||||
| import copy | ||||
| import json | ||||
| import requests | ||||
| import time | ||||
| import traceback | ||||
| from cachetools import cached, TTLCache | ||||
| from datetime import datetime | ||||
| from typing import Dict, List, Optional, Any, Callable | ||||
| from datetime import datetime | ||||
| import requests | ||||
| import arrow | ||||
| from cachetools import cached, TTLCache | ||||
| from freqtrade.analyze import Analyze | ||||
| from freqtrade.constants import Constants | ||||
| from freqtrade.fiat_convert import CryptoToFiatConverter | ||||
| @@ -507,14 +506,14 @@ class FreqtradeBot(object): | ||||
|                   "*Current Rate:* `{current_rate:.8f}`\n" \ | ||||
|                   "*Profit:* `{profit:.2f}%`" \ | ||||
|                   "".format( | ||||
|                         exchange=trade.exchange, | ||||
|                         pair=trade.pair, | ||||
|                         pair_url=exchange.get_pair_detail_url(trade.pair), | ||||
|                         limit=limit, | ||||
|                         open_rate=trade.open_rate, | ||||
|                         current_rate=current_rate, | ||||
|                         amount=round(trade.amount, 8), | ||||
|                         profit=round(profit * 100, 2), | ||||
|                       exchange=trade.exchange, | ||||
|                       pair=trade.pair, | ||||
|                       pair_url=exchange.get_pair_detail_url(trade.pair), | ||||
|                       limit=limit, | ||||
|                       open_rate=trade.open_rate, | ||||
|                       current_rate=current_rate, | ||||
|                       amount=round(trade.amount, 8), | ||||
|                       profit=round(profit * 100, 2), | ||||
|                   ) | ||||
|  | ||||
|         # For regular case, when the configuration exists | ||||
| @@ -528,12 +527,12 @@ class FreqtradeBot(object): | ||||
|             message += '` ({gain}: {profit_percent:.2f}%, {profit_coin:.8f} {coin}`' \ | ||||
|                        '` / {profit_fiat:.3f} {fiat})`' \ | ||||
|                        ''.format( | ||||
|                             gain="profit" if fmt_exp_profit > 0 else "loss", | ||||
|                             profit_percent=fmt_exp_profit, | ||||
|                             profit_coin=profit_trade, | ||||
|                             coin=self.config['stake_currency'], | ||||
|                             profit_fiat=profit_fiat, | ||||
|                             fiat=self.config['fiat_display_currency'], | ||||
|                            gain="profit" if fmt_exp_profit > 0 else "loss", | ||||
|                            profit_percent=fmt_exp_profit, | ||||
|                            profit_coin=profit_trade, | ||||
|                            coin=self.config['stake_currency'], | ||||
|                            profit_fiat=profit_fiat, | ||||
|                            fiat=self.config['fiat_display_currency'], | ||||
|                        ) | ||||
|         # Because telegram._forcesell does not have the configuration | ||||
|         # Ignore the FIAT value and does not show the stake_currency as well | ||||
|   | ||||
| @@ -97,10 +97,11 @@ def download_pairs(datadir, pairs: List[str], ticker_interval: int) -> bool: | ||||
|         try: | ||||
|             download_backtesting_testdata(datadir, pair=pair, interval=ticker_interval) | ||||
|         except BaseException: | ||||
|             logger.info('Failed to download the pair: "{pair}", Interval: {interval} min'.format( | ||||
|                 pair=pair, | ||||
|                 interval=ticker_interval, | ||||
|             )) | ||||
|             logger.info( | ||||
|                 'Failed to download the pair: "%s", Interval: %s min', | ||||
|                 pair, | ||||
|                 ticker_interval | ||||
|             ) | ||||
|             return False | ||||
|     return True | ||||
|  | ||||
| @@ -115,10 +116,11 @@ def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) -> | ||||
|     """ | ||||
|  | ||||
|     path = make_testdata_path(datadir) | ||||
|     logger.info('Download the pair: "{pair}", Interval: {interval} min'.format( | ||||
|         pair=pair, | ||||
|         interval=interval, | ||||
|     )) | ||||
|     logger.info( | ||||
|         'Download the pair: "%s", Interval: %s min', | ||||
|         pair, | ||||
|         interval | ||||
|     ) | ||||
|  | ||||
|     filepair = pair.replace("-", "_") | ||||
|     filename = os.path.join(path, '{pair}-{interval}.json'.format( | ||||
| @@ -129,8 +131,8 @@ def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) -> | ||||
|     if os.path.isfile(filename): | ||||
|         with open(filename, "rt") as file: | ||||
|             data = json.load(file) | ||||
|         logger.debug("Current Start: {}".format(data[1]['T'])) | ||||
|         logger.debug("Current End: {}".format(data[-1:][0]['T'])) | ||||
|         logger.debug("Current Start: %s", data[1]['T']) | ||||
|         logger.debug("Current End: %s", data[-1:][0]['T']) | ||||
|     else: | ||||
|         data = [] | ||||
|         logger.debug("Current Start: None") | ||||
| @@ -140,8 +142,8 @@ def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) -> | ||||
|     for row in new_data: | ||||
|         if row not in data: | ||||
|             data.append(row) | ||||
|     logger.debug("New Start: {}".format(data[1]['T'])) | ||||
|     logger.debug("New End: {}".format(data[-1:][0]['T'])) | ||||
|     logger.debug("New Start: %s", data[1]['T']) | ||||
|     logger.debug("New End: %s", data[-1:][0]['T']) | ||||
|     data = sorted(data, key=lambda data: data['T']) | ||||
|  | ||||
|     misc.file_dump_json(filename, data) | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import freqtrade.vendor.qtpylib.indicators as qtpylib | ||||
| from freqtrade.configuration import Configuration | ||||
| from freqtrade.optimize import load_data | ||||
| from freqtrade.arguments import Arguments | ||||
| from freqtrade.optimize.backtesting import Backtesting, setup_configuration | ||||
| from freqtrade.optimize.backtesting import Backtesting | ||||
| from freqtrade.logger import Logger | ||||
| from user_data.hyperopt_conf import hyperopt_optimize_conf | ||||
|  | ||||
| @@ -46,7 +46,6 @@ class Hyperopt(Backtesting): | ||||
|         self.logging = Logger(name=__name__, level=config['loglevel']) | ||||
|         self.logger = self.logging.get_logger() | ||||
|  | ||||
|  | ||||
|         # set TARGET_TRADES to suit your number concurrent trades so its realistic | ||||
|         # to the number of days | ||||
|         self.target_trades = 600 | ||||
| @@ -353,6 +352,9 @@ class Hyperopt(Backtesting): | ||||
|         Define the buy strategy parameters to be used by hyperopt | ||||
|         """ | ||||
|         def populate_buy_trend(dataframe: DataFrame) -> DataFrame: | ||||
|             """ | ||||
|             Buy strategy Hyperopt will build and use | ||||
|             """ | ||||
|             conditions = [] | ||||
|             # GUARDS AND TRENDS | ||||
|             if 'uptrend_long_ema' in params and params['uptrend_long_ema']['enabled']: | ||||
| @@ -513,8 +515,9 @@ class Hyperopt(Backtesting): | ||||
|                 self.current_tries = len(self.trials.results) | ||||
|                 self.total_tries += self.current_tries | ||||
|                 self.logger.info( | ||||
|                     'Continuing with trials. Current: {}, Total: {}' | ||||
|                     .format(self.current_tries, self.total_tries) | ||||
|                     'Continuing with trials. Current: %d, Total: %d', | ||||
|                     self.current_tries, | ||||
|                     self.total_tries | ||||
|                 ) | ||||
|  | ||||
|         try: | ||||
| @@ -557,7 +560,10 @@ class Hyperopt(Backtesting): | ||||
|         """ | ||||
|         Hyperopt SIGINT handler | ||||
|         """ | ||||
|         self.logger.info('Hyperopt received {}'.format(signal.Signals(sig).name)) | ||||
|         self.logger.info( | ||||
|             'Hyperopt received %s', | ||||
|             signal.Signals(sig).name | ||||
|         ) | ||||
|  | ||||
|         self.save_trials() | ||||
|         self.log_trials_result() | ||||
| @@ -580,9 +586,7 @@ def start(args) -> None: | ||||
|     logger.info('Starting freqtrade in Hyperopt mode') | ||||
|  | ||||
|     # Initialize configuration | ||||
|     #config = setup_configuration(args) | ||||
|  | ||||
|     # Monkey patch of the configuration with hyperopt_conf.py | ||||
|     # Monkey patch the configuration with hyperopt_conf.py | ||||
|     configuration = Configuration(args) | ||||
|     optimize_config = hyperopt_optimize_conf() | ||||
|     config = configuration._load_backtesting_config(optimize_config) | ||||
|   | ||||
| @@ -1,3 +1,7 @@ | ||||
| """ | ||||
| This module contains the class to persist trades into SQLite | ||||
| """ | ||||
|  | ||||
| import logging | ||||
| from datetime import datetime | ||||
| from decimal import Decimal, getcontext | ||||
| @@ -72,6 +76,9 @@ def clean_dry_run_db() -> None: | ||||
|  | ||||
|  | ||||
| class Trade(_DECL_BASE): | ||||
|     """ | ||||
|     Class used to define a trade structure | ||||
|     """ | ||||
|     __tablename__ = 'trades' | ||||
|  | ||||
|     id = Column(Integer, primary_key=True) | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -10,7 +10,6 @@ class RPCManager(object): | ||||
|     """ | ||||
|     Class to manage RPC objects (Telegram, Slack, ...) | ||||
|     """ | ||||
|      | ||||
|     def __init__(self, freqtrade) -> None: | ||||
|         """ | ||||
|         Initializes all enabled rpc modules | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -19,7 +19,7 @@ class Strategy(object): | ||||
|     """ | ||||
|     This class contains all the logic to load custom strategy class | ||||
|     """ | ||||
|     def __init__(self, config: dict={}) -> None: | ||||
|     def __init__(self, config: dict = {}) -> None: | ||||
|         """ | ||||
|         Load the custom class from config parameter | ||||
|         :param config: | ||||
|   | ||||
| @@ -1,14 +1,8 @@ | ||||
| # pragma pylint: disable=missing-docstring,W0212,C0103 | ||||
| import logging | ||||
| import os | ||||
| import pytest | ||||
| from copy import deepcopy | ||||
|  | ||||
| #from freqtrade.optimize.hyperopt import EXPECTED_MAX_PROFIT, start, \ | ||||
| #    log_results, save_trials, read_trials, generate_roi_table | ||||
| from unittest.mock import MagicMock | ||||
|  | ||||
| from freqtrade.optimize.hyperopt import Hyperopt, start | ||||
| from freqtrade.optimize.hyperopt import Hyperopt | ||||
| import freqtrade.tests.conftest as tt  # test tools | ||||
|  | ||||
|  | ||||
| @@ -24,7 +18,7 @@ def create_trials(mocker) -> None: | ||||
|       - we might have a pickle'd file so make sure that we return | ||||
|         false when looking for it | ||||
|     """ | ||||
|     _HYPEROPT.trials_file = os.path.join('freqtrade', 'tests', 'optimize','ut_trials.pickle') | ||||
|     _HYPEROPT.trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle') | ||||
|  | ||||
|     mocker.patch('freqtrade.optimize.hyperopt.os.path.exists', return_value=False) | ||||
|     mocker.patch('freqtrade.optimize.hyperopt.os.remove', return_value=True) | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| # pragma pylint: disable=protected-access, invalid-name | ||||
|  | ||||
| """ | ||||
| Unit test file for configuration.py | ||||
| """ | ||||
| @@ -270,4 +271,3 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non | ||||
|         'Parameter --export detected: {} ...'.format(config['export']), | ||||
|         caplog.record_tuples | ||||
|     ) | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,6 @@ from freqtrade.constants import Constants | ||||
| def test_constant_object() -> None: | ||||
|     """ | ||||
|     Test the Constants object has the mandatory Constants | ||||
|     :return: None | ||||
|     """ | ||||
|     assert hasattr(Constants, 'CONF_SCHEMA') | ||||
|     assert hasattr(Constants, 'DYNAMIC_WHITELIST') | ||||
| @@ -19,11 +18,9 @@ def test_constant_object() -> None: | ||||
|     assert hasattr(Constants, 'DEFAULT_STRATEGY') | ||||
|  | ||||
|  | ||||
|  | ||||
| def test_conf_schema() -> None: | ||||
|     """ | ||||
|     Test the CONF_SCHEMA is from the right type | ||||
|     :return: | ||||
|     """ | ||||
|     constant = Constants() | ||||
|     assert isinstance(constant.CONF_SCHEMA, dict) | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| import pandas | ||||
| from freqtrade.optimize import load_data | ||||
| from freqtrade.analyze import Analyze, SignalType | ||||
| from freqtrade.analyze import Analyze | ||||
|  | ||||
| _pairs = ['BTC_ETH'] | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user