mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
Make Pylint Happy chapter 1
This commit is contained in:
parent
d274f13480
commit
390501bac0
|
@ -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']
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user