From cae7be44472a2d37be36e844d0aae6c049e27e23 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:12:21 +0100 Subject: [PATCH 01/16] add fee param to function doc --- freqtrade/persistence.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index e0d433a24..56fe336d2 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -207,6 +207,7 @@ class Trade(_DECL_BASE): Calculates the profit in percentage (including fee). :param rate: rate to compare with (optional). If rate is not set self.close_rate will be used + :param fee: fee to use on the close rate (optional). :return: profit in percentage as float """ getcontext().prec = 8 From 31e2aa0f38ab79d4371bdab9f9baa40dbb1eb8ee Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:12:42 +0100 Subject: [PATCH 02/16] misc: apply missing typehints --- freqtrade/misc.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/freqtrade/misc.py b/freqtrade/misc.py index 814e0fb6f..d70364999 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -6,12 +6,15 @@ import re import json import logging from datetime import datetime +from typing import Dict + import numpy as np +from pandas import DataFrame logger = logging.getLogger(__name__) -def shorten_date(_date): +def shorten_date(_date: str) -> str: """ Trim the date so it fits on small screens """ @@ -28,7 +31,7 @@ def shorten_date(_date): # Matplotlib doesn't support ::datetime64, # # so we need to convert it into ::datetime # ############################################ -def datesarray_to_datetimearray(dates): +def datesarray_to_datetimearray(dates: np.ndarray) -> np.ndarray: """ Convert an pandas-array of timestamps into An numpy-array of datetimes @@ -42,10 +45,10 @@ def datesarray_to_datetimearray(dates): return np.array(times) -def common_datearray(dfs): +def common_datearray(dfs: Dict[str, DataFrame]) -> np.ndarray: """ Return dates from Dataframe - :param dfs: Dataframe + :param dfs: Dict with format pair: pair_data :return: List of dates """ alldates = {} From 2de63133ae57f4bacbd9506456beff9d83d40235 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:16:03 +0100 Subject: [PATCH 03/16] indicator_helpers: apply correct typehints --- freqtrade/indicator_helpers.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/freqtrade/indicator_helpers.py b/freqtrade/indicator_helpers.py index c3cc42e6a..14519d7a2 100644 --- a/freqtrade/indicator_helpers.py +++ b/freqtrade/indicator_helpers.py @@ -1,19 +1,19 @@ from math import exp, pi, sqrt, cos -import numpy +import numpy as np import talib as ta from pandas import Series -def went_up(series: Series) -> Series: +def went_up(series: Series) -> bool: return series > series.shift(1) -def went_down(series: Series) -> Series: +def went_down(series: Series) -> bool: return series < series.shift(1) -def ehlers_super_smoother(series: Series, smoothing: float = 6): +def ehlers_super_smoother(series: Series, smoothing: float = 6) -> type(Series): magic = pi * sqrt(2) / smoothing a1 = exp(-magic) coeff2 = 2 * a1 * cos(magic) @@ -29,7 +29,7 @@ def ehlers_super_smoother(series: Series, smoothing: float = 6): return filtered -def fishers_inverse(series: Series, smoothing: float = 0): +def fishers_inverse(series: Series, smoothing: float = 0) -> np.ndarray: """ Does a smoothed fishers inverse transformation. Can be used with any oscillator that goes from 0 to 100 like RSI or MFI """ v1 = 0.1 * (series - 50) @@ -37,4 +37,4 @@ def fishers_inverse(series: Series, smoothing: float = 0): v2 = ta.WMA(v1.values, timeperiod=smoothing) else: v2 = v1 - return (numpy.exp(2 * v2)-1) / (numpy.exp(2 * v2) + 1) + return (np.exp(2 * v2)-1) / (np.exp(2 * v2) + 1) From 90be78b28353764a727eaecb3994c5e006d77dd3 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:18:05 +0100 Subject: [PATCH 04/16] CryptoFiat: inherit from object explicitly --- freqtrade/fiat_convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index 4874247db..f73de4bec 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -10,7 +10,7 @@ from coinmarketcap import Market logger = logging.getLogger(__name__) -class CryptoFiat(): +class CryptoFiat(object): """ Object to describe what is the price of Crypto-currency in a FIAT """ From 1074415d30105010dedf1aa3e5f6e5741135c68b Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:18:25 +0100 Subject: [PATCH 05/16] remove invalid typehint from ctor --- freqtrade/freqtradebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index b18d6540b..08ef74bbd 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -27,7 +27,7 @@ class FreqtradeBot(object): This is from here the bot start its logic. """ - def __init__(self, config: Dict[str, Any], db_url: Optional[str] = None) -> bool: + def __init__(self, config: Dict[str, Any], db_url: Optional[str] = None): """ Init all variables and object the bot need to work :param config: configuration dict, you can use the Configuration.get_config() From ed71340a904b2a4d052cea971a8d293cd663a6e4 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:20:45 +0100 Subject: [PATCH 06/16] arguments: apply missing typehints --- freqtrade/arguments.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 30f94fddc..c53fd42ed 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -6,7 +6,7 @@ import argparse import os import re import logging -from typing import List +from typing import List, Tuple, Optional from freqtrade import __version__ from freqtrade.constants import Constants @@ -22,7 +22,7 @@ class Arguments(object): self.parsed_arg = None self.parser = argparse.ArgumentParser(description=description) - def _load_args(self): + def _load_args(self) -> None: self.common_args_parser() self._build_subcommands() @@ -205,7 +205,7 @@ class Arguments(object): self.hyperopt_options(hyperopt_cmd) @staticmethod - def parse_timerange(text: str) -> (List, int, int): + def parse_timerange(text: str) -> Optional[Tuple[List, int, int]]: """ Parse the value of the argument --timerange to determine what is the range desired :param text: value from --timerange @@ -236,10 +236,10 @@ class Arguments(object): stop = rvals[index] if stype[1] != 'date': stop = int(stop) - return (stype, start, stop) + return stype, start, stop raise Exception('Incorrect syntax for timerange "%s"' % text) - def scripts_options(self): + def scripts_options(self) -> None: """ Parses given arguments for plot scripts. """ From 5532cedcdd30b1bb552448a326fd4efb8d202a79 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:22:35 +0100 Subject: [PATCH 07/16] get_signal: remove redundant parentheses --- freqtrade/analyze.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 401d99479..fd3813458 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -3,7 +3,7 @@ Functions to analyze ticker data with indicators and produce buy and sell signal """ from datetime import datetime, timedelta from enum import Enum -from typing import Dict, List +from typing import Dict, List, Tuple import arrow from pandas import DataFrame, to_datetime from freqtrade.exchange import get_ticker_history @@ -96,9 +96,7 @@ class Analyze(object): dataframe = self.populate_sell_trend(dataframe) return dataframe - # FIX: Maybe return False, if an error has occured, - # Otherwise we might mask an error as an non-signal-scenario - def get_signal(self, pair: str, interval: int) -> (bool, bool): + def get_signal(self, pair: str, interval: int) -> Tuple[bool, bool]: """ Calculates current signal based several technical analysis indicators :param pair: pair in format BTC_ANT or BTC-ANT @@ -108,7 +106,7 @@ class Analyze(object): ticker_hist = get_ticker_history(pair, interval) if not ticker_hist: self.logger.warning('Empty ticker history for pair %s', pair) - return (False, False) # return False ? + return False, False try: dataframe = self.analyze_ticker(ticker_hist) @@ -118,18 +116,18 @@ class Analyze(object): pair, str(error) ) - return (False, False) # return False ? + return False, False except Exception as error: self.logger.exception( 'Unexpected error when analyzing ticker for pair %s: %s', pair, str(error) ) - return (False, False) # return False ? + return False, False if dataframe.empty: self.logger.warning('Empty dataframe for pair %s', pair) - return (False, False) # return False ? + return False, False latest = dataframe.iloc[-1] @@ -141,7 +139,7 @@ class Analyze(object): pair, (arrow.utcnow() - signal_date).seconds // 60 ) - return (False, False) # return False ? + return False, False (buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1 self.logger.debug( @@ -151,7 +149,7 @@ class Analyze(object): str(buy), str(sell) ) - return (buy, sell) + return buy, sell def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool, sell: bool) -> bool: """ From 532753318828726a14522645e827e532cf4e8c28 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:43:36 +0100 Subject: [PATCH 08/16] optimize: set correct typehints --- freqtrade/optimize/__init__.py | 19 +++++++++++-------- freqtrade/optimize/backtesting.py | 15 +++++++++------ freqtrade/optimize/hyperopt.py | 15 ++++++++------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index 049b2f94f..1ea6b9fe5 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -2,7 +2,7 @@ import json import os -from typing import Optional, List, Dict +from typing import Optional, List, Dict, Tuple import gzip from freqtrade.exchange import get_ticker_history @@ -13,8 +13,8 @@ from user_data.hyperopt_conf import hyperopt_optimize_conf logger = Logger(name=__name__).get_logger() -def trim_tickerlist(tickerlist, timerange): - (stype, start, stop) = timerange +def trim_tickerlist(tickerlist: List[Dict], timerange: Tuple[Tuple, int, int]) -> List[Dict]: + stype, start, stop = timerange if stype == (None, 'line'): return tickerlist[stop:] elif stype == ('line', None): @@ -25,7 +25,10 @@ def trim_tickerlist(tickerlist, timerange): return tickerlist -def load_tickerdata_file(datadir, pair, ticker_interval, timerange=None): +def load_tickerdata_file( + datadir: str, pair: str, + ticker_interval: int, + timerange: Optional[Tuple[Tuple, int, int]] = None) -> Optional[List[Dict]]: """ Load a pair from file, :return dict OR empty if unsuccesful @@ -55,12 +58,12 @@ def load_tickerdata_file(datadir, pair, ticker_interval, timerange=None): return pairdata -def load_data(datadir: str, ticker_interval: int, pairs: Optional[List[str]] = None, - refresh_pairs: Optional[bool] = False, timerange=None) -> Dict[str, List]: +def load_data(datadir: str, ticker_interval: int, + pairs: Optional[List[str]] = None, + refresh_pairs: Optional[bool] = False, + timerange: Optional[Tuple[Tuple, int, int]] = None) -> Dict[str, List]: """ Loads ticker history data for the given parameters - :param ticker_interval: ticker interval in minutes - :param pairs: list of pairs :return: dict """ result = {} diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 8d22d00e3..606af02c7 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -3,8 +3,8 @@ """ This module contains the backtesting logic """ - -from typing import Dict, Tuple, Any +from argparse import Namespace +from typing import Dict, Tuple, Any, List, Optional import arrow from pandas import DataFrame, Series from tabulate import tabulate @@ -101,7 +101,10 @@ class Backtesting(object): ]) return tabulate(tabular_data, headers=headers, floatfmt=floatfmt) - def _get_sell_trade_entry(self, pair, buy_row, partial_ticker, trade_count_lock, args): + def _get_sell_trade_entry( + self, pair: str, buy_row: DataFrame, + partial_ticker: List, trade_count_lock: Dict, args: Dict) -> Optional[Tuple]: + stake_amount = args['stake_amount'] max_open_trades = args.get('max_open_trades', 0) trade = Trade( @@ -132,7 +135,7 @@ class Backtesting(object): sell_row.date return None - def backtest(self, args) -> DataFrame: + def backtest(self, args: Dict) -> DataFrame: """ Implements backtesting functionality @@ -273,7 +276,7 @@ class Backtesting(object): ) -def setup_configuration(args) -> Dict[str, Any]: +def setup_configuration(args: Namespace) -> Dict[str, Any]: """ Prepare the configuration for the backtesting :param args: Cli args from Arguments() @@ -289,7 +292,7 @@ def setup_configuration(args) -> Dict[str, Any]: return config -def start(args) -> None: +def start(args: Namespace) -> None: """ Start Backtesting script :param args: Cli args from Arguments() diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 39bade554..5175345e5 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -10,10 +10,11 @@ import os import pickle import signal import sys +from argparse import Namespace from functools import reduce from math import exp from operator import itemgetter -from typing import Dict, Any, Callable +from typing import Dict, Any, Callable, List import numpy import talib.abstract as ta @@ -240,7 +241,7 @@ class Hyperopt(Backtesting): return trade_loss + profit_loss + duration_loss @staticmethod - def generate_roi_table(params) -> Dict[int, float]: + def generate_roi_table(params: Dict) -> Dict[int, float]: """ Generate the ROI table thqt will be used by Hyperopt """ @@ -335,7 +336,7 @@ class Hyperopt(Backtesting): ]), } - def has_space(self, space) -> bool: + def has_space(self, space: str) -> bool: """ Tell if a space value is contained in the configuration """ @@ -433,7 +434,7 @@ class Hyperopt(Backtesting): return populate_buy_trend - def generate_optimizer(self, params) -> Dict: + def generate_optimizer(self, params: Dict) -> Dict: if self.has_space('roi'): self.analyze.strategy.minimal_roi = self.generate_roi_table(params) @@ -496,7 +497,7 @@ class Hyperopt(Backtesting): results.duration.mean(), ) - def start(self): + def start(self) -> None: timerange = Arguments.parse_timerange(self.config.get('timerange')) data = load_data( datadir=self.config.get('datadir'), @@ -571,7 +572,7 @@ class Hyperopt(Backtesting): # Store trials result to file to resume next time self.save_trials() - def signal_handler(self, sig, frame): + def signal_handler(self, sig, frame) -> None: """ Hyperopt SIGINT handler """ @@ -585,7 +586,7 @@ class Hyperopt(Backtesting): sys.exit(0) -def start(args) -> None: +def start(args: Namespace) -> None: """ Start Backtesting script :param args: Cli args from Arguments() From d8689e504517f67d39f79df8706a0dbb14f933e1 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:43:59 +0100 Subject: [PATCH 09/16] set correct typehint; remove unused argument --- freqtrade/configuration.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index fd9872eb3..10ac783e6 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -3,8 +3,9 @@ This module contains the configuration class """ import json +from argparse import Namespace -from typing import Dict, List, Any +from typing import Dict, Any from jsonschema import Draft4Validator, validate from jsonschema.exceptions import ValidationError, best_match @@ -17,7 +18,7 @@ class Configuration(object): Class to read and init the bot configuration Reuse this class for the bot, backtesting, hyperopt and every script that required configuration """ - def __init__(self, args: List[str], do_not_init=False) -> None: + def __init__(self, args: Namespace) -> None: self.args = args self.logging = Logger(name=__name__) self.logger = self.logging.get_logger() From d2aea7bdc1c8c7637f1c0a27f4bccaee437943ab Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 22:44:47 +0100 Subject: [PATCH 10/16] optimize imports --- freqtrade/analyze.py | 4 +++- freqtrade/arguments.py | 2 +- freqtrade/configuration.py | 2 +- freqtrade/exchange/bittrex.py | 2 +- freqtrade/fiat_convert.py | 1 + freqtrade/freqtradebot.py | 8 ++++--- freqtrade/main.py | 5 +++-- freqtrade/misc.py | 2 +- freqtrade/optimize/__init__.py | 4 ++-- freqtrade/optimize/backtesting.py | 7 ++++--- freqtrade/optimize/hyperopt.py | 8 +++---- freqtrade/rpc/rpc.py | 10 +++++---- freqtrade/rpc/telegram.py | 2 ++ freqtrade/strategy/default_strategy.py | 3 ++- freqtrade/strategy/interface.py | 1 + freqtrade/strategy/strategy.py | 9 ++++---- freqtrade/tests/conftest.py | 11 +++++----- freqtrade/tests/exchange/test_exchange.py | 11 +++++----- .../tests/exchange/test_exchange_bittrex.py | 4 +++- freqtrade/tests/optimize/test_backtesting.py | 21 ++++++++++--------- freqtrade/tests/optimize/test_hyperopt.py | 1 + freqtrade/tests/optimize/test_optimize.py | 7 ++++--- freqtrade/tests/rpc/test_rpc_telegram.py | 8 +++---- .../tests/strategy/test_default_strategy.py | 4 +++- freqtrade/tests/strategy/test_strategy.py | 1 + freqtrade/tests/test_analyze.py | 4 ++-- freqtrade/tests/test_arguments.py | 1 + freqtrade/tests/test_configuration.py | 4 ++-- freqtrade/tests/test_dataframe.py | 2 +- freqtrade/tests/test_freqtradebot.py | 9 ++++---- freqtrade/tests/test_indicator_helpers.py | 1 + freqtrade/tests/test_logger.py | 1 + freqtrade/tests/test_main.py | 1 + freqtrade/tests/test_misc.py | 3 ++- freqtrade/tests/test_persistence.py | 2 ++ .../tests/testdata/download_backtest_data.py | 4 ++-- 36 files changed, 101 insertions(+), 69 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index fd3813458..8bc552d74 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -4,12 +4,14 @@ Functions to analyze ticker data with indicators and produce buy and sell signal from datetime import datetime, timedelta from enum import Enum from typing import Dict, List, Tuple + 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 from freqtrade.persistence import Trade +from freqtrade.strategy.strategy import Strategy class SignalType(Enum): diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index c53fd42ed..a73a1945f 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -3,9 +3,9 @@ This module contains the argument manager class """ import argparse +import logging import os import re -import logging from typing import List, Tuple, Optional from freqtrade import __version__ diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 10ac783e6..1f6cea4e6 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -4,8 +4,8 @@ This module contains the configuration class import json from argparse import Namespace - from typing import Dict, Any + from jsonschema import Draft4Validator, validate from jsonschema.exceptions import ValidationError, best_match diff --git a/freqtrade/exchange/bittrex.py b/freqtrade/exchange/bittrex.py index 5aa07e460..0cba621af 100644 --- a/freqtrade/exchange/bittrex.py +++ b/freqtrade/exchange/bittrex.py @@ -1,8 +1,8 @@ import logging from typing import Dict, List, Optional -from bittrex.bittrex import Bittrex as _Bittrex from bittrex.bittrex import API_V1_1, API_V2_0 +from bittrex.bittrex import Bittrex as _Bittrex from requests.exceptions import ContentDecodingError from freqtrade import OperationalException diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index f73de4bec..b86b56ec5 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -5,6 +5,7 @@ e.g BTC to USD import logging import time + from coinmarketcap import Market logger = logging.getLogger(__name__) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 08ef74bbd..e57f177e9 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -6,11 +6,14 @@ import copy import json import time import traceback -from typing import Dict, List, Optional, Any, Callable from datetime import datetime -import requests +from typing import Dict, List, Optional, Any, Callable + import arrow +import requests from cachetools import cached, TTLCache + +from freqtrade import (DependencyException, OperationalException, exchange, persistence) from freqtrade.analyze import Analyze from freqtrade.constants import Constants from freqtrade.fiat_convert import CryptoToFiatConverter @@ -18,7 +21,6 @@ from freqtrade.logger import Logger from freqtrade.persistence import Trade from freqtrade.rpc.rpc_manager import RPCManager from freqtrade.state import State -from freqtrade import (DependencyException, OperationalException, exchange, persistence) class FreqtradeBot(object): diff --git a/freqtrade/main.py b/freqtrade/main.py index 97515b68b..8deeb7da6 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -7,11 +7,12 @@ Read the documentation to know what cli arguments you need. import logging import sys from typing import Dict -from freqtrade.configuration import Configuration + +from freqtrade import (__version__) from freqtrade.arguments import Arguments +from freqtrade.configuration import Configuration from freqtrade.freqtradebot import FreqtradeBot from freqtrade.logger import Logger -from freqtrade import (__version__) logger = Logger(name='freqtrade').get_logger() diff --git a/freqtrade/misc.py b/freqtrade/misc.py index d70364999..f5d045c44 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -2,9 +2,9 @@ Various tool function for Freqtrade and scripts """ -import re import json import logging +import re from datetime import datetime from typing import Dict diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index 1ea6b9fe5..a26744691 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -1,12 +1,12 @@ # pragma pylint: disable=missing-docstring +import gzip import json import os from typing import Optional, List, Dict, Tuple -import gzip -from freqtrade.exchange import get_ticker_history from freqtrade import misc +from freqtrade.exchange import get_ticker_history from freqtrade.logger import Logger from user_data.hyperopt_conf import hyperopt_optimize_conf diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 606af02c7..d8af47326 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -5,16 +5,17 @@ This module contains the backtesting logic """ from argparse import Namespace from typing import Dict, Tuple, Any, List, Optional + import arrow from pandas import DataFrame, Series from tabulate import tabulate import freqtrade.optimize as optimize -from freqtrade.arguments import Arguments -from freqtrade.exchange import Bittrex -from freqtrade.configuration import Configuration from freqtrade import exchange from freqtrade.analyze import Analyze +from freqtrade.arguments import Arguments +from freqtrade.configuration import Configuration +from freqtrade.exchange import Bittrex from freqtrade.logger import Logger from freqtrade.misc import file_dump_json from freqtrade.persistence import Trade diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 5175345e5..7dcd46fd2 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -14,7 +14,7 @@ from argparse import Namespace from functools import reduce from math import exp from operator import itemgetter -from typing import Dict, Any, Callable, List +from typing import Dict, Any, Callable import numpy import talib.abstract as ta @@ -23,11 +23,11 @@ from hyperopt.mongoexp import MongoTrials from pandas import DataFrame 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 +from freqtrade.configuration import Configuration from freqtrade.logger import Logger +from freqtrade.optimize import load_data +from freqtrade.optimize.backtesting import Backtesting from user_data.hyperopt_conf import hyperopt_optimize_conf diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index fa9c2022d..4bf8f4e3a 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -2,16 +2,18 @@ This module contains class to define a RPC communications """ -from decimal import Decimal from datetime import datetime, timedelta +from decimal import Decimal + import arrow -from pandas import DataFrame import sqlalchemy as sql +from pandas import DataFrame + +from freqtrade import exchange from freqtrade.logger import Logger +from freqtrade.misc import shorten_date from freqtrade.persistence import Trade from freqtrade.state import State -from freqtrade import exchange -from freqtrade.misc import shorten_date class RPC(object): diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 0d4e4403b..fce7a81f9 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -5,10 +5,12 @@ This module manage Telegram communication """ from typing import Any, Callable + 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 diff --git a/freqtrade/strategy/default_strategy.py b/freqtrade/strategy/default_strategy.py index 2247ecf27..ea37735b7 100644 --- a/freqtrade/strategy/default_strategy.py +++ b/freqtrade/strategy/default_strategy.py @@ -2,9 +2,10 @@ import talib.abstract as ta from pandas import DataFrame + import freqtrade.vendor.qtpylib.indicators as qtpylib -from freqtrade.strategy.interface import IStrategy from freqtrade.indicator_helpers import fishers_inverse +from freqtrade.strategy.interface import IStrategy class_name = 'DefaultStrategy' diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index dc9f33244..4eb73fb2e 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -4,6 +4,7 @@ This module defines the interface to apply for strategies """ from abc import ABC, abstractmethod + from pandas import DataFrame diff --git a/freqtrade/strategy/strategy.py b/freqtrade/strategy/strategy.py index ed1dee10e..17bdb2c1f 100644 --- a/freqtrade/strategy/strategy.py +++ b/freqtrade/strategy/strategy.py @@ -7,11 +7,12 @@ import importlib import os import sys from collections import OrderedDict -from pandas import DataFrame -from freqtrade.logger import Logger -from freqtrade.constants import Constants -from freqtrade.strategy.interface import IStrategy +from pandas import DataFrame + +from freqtrade.constants import Constants +from freqtrade.logger import Logger +from freqtrade.strategy.interface import IStrategy sys.path.insert(0, r'../../user_data/strategies') diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index cb726633b..07dc45a3e 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -1,14 +1,15 @@ # pragma pylint: disable=missing-docstring -from datetime import datetime -from unittest.mock import MagicMock -from functools import reduce -import logging import json +import logging +from datetime import datetime +from functools import reduce +from unittest.mock import MagicMock + import arrow import pytest from jsonschema import validate -from telegram import Chat, Message, Update from sqlalchemy import create_engine +from telegram import Chat, Message, Update from freqtrade.analyze import Analyze from freqtrade.constants import Constants diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 4f6eab083..f2874f2da 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -1,15 +1,16 @@ # pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement # pragma pylint: disable=protected-access -from unittest.mock import MagicMock -from random import randint import logging -from requests.exceptions import RequestException -import pytest +from random import randint +from unittest.mock import MagicMock +import pytest +from requests.exceptions import RequestException + +import freqtrade.exchange as exchange from freqtrade import OperationalException from freqtrade.exchange import init, validate_pairs, buy, sell, get_balance, get_balances, \ get_ticker, get_ticker_history, cancel_order, get_name, get_fee -import freqtrade.exchange as exchange from freqtrade.tests.conftest import log_has API_INIT = False diff --git a/freqtrade/tests/exchange/test_exchange_bittrex.py b/freqtrade/tests/exchange/test_exchange_bittrex.py index 058c25de1..2c66215c2 100644 --- a/freqtrade/tests/exchange/test_exchange_bittrex.py +++ b/freqtrade/tests/exchange/test_exchange_bittrex.py @@ -1,10 +1,12 @@ # pragma pylint: disable=missing-docstring, C0103, protected-access, unused-argument from unittest.mock import MagicMock + import pytest from requests.exceptions import ContentDecodingError -from freqtrade.exchange.bittrex import Bittrex + import freqtrade.exchange.bittrex as btx +from freqtrade.exchange.bittrex import Bittrex # Eat this flake8 diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 731b93176..021474d5c 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -1,20 +1,21 @@ # pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument import json -import random import math -from typing import List +import random from copy import deepcopy +from typing import List from unittest.mock import MagicMock -from arrow import Arrow -import pandas as pd -import numpy as np -from freqtrade import optimize -from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration -from freqtrade.arguments import Arguments -from freqtrade.analyze import Analyze -from freqtrade.tests.conftest import default_conf, log_has +import numpy as np +import pandas as pd +from arrow import Arrow + +from freqtrade import optimize +from freqtrade.analyze import Analyze +from freqtrade.arguments import Arguments +from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration +from freqtrade.tests.conftest import default_conf, log_has # Avoid to reinit the same object again and again _BACKTESTING = Backtesting(default_conf()) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index f29694c2f..6d376471a 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -3,6 +3,7 @@ import json import os from copy import deepcopy from unittest.mock import MagicMock + import pandas as pd from freqtrade.optimize.__init__ import load_tickerdata_file diff --git a/freqtrade/tests/optimize/test_optimize.py b/freqtrade/tests/optimize/test_optimize.py index 43f46291f..e26d30534 100644 --- a/freqtrade/tests/optimize/test_optimize.py +++ b/freqtrade/tests/optimize/test_optimize.py @@ -1,13 +1,14 @@ # pragma pylint: disable=missing-docstring, protected-access, C0103 -import os import json +import os import uuid from shutil import copyfile + from freqtrade import optimize -from freqtrade.optimize.__init__ import make_testdata_path, download_pairs,\ - download_backtesting_testdata, load_tickerdata_file, trim_tickerlist from freqtrade.misc import file_dump_json +from freqtrade.optimize.__init__ import make_testdata_path, download_pairs, \ + download_backtesting_testdata, load_tickerdata_file, trim_tickerlist from freqtrade.tests.conftest import log_has # Change this if modifying BTC_UNITEST testdatafile diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py index 69ddc5ef5..4796b077e 100644 --- a/freqtrade/tests/rpc/test_rpc_telegram.py +++ b/freqtrade/tests/rpc/test_rpc_telegram.py @@ -6,23 +6,23 @@ Unit test file for rpc/telegram.py """ import re +from copy import deepcopy from datetime import datetime from random import randint from unittest.mock import MagicMock -from copy import deepcopy from sqlalchemy import create_engine from telegram import Update, Message, Chat from telegram.error import NetworkError from freqtrade import __version__ -from freqtrade.rpc.telegram import authorized_only from freqtrade.freqtradebot import FreqtradeBot -from freqtrade.rpc.telegram import Telegram from freqtrade.persistence import Trade +from freqtrade.rpc.telegram import Telegram +from freqtrade.rpc.telegram import authorized_only from freqtrade.state import State -from freqtrade.tests.test_freqtradebot import patch_get_signal, patch_coinmarketcap from freqtrade.tests.conftest import get_patched_freqtradebot, log_has +from freqtrade.tests.test_freqtradebot import patch_get_signal, patch_coinmarketcap class DummyCls(Telegram): diff --git a/freqtrade/tests/strategy/test_default_strategy.py b/freqtrade/tests/strategy/test_default_strategy.py index 02b5630fc..2b91fbec5 100644 --- a/freqtrade/tests/strategy/test_default_strategy.py +++ b/freqtrade/tests/strategy/test_default_strategy.py @@ -1,8 +1,10 @@ import json + import pytest from pandas import DataFrame -from freqtrade.strategy.default_strategy import DefaultStrategy, class_name + from freqtrade.analyze import Analyze +from freqtrade.strategy.default_strategy import DefaultStrategy, class_name @pytest.fixture diff --git a/freqtrade/tests/strategy/test_strategy.py b/freqtrade/tests/strategy/test_strategy.py index 77250659f..7ce9ae0ef 100644 --- a/freqtrade/tests/strategy/test_strategy.py +++ b/freqtrade/tests/strategy/test_strategy.py @@ -1,6 +1,7 @@ # pragma pylint: disable=missing-docstring, protected-access, C0103 import logging + from freqtrade.strategy.strategy import Strategy diff --git a/freqtrade/tests/test_analyze.py b/freqtrade/tests/test_analyze.py index 4d1c31de2..558ea7ee5 100644 --- a/freqtrade/tests/test_analyze.py +++ b/freqtrade/tests/test_analyze.py @@ -5,8 +5,9 @@ Unit test file for analyse.py """ import datetime -from unittest.mock import MagicMock import logging +from unittest.mock import MagicMock + import arrow from pandas import DataFrame @@ -14,7 +15,6 @@ from freqtrade.analyze import Analyze, SignalType from freqtrade.optimize.__init__ import load_tickerdata_file from freqtrade.tests.conftest import log_has - # Avoid to reinit the same object again and again _ANALYZE = Analyze({'strategy': 'default_strategy'}) diff --git a/freqtrade/tests/test_arguments.py b/freqtrade/tests/test_arguments.py index 6ad507e85..3e0639304 100644 --- a/freqtrade/tests/test_arguments.py +++ b/freqtrade/tests/test_arguments.py @@ -6,6 +6,7 @@ Unit test file for arguments.py import argparse import logging + import pytest from freqtrade.arguments import Arguments diff --git a/freqtrade/tests/test_configuration.py b/freqtrade/tests/test_configuration.py index 4ca92c343..002eac722 100644 --- a/freqtrade/tests/test_configuration.py +++ b/freqtrade/tests/test_configuration.py @@ -4,10 +4,10 @@ Unit test file for configuration.py """ import json - from copy import deepcopy -import pytest from unittest.mock import MagicMock + +import pytest from jsonschema import ValidationError from freqtrade.arguments import Arguments diff --git a/freqtrade/tests/test_dataframe.py b/freqtrade/tests/test_dataframe.py index 86944e4f3..1f69a7d32 100644 --- a/freqtrade/tests/test_dataframe.py +++ b/freqtrade/tests/test_dataframe.py @@ -2,8 +2,8 @@ import pandas -from freqtrade.optimize import load_data from freqtrade.analyze import Analyze +from freqtrade.optimize import load_data from freqtrade.strategy.strategy import Strategy _pairs = ['BTC_ETH'] diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py index 5d9b9aba1..d58b428da 100644 --- a/freqtrade/tests/test_freqtradebot.py +++ b/freqtrade/tests/test_freqtradebot.py @@ -5,22 +5,23 @@ Unit test file for freqtradebot.py """ import logging +import re import time -from unittest.mock import MagicMock from copy import deepcopy from typing import Dict, Optional +from unittest.mock import MagicMock + import arrow import pytest import requests -import re from sqlalchemy import create_engine -from freqtrade.tests.conftest import log_has from freqtrade import DependencyException, OperationalException from freqtrade.exchange import Exchanges from freqtrade.freqtradebot import FreqtradeBot -from freqtrade.state import State from freqtrade.persistence import Trade +from freqtrade.state import State +from freqtrade.tests.conftest import log_has # Functions for recurrent object patching diff --git a/freqtrade/tests/test_indicator_helpers.py b/freqtrade/tests/test_indicator_helpers.py index 90330a6ef..87b085a0b 100644 --- a/freqtrade/tests/test_indicator_helpers.py +++ b/freqtrade/tests/test_indicator_helpers.py @@ -1,4 +1,5 @@ import pandas as pd + from freqtrade.indicator_helpers import went_up, went_down diff --git a/freqtrade/tests/test_logger.py b/freqtrade/tests/test_logger.py index d6e7a2e06..8e094b2d1 100644 --- a/freqtrade/tests/test_logger.py +++ b/freqtrade/tests/test_logger.py @@ -3,6 +3,7 @@ Unit test file for logger.py """ import logging + from freqtrade.logger import Logger diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index 83da04495..71b816968 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -4,6 +4,7 @@ Unit test file for main.py import logging from unittest.mock import MagicMock + import pytest from freqtrade.main import main, set_loggers diff --git a/freqtrade/tests/test_misc.py b/freqtrade/tests/test_misc.py index 1d2417332..3560b2db1 100644 --- a/freqtrade/tests/test_misc.py +++ b/freqtrade/tests/test_misc.py @@ -6,10 +6,11 @@ Unit test file for misc.py import datetime from unittest.mock import MagicMock + from freqtrade.analyze import Analyze -from freqtrade.optimize.__init__ import load_tickerdata_file from freqtrade.misc import (shorten_date, datesarray_to_datetimearray, common_datearray, file_dump_json) +from freqtrade.optimize.__init__ import load_tickerdata_file def test_shorten_date() -> None: diff --git a/freqtrade/tests/test_persistence.py b/freqtrade/tests/test_persistence.py index f6c5318ce..70199b12a 100644 --- a/freqtrade/tests/test_persistence.py +++ b/freqtrade/tests/test_persistence.py @@ -1,7 +1,9 @@ # pragma pylint: disable=missing-docstring, C0103 import os + import pytest from sqlalchemy import create_engine + from freqtrade.exchange import Exchanges from freqtrade.persistence import Trade, init, clean_dry_run_db diff --git a/freqtrade/tests/testdata/download_backtest_data.py b/freqtrade/tests/testdata/download_backtest_data.py index 0cb545b3a..ceb8388a1 100755 --- a/freqtrade/tests/testdata/download_backtest_data.py +++ b/freqtrade/tests/testdata/download_backtest_data.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 """This script generate json data from bittrex""" -import sys import json +import sys from freqtrade import exchange -from freqtrade.exchange import Bittrex from freqtrade import misc +from freqtrade.exchange import Bittrex parser = misc.common_args_parser('download utility') parser.add_argument( From 7078bc00bd434ba77cbff2f214e40f2c47da0ca2 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sat, 17 Mar 2018 23:30:31 +0100 Subject: [PATCH 11/16] rpc: apply correct typehints; remove redundant parentheses --- freqtrade/rpc/rpc.py | 68 +++++++++++++++++++----------------- freqtrade/rpc/rpc_manager.py | 2 +- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 4bf8f4e3a..2d7af1b50 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -4,6 +4,7 @@ This module contains class to define a RPC communications from datetime import datetime, timedelta from decimal import Decimal +from typing import Tuple, Any import arrow import sqlalchemy as sql @@ -32,7 +33,7 @@ class RPC(object): level=self.freqtrade.config.get('loglevel') ).get_logger() - def rpc_trade_status(self) -> (bool, Trade): + def rpc_trade_status(self) -> Tuple[bool, Any]: """ Below follows the RPC backend it is prefixed with rpc_ to raise awareness that it is a remotely exposed function @@ -41,9 +42,9 @@ class RPC(object): # Fetch open trade trades = Trade.query.filter(Trade.is_open.is_(True)).all() if self.freqtrade.get_state() != State.RUNNING: - return (True, '*Status:* `trader is not running`') + return True, '*Status:* `trader is not running`' elif not trades: - return (True, '*Status:* `no active trade`') + return True, '*Status:* `no active trade`' else: result = [] for trade in trades: @@ -82,14 +83,14 @@ class RPC(object): ) if order else None, ) result.append(message) - return (False, result) + return False, result - def rpc_status_table(self) -> (bool, DataFrame): + def rpc_status_table(self) -> Tuple[bool, Any]: trades = Trade.query.filter(Trade.is_open.is_(True)).all() if self.freqtrade.get_state() != State.RUNNING: - return (True, '*Status:* `trader is not running`') + return True, '*Status:* `trader is not running`' elif not trades: - return (True, '*Status:* `no active order`') + return True, '*Status:* `no active order`' else: trades_list = [] for trade in trades: @@ -109,14 +110,16 @@ class RPC(object): # consisting of (error_occured?, result) # Another approach would be to just return the # result, or raise error - return (False, df_statuses) + return False, df_statuses - def rpc_daily_profit(self, timescale, stake_currency, fiat_display_currency): + def rpc_daily_profit( + self, timescale: int, + stake_currency: str, fiat_display_currency: str) -> Tuple[bool, Any]: 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`') + return True, '*Daily [n]:* `must be an integer greater than 0`' fiat = self.freqtrade.fiat_converter for day in range(0, timescale): @@ -155,9 +158,10 @@ class RPC(object): ] for key, value in profit_days.items() ] - return (False, stats) + return False, stats - def rpc_trade_statistics(self, stake_currency, fiat_display_currency) -> None: + def rpc_trade_statistics( + self, stake_currency: str, fiat_display_currency: str) -> Tuple[bool, Any]: """ :return: cumulative profit statistics. """ @@ -200,7 +204,7 @@ class RPC(object): .order_by(sql.text('profit_sum DESC')).first() if not best_pair: - return (True, '*Status:* `no closed trade`') + return True, '*Status:* `no closed trade`' bp_pair, bp_rate = best_pair @@ -241,7 +245,7 @@ class RPC(object): } ) - def rpc_balance(self, fiat_display_currency): + def rpc_balance(self, fiat_display_currency: str) -> Tuple[bool, Any]: """ :return: current account balance per crypto """ @@ -250,7 +254,7 @@ class RPC(object): if c['Balance'] or c['Available'] or c['Pending'] ] if not balances: - return (True, '`All balances are zero.`') + return True, '`All balances are zero.`' output = [] total = 0.0 @@ -277,17 +281,17 @@ class RPC(object): fiat = self.freqtrade.fiat_converter symbol = fiat_display_currency value = fiat.convert_amount(total, 'BTC', symbol) - return (False, (output, total, symbol, value)) + return False, (output, total, symbol, value) def rpc_start(self) -> (bool, str): """ Handler for start. """ if self.freqtrade.get_state() == State.RUNNING: - return (True, '*Status:* `already running`') + return True, '*Status:* `already running`' self.freqtrade.update_state(State.RUNNING) - return (False, '`Starting trader ...`') + return False, '`Starting trader ...`' def rpc_stop(self) -> (bool, str): """ @@ -295,18 +299,18 @@ class RPC(object): """ if self.freqtrade.get_state() == State.RUNNING: self.freqtrade.update_state(State.STOPPED) - return (False, '`Stopping trader ...`') + return False, '`Stopping trader ...`' - return (True, '*Status:* `already stopped`') + return True, '*Status:* `already stopped`' # FIX: no test for this!!!! - def rpc_forcesell(self, trade_id) -> None: + def rpc_forcesell(self, trade_id) -> Tuple[bool, Any]: """ Handler for forcesell . Sells the given trade at current price :return: error or None """ - def _exec_forcesell(trade: Trade) -> str: + def _exec_forcesell(trade: Trade) -> None: # Check if there is there is an open order if trade.open_order_id: order = exchange.get_order(trade.open_order_id) @@ -328,13 +332,13 @@ class RPC(object): # ---- EOF def _exec_forcesell ---- if self.freqtrade.get_state() != State.RUNNING: - return (True, '`trader is not 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, '') + return False, '' # Query for trade trade = Trade.query.filter( @@ -345,18 +349,18 @@ class RPC(object): ).first() if not trade: self.logger.warning('forcesell: Invalid argument received') - return (True, 'Invalid argument.') + return True, 'Invalid argument.' _exec_forcesell(trade) - return (False, '') + return False, '' - def rpc_performance(self) -> None: + def rpc_performance(self) -> Tuple[bool, Any]: """ Handler for performance. Shows a performance statistic from finished trades """ if self.freqtrade.get_state() != State.RUNNING: - return (True, '`trader is not running`') + return True, '`trader is not running`' pair_rates = Trade.session.query(Trade.pair, sql.func.sum(Trade.close_profit).label('profit_sum'), @@ -369,15 +373,15 @@ class RPC(object): for (pair, rate, count) in pair_rates: trades.append({'pair': pair, 'profit': round(rate * 100, 2), 'count': count}) - return (False, trades) + return False, trades - def rpc_count(self) -> None: + def rpc_count(self) -> Tuple[bool, Any]: """ Returns the number of trades running :return: None """ if self.freqtrade.get_state() != State.RUNNING: - return (True, '`trader is not running`') + return True, '`trader is not running`' trades = Trade.query.filter(Trade.is_open.is_(True)).all() - return (False, trades) + return False, trades diff --git a/freqtrade/rpc/rpc_manager.py b/freqtrade/rpc/rpc_manager.py index cd3a694c2..fb18a8d73 100644 --- a/freqtrade/rpc/rpc_manager.py +++ b/freqtrade/rpc/rpc_manager.py @@ -28,7 +28,7 @@ class RPCManager(object): self.telegram = None self._init() - def _init(self): + def _init(self) -> None: """ Init RPC modules :return: From 33ddc540cf7f3b10ec7ad0ef0e758d91e392802f Mon Sep 17 00:00:00 2001 From: gcarq Date: Sun, 18 Mar 2018 00:01:22 +0100 Subject: [PATCH 12/16] don't shadow built-in name tuple --- freqtrade/strategy/strategy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/strategy/strategy.py b/freqtrade/strategy/strategy.py index 17bdb2c1f..d7a89d1de 100644 --- a/freqtrade/strategy/strategy.py +++ b/freqtrade/strategy/strategy.py @@ -60,7 +60,7 @@ class Strategy(object): # Minimal ROI designed for the strategy self.minimal_roi = OrderedDict(sorted( {int(key): value for (key, value) in self.custom_strategy.minimal_roi.items()}.items(), - key=lambda tuple: tuple[0])) # sort after converting to number + key=lambda t: t[0])) # sort after converting to number # Optimal stoploss designed for the strategy self.stoploss = float(self.custom_strategy.stoploss) From f6df7df9bf43dd549e2e0c9ec20765bef686a463 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sun, 18 Mar 2018 00:02:02 +0100 Subject: [PATCH 13/16] modify args typehints --- freqtrade/arguments.py | 4 ++-- freqtrade/main.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index a73a1945f..c69135117 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -26,7 +26,7 @@ class Arguments(object): self.common_args_parser() self._build_subcommands() - def get_parsed_arg(self) -> List[str]: + def get_parsed_arg(self) -> argparse.Namespace: """ Return the list of arguments :return: List[str] List of arguments @@ -37,7 +37,7 @@ class Arguments(object): return self.parsed_arg - def parse_args(self) -> List[str]: + def parse_args(self) -> argparse.Namespace: """ Parses given arguments and returns an argparse Namespace instance. """ diff --git a/freqtrade/main.py b/freqtrade/main.py index 8deeb7da6..d2cfc6f9f 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -6,7 +6,7 @@ Read the documentation to know what cli arguments you need. import logging import sys -from typing import Dict +from typing import List from freqtrade import (__version__) from freqtrade.arguments import Arguments @@ -17,7 +17,7 @@ from freqtrade.logger import Logger logger = Logger(name='freqtrade').get_logger() -def main(sysargv: Dict) -> None: +def main(sysargv: List[str]) -> None: """ This function will initiate the bot and start the trading loop. :return: None From a5c62b5c1082f758438ca0dfd5addc0d7cb1eed5 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sun, 18 Mar 2018 00:27:57 +0100 Subject: [PATCH 14/16] rpc/rpc.py: fix indentation --- freqtrade/rpc/rpc.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 2d7af1b50..b4592f78a 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -196,11 +196,9 @@ class RPC(object): 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)\ + 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: From bc554faffb2736ecc9aafa34827d089bbb726955 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sun, 18 Mar 2018 02:46:18 +0100 Subject: [PATCH 15/16] plot_profit: add missing typehints and fix mutable argument issue --- scripts/plot_profit.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/plot_profit.py b/scripts/plot_profit.py index 68434f1fb..022bbf33c 100755 --- a/scripts/plot_profit.py +++ b/scripts/plot_profit.py @@ -13,7 +13,8 @@ Optional Cli parameters import sys import json -from typing import Dict +from argparse import Namespace +from typing import List, Optional import numpy as np from plotly import tools @@ -34,8 +35,11 @@ logger = Logger(name="Graph profits").get_logger() # data:: [ pair, profit-%, enter, exit, time, duration] # data:: ["BTC_ETH", 0.0023975, "1515598200", "1515602100", "2018-01-10 07:30:00+00:00", 65] -def make_profit_array(data, px, min_date, interval, filter_pairs=[]): +def make_profit_array( + data: List, px: int, min_date: int, + interval: int, filter_pairs: Optional[List] = None) -> np.ndarray: pg = np.zeros(px) + filter_pairs = filter_pairs or [] # Go through the trades # and make an total profit # array @@ -63,7 +67,7 @@ def make_profit_array(data, px, min_date, interval, filter_pairs=[]): return pg -def plot_profit(args) -> None: +def plot_profit(args: Namespace) -> None: """ Plots the total profit for all pairs. Note, the profit calculation isn't realistic. @@ -183,14 +187,14 @@ def plot_profit(args) -> None: plot(fig, filename='freqtrade-profit-plot.html') -def define_index(min_date, max_date, interval): +def define_index(min_date: int, max_date: int, interval: int) -> int: """ Return the index of a specific date """ return int((max_date - min_date) / (interval * 60)) -def plot_parse_args(args): +def plot_parse_args(args: List[str]) -> Namespace: """ Parse args passed to the script :param args: Cli arguments @@ -205,7 +209,7 @@ def plot_parse_args(args): return arguments.parse_args() -def main(sysargv: Dict) -> None: +def main(sysargv: List[str]) -> None: """ This function will initiate the bot and start the trading loop. :return: None From 3553686e502c4abadf39f4e3f9544dc1560ac3f5 Mon Sep 17 00:00:00 2001 From: gcarq Date: Sun, 18 Mar 2018 02:46:48 +0100 Subject: [PATCH 16/16] plot_dataframe: set missing typehints --- scripts/plot_dataframe.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/plot_dataframe.py b/scripts/plot_dataframe.py index e7a52b2bf..285ba6d97 100755 --- a/scripts/plot_dataframe.py +++ b/scripts/plot_dataframe.py @@ -13,8 +13,9 @@ Optional Cli parameters """ import sys +from argparse import Namespace -from typing import Dict +from typing import List from plotly import tools from plotly.offline import plot @@ -30,10 +31,9 @@ import freqtrade.optimize as optimize logger = Logger(name="Graph dataframe").get_logger() -def plot_analyzed_dataframe(args) -> None: +def plot_analyzed_dataframe(args: Namespace) -> None: """ Calls analyze() and plots the returned dataframe - :param pair: pair as str :return: None """ pair = args.pair.replace('-', '_') @@ -153,7 +153,7 @@ def plot_analyzed_dataframe(args) -> None: plot(fig, filename='freqtrade-plot.html') -def plot_parse_args(args): +def plot_parse_args(args: List[str]) -> Namespace: """ Parse args passed to the script :param args: Cli arguments @@ -168,7 +168,7 @@ def plot_parse_args(args): return arguments.parse_args() -def main(sysargv: Dict) -> None: +def main(sysargv: List[str]) -> None: """ This function will initiate the bot and start the trading loop. :return: None