Merge pull request #981 from freqtrade/fstrings-in-use

Fstrings in use
This commit is contained in:
Matthias 2018-07-05 22:18:15 +02:00 committed by GitHub
commit 4f642b769c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 106 additions and 120 deletions

View File

@ -62,8 +62,8 @@ class Configuration(object):
conf = json.load(file) conf = json.load(file)
except FileNotFoundError: except FileNotFoundError:
raise OperationalException( raise OperationalException(
'Config file "{}" not found!' f'Config file "{path}" not found!'
' Please create a config file or check whether it exists.'.format(path)) ' Please create a config file or check whether it exists.')
if 'internals' not in conf: if 'internals' not in conf:
conf['internals'] = {} conf['internals'] = {}
@ -109,7 +109,7 @@ class Configuration(object):
config['db_url'] = constants.DEFAULT_DB_PROD_URL config['db_url'] = constants.DEFAULT_DB_PROD_URL
logger.info('Dry run is disabled') 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 # Check if the exchange set by the user is supported
self.check_exchange(config) self.check_exchange(config)

View File

@ -626,12 +626,8 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
# Because telegram._forcesell does not have the configuration # Because telegram._forcesell does not have the configuration
# Ignore the FIAT value and does not show the stake_currency as well # Ignore the FIAT value and does not show the stake_currency as well
else: else:
message += '` ({gain}: {profit_percent:.2f}%, {profit_coin:.8f})`'.format( gain = "profit" if fmt_exp_profit > 0 else "loss"
gain="profit" if fmt_exp_profit > 0 else "loss", message += f'` ({gain}: {fmt_exp_profit:.2f}%, {profit_trade:.8f})`'
profit_percent=fmt_exp_profit,
profit_coin=profit_trade
)
# Send the message # Send the message
self.rpc.send_msg(message) self.rpc.send_msg(message)
Trade.session.flush() Trade.session.flush()

View File

@ -74,10 +74,7 @@ def reconfigure(freqtrade: FreqtradeBot, args: Namespace) -> FreqtradeBot:
# Create new instance # Create new instance
freqtrade = FreqtradeBot(Configuration(args).get_config()) freqtrade = FreqtradeBot(Configuration(args).get_config())
freqtrade.rpc.send_msg( freqtrade.rpc.send_msg(
'*Status:* `Config reloaded ...`'.format( '*Status:* `Config reloaded {freqtrade.state.name.lower()}...`')
freqtrade.state.name.lower()
)
)
return freqtrade return freqtrade

View File

@ -54,11 +54,8 @@ def load_tickerdata_file(
:return dict OR empty if unsuccesful :return dict OR empty if unsuccesful
""" """
path = make_testdata_path(datadir) path = make_testdata_path(datadir)
pair_file_string = pair.replace('/', '_') pair_s = pair.replace('/', '_')
file = os.path.join(path, '{pair}-{ticker_interval}.json'.format( file = os.path.join(path, f'{pair_s}-{ticker_interval}.json')
pair=pair_file_string,
ticker_interval=ticker_interval,
))
gzipfile = file + '.gz' gzipfile = file + '.gz'
# If the file does not exist we download it when None is returned. # If the file does not exist we download it when None is returned.

View File

@ -128,13 +128,12 @@ class Hyperopt(Backtesting):
Log results if it is better than any previous evaluation Log results if it is better than any previous evaluation
""" """
if results['loss'] < self.current_best_loss: 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'] self.current_best_loss = results['loss']
log_msg = '\n{:5d}/{}: {}. Loss {:.5f}'.format( log_msg = f'\n{current:5d}/{total}: {res}. Loss {loss:.5f}'
results['current_tries'],
results['total_tries'],
results['result'],
results['loss']
)
print(log_msg) print(log_msg)
else: else:
print('.', end='') print('.', end='')
@ -309,15 +308,16 @@ class Hyperopt(Backtesting):
""" """
Return the format result in a string Return the format result in a string
""" """
return ('{:6d} trades. Avg profit {: 5.2f}%. ' trades = len(results.index)
'Total profit {: 11.8f} {} ({:.4f}Σ%). Avg duration {:5.1f} mins.').format( avg_profit = results.profit_percent.mean() * 100.0
len(results.index), total_profit = results.profit_abs.sum()
results.profit_percent.mean() * 100.0, stake_cur = self.config['stake_currency']
results.profit_abs.sum(), profit = results.profit_percent.sum()
self.config['stake_currency'], duration = results.trade_duration.mean()
results.profit_percent.sum(),
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: def get_optimizer(self, cpu_count) -> Optimizer:
return Optimizer( return Optimizer(

View File

@ -21,6 +21,7 @@ from freqtrade import OperationalException
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_DECL_BASE: Any = declarative_base() _DECL_BASE: Any = declarative_base()
_SQL_DOCS_URL = 'http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls'
def init(config: Dict) -> None: def init(config: Dict) -> None:
@ -45,10 +46,8 @@ def init(config: Dict) -> None:
try: try:
engine = create_engine(db_url, **kwargs) engine = create_engine(db_url, **kwargs)
except NoSuchModuleError: except NoSuchModuleError:
error = 'Given value for db_url: \'{}\' is no valid database URL! (See {}).'.format( raise OperationalException(f'Given value for db_url: \'{db_url}\' '
db_url, 'http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls' f'is no valid database URL! (See {_SQL_DOCS_URL})')
)
raise OperationalException(error)
session = scoped_session(sessionmaker(bind=engine, autoflush=True, autocommit=True)) session = scoped_session(sessionmaker(bind=engine, autoflush=True, autocommit=True))
Trade.session = session() Trade.session = session()
@ -173,13 +172,10 @@ class Trade(_DECL_BASE):
max_rate = Column(Float, nullable=True, default=0.0) max_rate = Column(Float, nullable=True, default=0.0)
def __repr__(self): def __repr__(self):
return 'Trade(id={}, pair={}, amount={:.8f}, open_rate={:.8f}, open_since={})'.format( open_since = arrow.get(self.open_date).humanize() if self.is_open else 'closed'
self.id,
self.pair, return (f'Trade(id={self.id}, pair={self.pair}, amount={self.amount:.8f}, '
self.amount, f'open_rate={self.open_rate:.8f}, open_since={open_since})')
self.open_rate,
arrow.get(self.open_date).humanize() if self.is_open else 'closed'
)
def adjust_stop_loss(self, current_price: float, stoploss: float, initial: bool = False): 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""" """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() :param order: order retrieved by exchange.get_order()
:return: None :return: None
""" """
order_type = order['type']
# Ignore open and cancelled orders # Ignore open and cancelled orders
if order['status'] == 'open' or order['price'] is None: if order['status'] == 'open' or order['price'] is None:
return return
@ -233,16 +230,16 @@ class Trade(_DECL_BASE):
logger.info('Updating trade (id=%d) ...', self.id) logger.info('Updating trade (id=%d) ...', self.id)
getcontext().prec = 8 # Bittrex do not go above 8 decimal 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 # Update open rate and actual amount
self.open_rate = Decimal(order['price']) self.open_rate = Decimal(order['price'])
self.amount = Decimal(order['amount']) self.amount = Decimal(order['amount'])
logger.info('LIMIT_BUY has been fulfilled for %s.', self) logger.info('LIMIT_BUY has been fulfilled for %s.', self)
self.open_order_id = None 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']) self.close(order['price'])
else: else:
raise ValueError('Unknown order type: {}'.format(order['type'])) raise ValueError(f'Unknown order type: {order_type}')
cleanup() cleanup()
def close(self, rate: float) -> None: def close(self, rate: float) -> None:
@ -313,7 +310,8 @@ class Trade(_DECL_BASE):
rate=(rate or self.close_rate), rate=(rate or self.close_rate),
fee=(fee or self.fee_close) 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( def calc_profit_percent(
self, self,
@ -333,5 +331,5 @@ class Trade(_DECL_BASE):
rate=(rate or self.close_rate), rate=(rate or self.close_rate),
fee=(fee or self.fee_close) fee=(fee or self.fee_close)
) )
profit_percent = (close_trade_price / open_trade_price) - 1
return float("{0:.8f}".format((close_trade_price / open_trade_price) - 1)) return float(f"{profit_percent:.8f}")

View File

@ -74,34 +74,32 @@ class RPC(object):
# calculate profit and send message to user # calculate profit and send message to user
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid'] current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
current_profit = trade.calc_profit_percent(current_rate) current_profit = trade.calc_profit_percent(current_rate)
fmt_close_profit = '{:.2f}%'.format( fmt_close_profit = (f'{round(trade.close_profit * 100, 2):.2f}%'
round(trade.close_profit * 100, 2) if trade.close_profit else None)
) if trade.close_profit else None market_url = self._freqtrade.exchange.get_pair_detail_url(trade.pair)
message = "*Trade ID:* `{trade_id}`\n" \ trade_date = arrow.get(trade.open_date).humanize()
"*Current Pair:* [{pair}]({market_url})\n" \ open_rate = trade.open_rate
"*Open Since:* `{date}`\n" \ close_rate = trade.close_rate
"*Amount:* `{amount}`\n" \ amount = round(trade.amount, 8)
"*Open Rate:* `{open_rate:.8f}`\n" \ current_profit = round(current_profit * 100, 2)
"*Close Rate:* `{close_rate}`\n" \ open_order = ''
"*Current Rate:* `{current_rate:.8f}`\n" \ if order:
"*Close Profit:* `{close_profit}`\n" \ order_type = order['type']
"*Current Profit:* `{current_profit:.2f}%`\n" \ order_side = order['side']
"*Open Order:* `{open_order}`"\ order_rem = order['remaining']
.format( open_order = f'({order_type} {order_side} rem={order_rem:.8f})'
trade_id=trade.id,
pair=trade.pair, message = f"*Trade ID:* `{trade.id}`\n" \
market_url=self._freqtrade.exchange.get_pair_detail_url(trade.pair), f"*Current Pair:* [{trade.pair}]({market_url})\n" \
date=arrow.get(trade.open_date).humanize(), f"*Open Since:* `{trade_date}`\n" \
open_rate=trade.open_rate, f"*Amount:* `{amount}`\n" \
close_rate=trade.close_rate, f"*Open Rate:* `{open_rate:.8f}`\n" \
current_rate=current_rate, f"*Close Rate:* `{close_rate}`\n" \
amount=round(trade.amount, 8), f"*Current Rate:* `{current_rate:.8f}`\n" \
close_profit=fmt_close_profit, f"*Close Profit:* `{fmt_close_profit}`\n" \
current_profit=round(current_profit * 100, 2), f"*Current Profit:* `{current_profit:.2f}%`\n" \
open_order='({} {} rem={:.8f})'.format( f"*Open Order:* `{open_order}`"\
order['type'], order['side'], order['remaining']
) if order else None,
)
result.append(message) result.append(message)
return result return result
@ -116,11 +114,12 @@ class RPC(object):
for trade in trades: for trade in trades:
# calculate profit and send message to user # calculate profit and send message to user
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid'] current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
trade_perc = (100 * trade.calc_profit_percent(current_rate))
trades_list.append([ trades_list.append([
trade.id, trade.id,
trade.pair, trade.pair,
shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)), 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'] columns = ['ID', 'Pair', 'Since', 'Profit']
@ -148,7 +147,7 @@ class RPC(object):
.all() .all()
curdayprofit = sum(trade.calc_profit() for trade in trades) curdayprofit = sum(trade.calc_profit() for trade in trades)
profit_days[profitday] = { profit_days[profitday] = {
'amount': format(curdayprofit, '.8f'), 'amount': f'{curdayprofit:.8f}',
'trades': len(trades) 'trades': len(trades)
} }

View File

@ -153,7 +153,7 @@ class Telegram(RPC):
try: try:
df_statuses = self._rpc_status_table() df_statuses = self._rpc_status_table()
message = tabulate(df_statuses, headers='keys', tablefmt='simple') message = tabulate(df_statuses, headers='keys', tablefmt='simple')
self._send_msg("<pre>{}</pre>".format(message), parse_mode=ParseMode.HTML) self._send_msg(f"<pre>{message}</pre>", parse_mode=ParseMode.HTML)
except RPCException as e: except RPCException as e:
self._send_msg(str(e), bot=bot) self._send_msg(str(e), bot=bot)
@ -166,6 +166,8 @@ class Telegram(RPC):
:param update: message update :param update: message update
:return: None :return: None
""" """
stake_cur = self._config['stake_currency']
fiat_disp_cur = self._config['fiat_display_currency']
try: try:
timescale = int(update.message.text.replace('/daily', '').strip()) timescale = int(update.message.text.replace('/daily', '').strip())
except (TypeError, ValueError): except (TypeError, ValueError):
@ -173,18 +175,17 @@ class Telegram(RPC):
try: try:
stats = self._rpc_daily_profit( stats = self._rpc_daily_profit(
timescale, timescale,
self._config['stake_currency'], stake_cur,
self._config['fiat_display_currency'] fiat_disp_cur
) )
stats = tabulate(stats, stats = tabulate(stats,
headers=[ headers=[
'Day', 'Day',
'Profit {}'.format(self._config['stake_currency']), f'Profit {stake_cur}',
'Profit {}'.format(self._config['fiat_display_currency']) f'Profit {fiat_disp_cur}'
], ],
tablefmt='simple') tablefmt='simple')
message = '<b>Daily Profit over the last {} days</b>:\n<pre>{}</pre>'\ message = f'<b>Daily Profit over the last {timescale} days</b>:\n<pre>{stats}</pre>'
.format(timescale, stats)
self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML) self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML)
except RPCException as e: except RPCException as e:
self._send_msg(str(e), bot=bot) self._send_msg(str(e), bot=bot)
@ -198,39 +199,38 @@ class Telegram(RPC):
:param update: message update :param update: message update
:return: None :return: None
""" """
stake_cur = self._config['stake_currency']
fiat_disp_cur = self._config['fiat_display_currency']
try: try:
stats = self._rpc_trade_statistics( stats = self._rpc_trade_statistics(
self._config['stake_currency'], stake_cur,
self._config['fiat_display_currency']) 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 # Message to display
markdown_msg = "*ROI:* Close trades\n" \ markdown_msg = "*ROI:* Close trades\n" \
"∙ `{profit_closed_coin:.8f} {coin} ({profit_closed_percent:.2f}%)`\n" \ f"∙ `{profit_closed_coin:.8f} {stake_cur} "\
"∙ `{profit_closed_fiat:.3f} {fiat}`\n" \ f"({profit_closed_percent:.2f}%)`\n" \
"*ROI:* All trades\n" \ f"∙ `{profit_closed_fiat:.3f} {fiat_disp_cur}`\n" \
"∙ `{profit_all_coin:.8f} {coin} ({profit_all_percent:.2f}%)`\n" \ f"*ROI:* All trades\n" \
"∙ `{profit_all_fiat:.3f} {fiat}`\n" \ f"∙ `{profit_all_coin:.8f} {stake_cur} ({profit_all_percent:.2f}%)`\n" \
"*Total Trade Count:* `{trade_count}`\n" \ f"∙ `{profit_all_fiat:.3f} {fiat_disp_cur}`\n" \
"*First Trade opened:* `{first_trade_date}`\n" \ f"*Total Trade Count:* `{trade_count}`\n" \
"*Latest Trade opened:* `{latest_trade_date}`\n" \ f"*First Trade opened:* `{first_trade_date}`\n" \
"*Avg. Duration:* `{avg_duration}`\n" \ f"*Latest Trade opened:* `{latest_trade_date}`\n" \
"*Best Performing:* `{best_pair}: {best_rate:.2f}%`"\ f"*Avg. Duration:* `{avg_duration}`\n" \
.format( f"*Best Performing:* `{best_pair}: {best_rate:.2f}%`"
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) self._send_msg(markdown_msg, bot=bot)
except RPCException as e: except RPCException as e:
self._send_msg(str(e), bot=bot) self._send_msg(str(e), bot=bot)

View File

@ -143,15 +143,14 @@ def convert_main(args: Namespace) -> None:
interval = str_interval interval = str_interval
break break
# change order on pairs if old ticker interval found # change order on pairs if old ticker interval found
filename_new = path.join(path.dirname(filename), filename_new = path.join(path.dirname(filename),
"{}_{}-{}.json".format(currencies[1], f"{currencies[1]}_{currencies[0]}-{interval}.json")
currencies[0], interval))
elif ret_string: elif ret_string:
interval = ret_string.group(0) interval = ret_string.group(0)
filename_new = path.join(path.dirname(filename), filename_new = path.join(path.dirname(filename),
"{}_{}-{}.json".format(currencies[0], f"{currencies[0]}_{currencies[1]}-{interval}.json")
currencies[1], interval))
else: else:
logger.warning("file %s could not be converted, interval not found", filename) logger.warning("file %s could not be converted, interval not found", filename)