Merge pull request #563 from gcarq/feature/typehints

Set correct typehints and minor code cleanups
This commit is contained in:
Janne Sinivirta 2018-03-21 08:53:38 +02:00 committed by GitHub
commit 04c6474dd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 217 additions and 169 deletions

View File

@ -3,13 +3,15 @@ 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
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):
@ -96,9 +98,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 +108,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 +118,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 +141,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 +151,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:
"""

View File

@ -3,10 +3,10 @@ This module contains the argument manager class
"""
import argparse
import logging
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,11 +22,11 @@ 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()
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.
"""
@ -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.
"""

View File

@ -3,8 +3,9 @@ This module contains the configuration class
"""
import json
from argparse import Namespace
from typing import Dict, Any
from typing import Dict, List, 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()

View File

@ -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

View File

@ -5,12 +5,13 @@ e.g BTC to USD
import logging
import time
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
"""

View File

@ -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):
@ -27,7 +29,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()

View File

@ -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)

View File

@ -6,17 +6,18 @@ Read the documentation to know what cli arguments you need.
import logging
import sys
from typing import Dict
from freqtrade.configuration import Configuration
from typing import List
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()
def main(sysargv: Dict) -> None:
def main(sysargv: List[str]) -> None:
"""
This function will initiate the bot and start the trading loop.
:return: None

View File

@ -2,16 +2,19 @@
Various tool function for Freqtrade and scripts
"""
import re
import json
import logging
import re
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 = {}

View File

@ -1,20 +1,20 @@
# pragma pylint: disable=missing-docstring
import gzip
import json
import os
from typing import Optional, List, Dict
import gzip
from freqtrade.exchange import get_ticker_history
from typing import Optional, List, Dict, Tuple
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
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 = {}

View File

@ -3,18 +3,19 @@
"""
This module contains the backtesting logic
"""
from argparse import Namespace
from typing import Dict, Tuple, Any, List, Optional
from typing import Dict, Tuple, Any
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
@ -101,7 +102,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 +136,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 +277,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 +293,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()

View File

@ -10,6 +10,7 @@ import os
import pickle
import signal
import sys
from argparse import Namespace
from functools import reduce
from math import exp
from operator import itemgetter
@ -22,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
@ -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()

View File

@ -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

View File

@ -2,16 +2,19 @@
This module contains class to define a RPC communications
"""
from decimal import Decimal
from datetime import datetime, timedelta
from decimal import Decimal
from typing import Tuple, Any
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):
@ -30,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
@ -39,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:
@ -80,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:
@ -107,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):
@ -153,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.
"""
@ -190,15 +196,13 @@ 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))\
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`')
return True, '*Status:* `no closed trade`'
bp_pair, bp_rate = best_pair
@ -239,7 +243,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
"""
@ -248,7 +252,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
@ -275,17 +279,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):
"""
@ -293,18 +297,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 <id>.
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)
@ -326,13 +330,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(
@ -343,18 +347,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'),
@ -367,15 +371,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

View File

@ -28,7 +28,7 @@ class RPCManager(object):
self.telegram = None
self._init()
def _init(self):
def _init(self) -> None:
"""
Init RPC modules
:return:

View File

@ -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

View File

@ -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'

View File

@ -4,6 +4,7 @@ This module defines the interface to apply for strategies
"""
from abc import ABC, abstractmethod
from pandas import DataFrame

View File

@ -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')
@ -59,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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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())

View File

@ -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

View File

@ -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.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.misc import file_dump_json
from freqtrade.tests.conftest import log_has
# Change this if modifying BTC_UNITEST testdatafile

View File

@ -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):

View File

@ -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

View File

@ -1,6 +1,7 @@
# pragma pylint: disable=missing-docstring, protected-access, C0103
import logging
from freqtrade.strategy.strategy import Strategy

View File

@ -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'})

View File

@ -6,6 +6,7 @@ Unit test file for arguments.py
import argparse
import logging
import pytest
from freqtrade.arguments import Arguments

View File

@ -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

View File

@ -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']

View File

@ -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

View File

@ -1,4 +1,5 @@
import pandas as pd
from freqtrade.indicator_helpers import went_up, went_down

View File

@ -3,6 +3,7 @@ Unit test file for logger.py
"""
import logging
from freqtrade.logger import Logger

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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(

View File

@ -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

View File

@ -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