From 03c112a6010c07941c55d565e4be0fa47e00b2b6 Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Thu, 14 Jun 2018 08:31:29 +0300 Subject: [PATCH 1/7] config, optimize: fstrings in use --- freqtrade/configuration.py | 6 +++--- freqtrade/optimize/__init__.py | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index c90eddeb8..582b2889c 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -62,8 +62,8 @@ class Configuration(object): conf = json.load(file) except FileNotFoundError: raise OperationalException( - 'Config file "{}" not found!' - ' Please create a config file or check whether it exists.'.format(path)) + f'Config file "{path}" not found!' + ' Please create a config file or check whether it exists.') if 'internals' not in conf: conf['internals'] = {} @@ -109,7 +109,7 @@ class Configuration(object): config['db_url'] = constants.DEFAULT_DB_PROD_URL logger.info('Dry run is disabled') - logger.info('Using DB: "{}"'.format(config['db_url'])) + logger.info(f'Using DB: "{config["db_url"]}"') # Check if the exchange set by the user is supported self.check_exchange(config) diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index 1e76808e7..e806ff2b8 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -54,11 +54,8 @@ def load_tickerdata_file( :return dict OR empty if unsuccesful """ path = make_testdata_path(datadir) - pair_file_string = pair.replace('/', '_') - file = os.path.join(path, '{pair}-{ticker_interval}.json'.format( - pair=pair_file_string, - ticker_interval=ticker_interval, - )) + pair_s = pair.replace('/', '_') + file = os.path.join(path, f'{pair_s}-{ticker_interval}.json') gzipfile = file + '.gz' # If the file does not exist we download it when None is returned. From 7dca3c6d03e83fe512d85280ceab0a5c41673d80 Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Thu, 14 Jun 2018 08:52:13 +0300 Subject: [PATCH 2/7] freqtradebot,main,hyperopt: fstrings in use --- freqtrade/freqtradebot.py | 8 ++------ freqtrade/main.py | 5 +---- freqtrade/optimize/hyperopt.py | 30 +++++++++++++++--------------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 64ff170fd..9def7078c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -626,12 +626,8 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \ # Because telegram._forcesell does not have the configuration # Ignore the FIAT value and does not show the stake_currency as well else: - message += '` ({gain}: {profit_percent:.2f}%, {profit_coin:.8f})`'.format( - gain="profit" if fmt_exp_profit > 0 else "loss", - profit_percent=fmt_exp_profit, - profit_coin=profit_trade - ) - + gain = "profit" if fmt_exp_profit > 0 else "loss" + message += f'` ({gain}: {fmt_exp_profit:.2f}%, {profit_trade:.8f})`' # Send the message self.rpc.send_msg(message) Trade.session.flush() diff --git a/freqtrade/main.py b/freqtrade/main.py index 9d17a403a..79080ce37 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -74,10 +74,7 @@ def reconfigure(freqtrade: FreqtradeBot, args: Namespace) -> FreqtradeBot: # Create new instance freqtrade = FreqtradeBot(Configuration(args).get_config()) freqtrade.rpc.send_msg( - '*Status:* `Config reloaded ...`'.format( - freqtrade.state.name.lower() - ) - ) + '*Status:* `Config reloaded {freqtrade.state.name.lower()}...`') return freqtrade diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 7138e2601..72bf34eb3 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -128,13 +128,12 @@ class Hyperopt(Backtesting): Log results if it is better than any previous evaluation """ if results['loss'] < self.current_best_loss: + current = results['current_tries'] + total = results['total_tries'] + res = results['result'] + loss = results['loss'] self.current_best_loss = results['loss'] - log_msg = '\n{:5d}/{}: {}. Loss {:.5f}'.format( - results['current_tries'], - results['total_tries'], - results['result'], - results['loss'] - ) + log_msg = f'\n{current:5d}/{total}: {res}. Loss {loss:.5f}' print(log_msg) else: print('.', end='') @@ -309,15 +308,16 @@ class Hyperopt(Backtesting): """ Return the format result in a string """ - return ('{:6d} trades. Avg profit {: 5.2f}%. ' - 'Total profit {: 11.8f} {} ({:.4f}Σ%). Avg duration {:5.1f} mins.').format( - len(results.index), - results.profit_percent.mean() * 100.0, - results.profit_abs.sum(), - self.config['stake_currency'], - results.profit_percent.sum(), - results.trade_duration.mean(), - ) + trades = len(results.index) + avg_profit = results.profit_percent.mean() * 100.0 + total_profit = results.profit_abs.sum() + stake_cur = self.config['stake_currency'] + profit = results.profit_percent.sum() + duration = results.trade_duration.mean() + + return (f'{trades:6d} trades. Avg profit {avg_profit: 5.2f}%. ' + f'Total profit {total_profit: 11.8f} {stake_cur} ' + f'({profit:.4f}Σ%). Avg duration {duration:5.1f} mins.') def get_optimizer(self, cpu_count) -> Optimizer: return Optimizer( From a2063ede558a28e68e94fa385fa56416c20f8341 Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Sat, 23 Jun 2018 08:27:29 -0500 Subject: [PATCH 3/7] persistence: fstrings in use --- freqtrade/persistence.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index 764ba6509..0e0b22e82 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -21,6 +21,7 @@ from freqtrade import OperationalException logger = logging.getLogger(__name__) _DECL_BASE: Any = declarative_base() +_SQL_DOCS_URL = 'http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls' def init(config: Dict) -> None: @@ -45,10 +46,8 @@ def init(config: Dict) -> None: try: engine = create_engine(db_url, **kwargs) except NoSuchModuleError: - error = 'Given value for db_url: \'{}\' is no valid database URL! (See {}).'.format( - db_url, 'http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls' - ) - raise OperationalException(error) + raise OperationalException(f'Given value for db_url: \'{db_url}\' ' + f'is no valid database URL! (See {_SQL_DOCS_URL})') session = scoped_session(sessionmaker(bind=engine, autoflush=True, autocommit=True)) Trade.session = session() @@ -173,13 +172,10 @@ class Trade(_DECL_BASE): max_rate = Column(Float, nullable=True, default=0.0) def __repr__(self): - return 'Trade(id={}, pair={}, amount={:.8f}, open_rate={:.8f}, open_since={})'.format( - self.id, - self.pair, - self.amount, - self.open_rate, - arrow.get(self.open_date).humanize() if self.is_open else 'closed' - ) + open_since = arrow.get(self.open_date).humanize() if self.is_open else 'closed' + + return (f'Trade(id={self.id}, pair={self.pair}, amount={self.amount:.8f}, ' + f'open_rate={self.open_rate:.8f}, open_since={open_since})') def adjust_stop_loss(self, current_price: float, stoploss: float, initial: bool = False): """this adjusts the stop loss to it's most recently observed setting""" @@ -226,6 +222,7 @@ class Trade(_DECL_BASE): :param order: order retrieved by exchange.get_order() :return: None """ + order_type = order['type'] # Ignore open and cancelled orders if order['status'] == 'open' or order['price'] is None: return @@ -233,16 +230,16 @@ class Trade(_DECL_BASE): logger.info('Updating trade (id=%d) ...', self.id) getcontext().prec = 8 # Bittrex do not go above 8 decimal - if order['type'] == 'limit' and order['side'] == 'buy': + if order_type == 'limit' and order['side'] == 'buy': # Update open rate and actual amount self.open_rate = Decimal(order['price']) self.amount = Decimal(order['amount']) logger.info('LIMIT_BUY has been fulfilled for %s.', self) self.open_order_id = None - elif order['type'] == 'limit' and order['side'] == 'sell': + elif order_type == 'limit' and order['side'] == 'sell': self.close(order['price']) else: - raise ValueError('Unknown order type: {}'.format(order['type'])) + raise ValueError(f'Unknown order type: {order_type}') cleanup() def close(self, rate: float) -> None: @@ -313,7 +310,8 @@ class Trade(_DECL_BASE): rate=(rate or self.close_rate), fee=(fee or self.fee_close) ) - return float("{0:.8f}".format(close_trade_price - open_trade_price)) + profit = close_trade_price - open_trade_price + return float(f"{profit:.8f}") def calc_profit_percent( self, @@ -333,5 +331,5 @@ class Trade(_DECL_BASE): rate=(rate or self.close_rate), fee=(fee or self.fee_close) ) - - return float("{0:.8f}".format((close_trade_price / open_trade_price) - 1)) + profit_percent = (close_trade_price / open_trade_price) - 1 + return float(f"{profit_percent:.8f}") From 21fc933678ebf938e99fdcaa19f48d64844b26e9 Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Sat, 23 Jun 2018 16:35:35 -0500 Subject: [PATCH 4/7] convert_backtesting: fstrings in use --- scripts/convert_backtestdata.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/convert_backtestdata.py b/scripts/convert_backtestdata.py index 698c1c829..96e0cbce8 100755 --- a/scripts/convert_backtestdata.py +++ b/scripts/convert_backtestdata.py @@ -143,15 +143,14 @@ def convert_main(args: Namespace) -> None: interval = str_interval break # change order on pairs if old ticker interval found + filename_new = path.join(path.dirname(filename), - "{}_{}-{}.json".format(currencies[1], - currencies[0], interval)) + f"{currencies[1]}_{currencies[0]}-{interval}.json") elif ret_string: interval = ret_string.group(0) filename_new = path.join(path.dirname(filename), - "{}_{}-{}.json".format(currencies[0], - currencies[1], interval)) + f"{currencies[0]}_{currencies[1]}-{interval}.json") else: logger.warning("file %s could not be converted, interval not found", filename) From adbffc69e152a9a9b4413a9b9c3f9e20baa3796b Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Sat, 23 Jun 2018 17:17:10 -0500 Subject: [PATCH 5/7] telegram: fstrings in use --- freqtrade/rpc/telegram.py | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 4dd23971b..13a2b1913 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -153,7 +153,7 @@ class Telegram(RPC): try: df_statuses = self._rpc_status_table() message = tabulate(df_statuses, headers='keys', tablefmt='simple') - self._send_msg("
{}
".format(message), parse_mode=ParseMode.HTML) + self._send_msg(f"
{message}
", parse_mode=ParseMode.HTML) except RPCException as e: self._send_msg(str(e), bot=bot) @@ -166,6 +166,8 @@ class Telegram(RPC): :param update: message update :return: None """ + stake_cur = self._config['stake_currency'] + fiat_disp_cur = self._config['fiat_display_currency'] try: timescale = int(update.message.text.replace('/daily', '').strip()) except (TypeError, ValueError): @@ -173,18 +175,17 @@ class Telegram(RPC): try: stats = self._rpc_daily_profit( timescale, - self._config['stake_currency'], - self._config['fiat_display_currency'] + stake_cur, + fiat_disp_cur ) stats = tabulate(stats, headers=[ 'Day', - 'Profit {}'.format(self._config['stake_currency']), - 'Profit {}'.format(self._config['fiat_display_currency']) + f'Profit {stake_cur}', + f'Profit {fiat_disp_cur}' ], tablefmt='simple') - message = 'Daily Profit over the last {} days:\n
{}
'\ - .format(timescale, stats) + message = f'Daily Profit over the last {timescale} days:\n
{stats}
' self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML) except RPCException as e: self._send_msg(str(e), bot=bot) @@ -198,39 +199,38 @@ class Telegram(RPC): :param update: message update :return: None """ + stake_cur = self._config['stake_currency'] + fiat_disp_cur = self._config['fiat_display_currency'] + try: stats = self._rpc_trade_statistics( - self._config['stake_currency'], - self._config['fiat_display_currency']) - + stake_cur, + fiat_disp_cur) + 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'] # Message to display markdown_msg = "*ROI:* Close trades\n" \ - "∙ `{profit_closed_coin:.8f} {coin} ({profit_closed_percent:.2f}%)`\n" \ - "∙ `{profit_closed_fiat:.3f} {fiat}`\n" \ - "*ROI:* All trades\n" \ - "∙ `{profit_all_coin:.8f} {coin} ({profit_all_percent:.2f}%)`\n" \ - "∙ `{profit_all_fiat:.3f} {fiat}`\n" \ - "*Total Trade Count:* `{trade_count}`\n" \ - "*First Trade opened:* `{first_trade_date}`\n" \ - "*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'] - ) + f"∙ `{profit_closed_coin:.8f} {stake_cur} "\ + f"({profit_closed_percent:.2f}%)`\n" \ + f"∙ `{profit_closed_fiat:.3f} {fiat_disp_cur}`\n" \ + f"*ROI:* All trades\n" \ + f"∙ `{profit_all_coin:.8f} {stake_cur} ({profit_all_percent:.2f}%)`\n" \ + f"∙ `{profit_all_fiat:.3f} {fiat_disp_cur}`\n" \ + f"*Total Trade Count:* `{trade_count}`\n" \ + f"*First Trade opened:* `{first_trade_date}`\n" \ + f"*Latest Trade opened:* `{latest_trade_date}`\n" \ + f"*Avg. Duration:* `{avg_duration}`\n" \ + f"*Best Performing:* `{best_pair}: {best_rate:.2f}%`" self._send_msg(markdown_msg, bot=bot) except RPCException as e: self._send_msg(str(e), bot=bot) From df68b0990ffc991032eadaabdf04d22f8db9ca4f Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Wed, 4 Jul 2018 13:53:45 -0500 Subject: [PATCH 6/7] rpc: fstrings --- freqtrade/rpc/rpc.py | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index f8cb136e4..263f293c6 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -74,34 +74,33 @@ class RPC(object): # calculate profit and send message to user current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid'] current_profit = trade.calc_profit_percent(current_rate) - fmt_close_profit = '{:.2f}%'.format( - round(trade.close_profit * 100, 2) - ) if trade.close_profit else None - message = "*Trade ID:* `{trade_id}`\n" \ - "*Current Pair:* [{pair}]({market_url})\n" \ - "*Open Since:* `{date}`\n" \ - "*Amount:* `{amount}`\n" \ - "*Open Rate:* `{open_rate:.8f}`\n" \ - "*Close Rate:* `{close_rate}`\n" \ - "*Current Rate:* `{current_rate:.8f}`\n" \ - "*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=self._freqtrade.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['side'], order['remaining'] - ) if order else None, - ) + fmt_close_profit = (f'{round(trade.close_profit * 100, 2):.2f}%' + if trade.close_profit else None) + market_url = self._freqtrade.exchange.get_pair_detail_url(trade.pair) + trade_date = arrow.get(trade.open_date).humanize() + open_rate = trade.open_rate + close_rate = trade.close_rate + amount = round(trade.amount, 8) + current_profit = round(current_profit * 100, 2) + if order: + order_type = order['type'] + order_side = order['side'] + order_rem = order['remaining'] + open_order = f'({order_type} {order_side} rem={order_rem:.8f})' + else: + open_order = None + + message = f"*Trade ID:* `{trade.id}`\n" \ + f"*Current Pair:* [{trade.pair}]({market_url})\n" \ + f"*Open Since:* `{trade_date}`\n" \ + f"*Amount:* `{amount}`\n" \ + f"*Open Rate:* `{open_rate:.8f}`\n" \ + f"*Close Rate:* `{close_rate}`\n" \ + f"*Current Rate:* `{current_rate:.8f}`\n" \ + f"*Close Profit:* `{fmt_close_profit}`\n" \ + f"*Current Profit:* `{current_profit:.2f}%`\n" \ + f"*Open Order:* `{open_order}`"\ + result.append(message) return result @@ -116,11 +115,12 @@ class RPC(object): for trade in trades: # calculate profit and send message to user current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid'] + trade_perc = (100 * trade.calc_profit_percent(current_rate)) trades_list.append([ trade.id, trade.pair, shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)), - '{:.2f}%'.format(100 * trade.calc_profit_percent(current_rate)) + f'{trade_perc:.2f}%' ]) columns = ['ID', 'Pair', 'Since', 'Profit'] @@ -148,7 +148,7 @@ class RPC(object): .all() curdayprofit = sum(trade.calc_profit() for trade in trades) profit_days[profitday] = { - 'amount': format(curdayprofit, '.8f'), + 'amount': f'{curdayprofit:.8f}', 'trades': len(trades) } From e808b3a2a1c73a1f30d33d073cf2245013d46d0e Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Thu, 5 Jul 2018 10:47:08 -0500 Subject: [PATCH 7/7] rpc: get rid of extra else and fix mypy warning --- freqtrade/rpc/rpc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 263f293c6..11658c6fb 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -82,13 +82,12 @@ class RPC(object): close_rate = trade.close_rate amount = round(trade.amount, 8) current_profit = round(current_profit * 100, 2) + open_order = '' if order: order_type = order['type'] order_side = order['side'] order_rem = order['remaining'] open_order = f'({order_type} {order_side} rem={order_rem:.8f})' - else: - open_order = None message = f"*Trade ID:* `{trade.id}`\n" \ f"*Current Pair:* [{trade.pair}]({market_url})\n" \