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 datetime import datetime, timedelta
from enum import Enum from enum import Enum
from typing import Dict, List from typing import Dict, List, Tuple
import arrow import arrow
from pandas import DataFrame, to_datetime from pandas import DataFrame, to_datetime
from freqtrade.exchange import get_ticker_history from freqtrade.exchange import get_ticker_history
from freqtrade.logger import Logger from freqtrade.logger import Logger
from freqtrade.strategy.strategy import Strategy
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.strategy.strategy import Strategy
class SignalType(Enum): class SignalType(Enum):
@ -96,9 +98,7 @@ class Analyze(object):
dataframe = self.populate_sell_trend(dataframe) dataframe = self.populate_sell_trend(dataframe)
return dataframe return dataframe
# FIX: Maybe return False, if an error has occured, def get_signal(self, pair: str, interval: int) -> Tuple[bool, bool]:
# Otherwise we might mask an error as an non-signal-scenario
def get_signal(self, pair: str, interval: int) -> (bool, bool):
""" """
Calculates current signal based several technical analysis indicators Calculates current signal based several technical analysis indicators
:param pair: pair in format BTC_ANT or BTC-ANT :param pair: pair in format BTC_ANT or BTC-ANT
@ -108,7 +108,7 @@ class Analyze(object):
ticker_hist = get_ticker_history(pair, interval) ticker_hist = get_ticker_history(pair, interval)
if not ticker_hist: if not ticker_hist:
self.logger.warning('Empty ticker history for pair %s', pair) self.logger.warning('Empty ticker history for pair %s', pair)
return (False, False) # return False ? return False, False
try: try:
dataframe = self.analyze_ticker(ticker_hist) dataframe = self.analyze_ticker(ticker_hist)
@ -118,18 +118,18 @@ class Analyze(object):
pair, pair,
str(error) str(error)
) )
return (False, False) # return False ? return False, False
except Exception as error: except Exception as error:
self.logger.exception( self.logger.exception(
'Unexpected error when analyzing ticker for pair %s: %s', 'Unexpected error when analyzing ticker for pair %s: %s',
pair, pair,
str(error) str(error)
) )
return (False, False) # return False ? return False, False
if dataframe.empty: if dataframe.empty:
self.logger.warning('Empty dataframe for pair %s', pair) self.logger.warning('Empty dataframe for pair %s', pair)
return (False, False) # return False ? return False, False
latest = dataframe.iloc[-1] latest = dataframe.iloc[-1]
@ -141,7 +141,7 @@ class Analyze(object):
pair, pair,
(arrow.utcnow() - signal_date).seconds // 60 (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 (buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1
self.logger.debug( self.logger.debug(
@ -151,7 +151,7 @@ class Analyze(object):
str(buy), str(buy),
str(sell) str(sell)
) )
return (buy, sell) return buy, sell
def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool, sell: bool) -> bool: 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 argparse
import logging
import os import os
import re import re
import logging from typing import List, Tuple, Optional
from typing import List
from freqtrade import __version__ from freqtrade import __version__
from freqtrade.constants import Constants from freqtrade.constants import Constants
@ -22,11 +22,11 @@ class Arguments(object):
self.parsed_arg = None self.parsed_arg = None
self.parser = argparse.ArgumentParser(description=description) self.parser = argparse.ArgumentParser(description=description)
def _load_args(self): def _load_args(self) -> None:
self.common_args_parser() self.common_args_parser()
self._build_subcommands() self._build_subcommands()
def get_parsed_arg(self) -> List[str]: def get_parsed_arg(self) -> argparse.Namespace:
""" """
Return the list of arguments Return the list of arguments
:return: List[str] List of arguments :return: List[str] List of arguments
@ -37,7 +37,7 @@ class Arguments(object):
return self.parsed_arg 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. Parses given arguments and returns an argparse Namespace instance.
""" """
@ -205,7 +205,7 @@ class Arguments(object):
self.hyperopt_options(hyperopt_cmd) self.hyperopt_options(hyperopt_cmd)
@staticmethod @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 Parse the value of the argument --timerange to determine what is the range desired
:param text: value from --timerange :param text: value from --timerange
@ -236,10 +236,10 @@ class Arguments(object):
stop = rvals[index] stop = rvals[index]
if stype[1] != 'date': if stype[1] != 'date':
stop = int(stop) stop = int(stop)
return (stype, start, stop) return stype, start, stop
raise Exception('Incorrect syntax for timerange "%s"' % text) raise Exception('Incorrect syntax for timerange "%s"' % text)
def scripts_options(self): def scripts_options(self) -> None:
""" """
Parses given arguments for plot scripts. Parses given arguments for plot scripts.
""" """

View File

@ -3,8 +3,9 @@ This module contains the configuration class
""" """
import json import json
from argparse import Namespace
from typing import Dict, Any
from typing import Dict, List, Any
from jsonschema import Draft4Validator, validate from jsonschema import Draft4Validator, validate
from jsonschema.exceptions import ValidationError, best_match from jsonschema.exceptions import ValidationError, best_match
@ -17,7 +18,7 @@ class Configuration(object):
Class to read and init the bot configuration Class to read and init the bot configuration
Reuse this class for the bot, backtesting, hyperopt and every script that required 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.args = args
self.logging = Logger(name=__name__) self.logging = Logger(name=__name__)
self.logger = self.logging.get_logger() self.logger = self.logging.get_logger()

View File

@ -1,8 +1,8 @@
import logging import logging
from typing import Dict, List, Optional 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 API_V1_1, API_V2_0
from bittrex.bittrex import Bittrex as _Bittrex
from requests.exceptions import ContentDecodingError from requests.exceptions import ContentDecodingError
from freqtrade import OperationalException from freqtrade import OperationalException

View File

@ -5,12 +5,13 @@ e.g BTC to USD
import logging import logging
import time import time
from coinmarketcap import Market from coinmarketcap import Market
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class CryptoFiat(): class CryptoFiat(object):
""" """
Object to describe what is the price of Crypto-currency in a FIAT Object to describe what is the price of Crypto-currency in a FIAT
""" """

View File

@ -6,11 +6,14 @@ import copy
import json import json
import time import time
import traceback import traceback
from typing import Dict, List, Optional, Any, Callable
from datetime import datetime from datetime import datetime
import requests from typing import Dict, List, Optional, Any, Callable
import arrow import arrow
import requests
from cachetools import cached, TTLCache from cachetools import cached, TTLCache
from freqtrade import (DependencyException, OperationalException, exchange, persistence)
from freqtrade.analyze import Analyze from freqtrade.analyze import Analyze
from freqtrade.constants import Constants from freqtrade.constants import Constants
from freqtrade.fiat_convert import CryptoToFiatConverter from freqtrade.fiat_convert import CryptoToFiatConverter
@ -18,7 +21,6 @@ from freqtrade.logger import Logger
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.rpc.rpc_manager import RPCManager from freqtrade.rpc.rpc_manager import RPCManager
from freqtrade.state import State from freqtrade.state import State
from freqtrade import (DependencyException, OperationalException, exchange, persistence)
class FreqtradeBot(object): class FreqtradeBot(object):
@ -27,7 +29,7 @@ class FreqtradeBot(object):
This is from here the bot start its logic. 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 Init all variables and object the bot need to work
:param config: configuration dict, you can use the Configuration.get_config() :param config: configuration dict, you can use the Configuration.get_config()

View File

@ -1,19 +1,19 @@
from math import exp, pi, sqrt, cos from math import exp, pi, sqrt, cos
import numpy import numpy as np
import talib as ta import talib as ta
from pandas import Series from pandas import Series
def went_up(series: Series) -> Series: def went_up(series: Series) -> bool:
return series > series.shift(1) return series > series.shift(1)
def went_down(series: Series) -> Series: def went_down(series: Series) -> bool:
return series < series.shift(1) 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 magic = pi * sqrt(2) / smoothing
a1 = exp(-magic) a1 = exp(-magic)
coeff2 = 2 * a1 * cos(magic) coeff2 = 2 * a1 * cos(magic)
@ -29,7 +29,7 @@ def ehlers_super_smoother(series: Series, smoothing: float = 6):
return filtered 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. """ Does a smoothed fishers inverse transformation.
Can be used with any oscillator that goes from 0 to 100 like RSI or MFI """ Can be used with any oscillator that goes from 0 to 100 like RSI or MFI """
v1 = 0.1 * (series - 50) v1 = 0.1 * (series - 50)
@ -37,4 +37,4 @@ def fishers_inverse(series: Series, smoothing: float = 0):
v2 = ta.WMA(v1.values, timeperiod=smoothing) v2 = ta.WMA(v1.values, timeperiod=smoothing)
else: else:
v2 = v1 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 logging
import sys import sys
from typing import Dict from typing import List
from freqtrade.configuration import Configuration
from freqtrade import (__version__)
from freqtrade.arguments import Arguments from freqtrade.arguments import Arguments
from freqtrade.configuration import Configuration
from freqtrade.freqtradebot import FreqtradeBot from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.logger import Logger from freqtrade.logger import Logger
from freqtrade import (__version__)
logger = Logger(name='freqtrade').get_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. This function will initiate the bot and start the trading loop.
:return: None :return: None

View File

@ -2,16 +2,19 @@
Various tool function for Freqtrade and scripts Various tool function for Freqtrade and scripts
""" """
import re
import json import json
import logging import logging
import re
from datetime import datetime from datetime import datetime
from typing import Dict
import numpy as np import numpy as np
from pandas import DataFrame
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def shorten_date(_date): def shorten_date(_date: str) -> str:
""" """
Trim the date so it fits on small screens Trim the date so it fits on small screens
""" """
@ -28,7 +31,7 @@ def shorten_date(_date):
# Matplotlib doesn't support ::datetime64, # # Matplotlib doesn't support ::datetime64, #
# so we need to convert it into ::datetime # # 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 Convert an pandas-array of timestamps into
An numpy-array of datetimes An numpy-array of datetimes
@ -42,10 +45,10 @@ def datesarray_to_datetimearray(dates):
return np.array(times) return np.array(times)
def common_datearray(dfs): def common_datearray(dfs: Dict[str, DataFrame]) -> np.ndarray:
""" """
Return dates from Dataframe Return dates from Dataframe
:param dfs: Dataframe :param dfs: Dict with format pair: pair_data
:return: List of dates :return: List of dates
""" """
alldates = {} alldates = {}

View File

@ -1,20 +1,20 @@
# pragma pylint: disable=missing-docstring # pragma pylint: disable=missing-docstring
import gzip
import json import json
import os import os
from typing import Optional, List, Dict from typing import Optional, List, Dict, Tuple
import gzip
from freqtrade.exchange import get_ticker_history
from freqtrade import misc from freqtrade import misc
from freqtrade.exchange import get_ticker_history
from freqtrade.logger import Logger from freqtrade.logger import Logger
from user_data.hyperopt_conf import hyperopt_optimize_conf from user_data.hyperopt_conf import hyperopt_optimize_conf
logger = Logger(name=__name__).get_logger() logger = Logger(name=__name__).get_logger()
def trim_tickerlist(tickerlist, timerange): def trim_tickerlist(tickerlist: List[Dict], timerange: Tuple[Tuple, int, int]) -> List[Dict]:
(stype, start, stop) = timerange stype, start, stop = timerange
if stype == (None, 'line'): if stype == (None, 'line'):
return tickerlist[stop:] return tickerlist[stop:]
elif stype == ('line', None): elif stype == ('line', None):
@ -25,7 +25,10 @@ def trim_tickerlist(tickerlist, timerange):
return tickerlist 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, Load a pair from file,
:return dict OR empty if unsuccesful :return dict OR empty if unsuccesful
@ -55,12 +58,12 @@ def load_tickerdata_file(datadir, pair, ticker_interval, timerange=None):
return pairdata return pairdata
def load_data(datadir: str, ticker_interval: int, pairs: Optional[List[str]] = None, def load_data(datadir: str, ticker_interval: int,
refresh_pairs: Optional[bool] = False, timerange=None) -> Dict[str, List]: 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 Loads ticker history data for the given parameters
:param ticker_interval: ticker interval in minutes
:param pairs: list of pairs
:return: dict :return: dict
""" """
result = {} result = {}

View File

@ -3,18 +3,19 @@
""" """
This module contains the backtesting logic 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 import arrow
from pandas import DataFrame, Series from pandas import DataFrame, Series
from tabulate import tabulate from tabulate import tabulate
import freqtrade.optimize as optimize 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 import exchange
from freqtrade.analyze import Analyze 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.logger import Logger
from freqtrade.misc import file_dump_json from freqtrade.misc import file_dump_json
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
@ -101,7 +102,10 @@ class Backtesting(object):
]) ])
return tabulate(tabular_data, headers=headers, floatfmt=floatfmt) 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'] stake_amount = args['stake_amount']
max_open_trades = args.get('max_open_trades', 0) max_open_trades = args.get('max_open_trades', 0)
trade = Trade( trade = Trade(
@ -132,7 +136,7 @@ class Backtesting(object):
sell_row.date sell_row.date
return None return None
def backtest(self, args) -> DataFrame: def backtest(self, args: Dict) -> DataFrame:
""" """
Implements backtesting functionality 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 Prepare the configuration for the backtesting
:param args: Cli args from Arguments() :param args: Cli args from Arguments()
@ -289,7 +293,7 @@ def setup_configuration(args) -> Dict[str, Any]:
return config return config
def start(args) -> None: def start(args: Namespace) -> None:
""" """
Start Backtesting script Start Backtesting script
:param args: Cli args from Arguments() :param args: Cli args from Arguments()

View File

@ -10,6 +10,7 @@ import os
import pickle import pickle
import signal import signal
import sys import sys
from argparse import Namespace
from functools import reduce from functools import reduce
from math import exp from math import exp
from operator import itemgetter from operator import itemgetter
@ -22,11 +23,11 @@ from hyperopt.mongoexp import MongoTrials
from pandas import DataFrame from pandas import DataFrame
import freqtrade.vendor.qtpylib.indicators as qtpylib 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.arguments import Arguments
from freqtrade.optimize.backtesting import Backtesting from freqtrade.configuration import Configuration
from freqtrade.logger import Logger 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 from user_data.hyperopt_conf import hyperopt_optimize_conf
@ -240,7 +241,7 @@ class Hyperopt(Backtesting):
return trade_loss + profit_loss + duration_loss return trade_loss + profit_loss + duration_loss
@staticmethod @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 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 Tell if a space value is contained in the configuration
""" """
@ -433,7 +434,7 @@ class Hyperopt(Backtesting):
return populate_buy_trend return populate_buy_trend
def generate_optimizer(self, params) -> Dict: def generate_optimizer(self, params: Dict) -> Dict:
if self.has_space('roi'): if self.has_space('roi'):
self.analyze.strategy.minimal_roi = self.generate_roi_table(params) self.analyze.strategy.minimal_roi = self.generate_roi_table(params)
@ -496,7 +497,7 @@ class Hyperopt(Backtesting):
results.duration.mean(), results.duration.mean(),
) )
def start(self): def start(self) -> None:
timerange = Arguments.parse_timerange(self.config.get('timerange')) timerange = Arguments.parse_timerange(self.config.get('timerange'))
data = load_data( data = load_data(
datadir=self.config.get('datadir'), datadir=self.config.get('datadir'),
@ -571,7 +572,7 @@ class Hyperopt(Backtesting):
# Store trials result to file to resume next time # Store trials result to file to resume next time
self.save_trials() self.save_trials()
def signal_handler(self, sig, frame): def signal_handler(self, sig, frame) -> None:
""" """
Hyperopt SIGINT handler Hyperopt SIGINT handler
""" """
@ -585,7 +586,7 @@ class Hyperopt(Backtesting):
sys.exit(0) sys.exit(0)
def start(args) -> None: def start(args: Namespace) -> None:
""" """
Start Backtesting script Start Backtesting script
:param args: Cli args from Arguments() :param args: Cli args from Arguments()

View File

@ -207,6 +207,7 @@ class Trade(_DECL_BASE):
Calculates the profit in percentage (including fee). Calculates the profit in percentage (including fee).
:param rate: rate to compare with (optional). :param rate: rate to compare with (optional).
If rate is not set self.close_rate will be used 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 :return: profit in percentage as float
""" """
getcontext().prec = 8 getcontext().prec = 8

View File

@ -2,16 +2,19 @@
This module contains class to define a RPC communications This module contains class to define a RPC communications
""" """
from decimal import Decimal
from datetime import datetime, timedelta from datetime import datetime, timedelta
from decimal import Decimal
from typing import Tuple, Any
import arrow import arrow
from pandas import DataFrame
import sqlalchemy as sql import sqlalchemy as sql
from pandas import DataFrame
from freqtrade import exchange
from freqtrade.logger import Logger from freqtrade.logger import Logger
from freqtrade.misc import shorten_date
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.state import State from freqtrade.state import State
from freqtrade import exchange
from freqtrade.misc import shorten_date
class RPC(object): class RPC(object):
@ -30,7 +33,7 @@ class RPC(object):
level=self.freqtrade.config.get('loglevel') level=self.freqtrade.config.get('loglevel')
).get_logger() ).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 Below follows the RPC backend it is prefixed with rpc_ to raise awareness that it is
a remotely exposed function a remotely exposed function
@ -39,9 +42,9 @@ class RPC(object):
# Fetch open trade # Fetch open trade
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
if self.freqtrade.get_state() != State.RUNNING: if self.freqtrade.get_state() != State.RUNNING:
return (True, '*Status:* `trader is not running`') return True, '*Status:* `trader is not running`'
elif not trades: elif not trades:
return (True, '*Status:* `no active trade`') return True, '*Status:* `no active trade`'
else: else:
result = [] result = []
for trade in trades: for trade in trades:
@ -80,14 +83,14 @@ class RPC(object):
) if order else None, ) if order else None,
) )
result.append(message) 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() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
if self.freqtrade.get_state() != State.RUNNING: if self.freqtrade.get_state() != State.RUNNING:
return (True, '*Status:* `trader is not running`') return True, '*Status:* `trader is not running`'
elif not trades: elif not trades:
return (True, '*Status:* `no active order`') return True, '*Status:* `no active order`'
else: else:
trades_list = [] trades_list = []
for trade in trades: for trade in trades:
@ -107,14 +110,16 @@ class RPC(object):
# consisting of (error_occured?, result) # consisting of (error_occured?, result)
# Another approach would be to just return the # Another approach would be to just return the
# result, or raise error # 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() today = datetime.utcnow().date()
profit_days = {} profit_days = {}
if not (isinstance(timescale, int) and timescale > 0): 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 fiat = self.freqtrade.fiat_converter
for day in range(0, timescale): for day in range(0, timescale):
@ -153,9 +158,10 @@ class RPC(object):
] ]
for key, value in profit_days.items() 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. :return: cumulative profit statistics.
""" """
@ -190,15 +196,13 @@ class RPC(object):
profit_all_percent.append(profit_percent) profit_all_percent.append(profit_percent)
best_pair = Trade.session.query( best_pair = Trade.session.query(
Trade.pair, Trade.pair, sql.func.sum(Trade.close_profit).label('profit_sum')
sql.func.sum(Trade.close_profit).label('profit_sum') ).filter(Trade.is_open.is_(False)) \
)\ .group_by(Trade.pair) \
.filter(Trade.is_open.is_(False))\
.group_by(Trade.pair)\
.order_by(sql.text('profit_sum DESC')).first() .order_by(sql.text('profit_sum DESC')).first()
if not best_pair: if not best_pair:
return (True, '*Status:* `no closed trade`') return True, '*Status:* `no closed trade`'
bp_pair, bp_rate = best_pair 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 :return: current account balance per crypto
""" """
@ -248,7 +252,7 @@ class RPC(object):
if c['Balance'] or c['Available'] or c['Pending'] if c['Balance'] or c['Available'] or c['Pending']
] ]
if not balances: if not balances:
return (True, '`All balances are zero.`') return True, '`All balances are zero.`'
output = [] output = []
total = 0.0 total = 0.0
@ -275,17 +279,17 @@ class RPC(object):
fiat = self.freqtrade.fiat_converter fiat = self.freqtrade.fiat_converter
symbol = fiat_display_currency symbol = fiat_display_currency
value = fiat.convert_amount(total, 'BTC', symbol) 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): def rpc_start(self) -> (bool, str):
""" """
Handler for start. Handler for start.
""" """
if self.freqtrade.get_state() == State.RUNNING: if self.freqtrade.get_state() == State.RUNNING:
return (True, '*Status:* `already running`') return True, '*Status:* `already running`'
self.freqtrade.update_state(State.RUNNING) self.freqtrade.update_state(State.RUNNING)
return (False, '`Starting trader ...`') return False, '`Starting trader ...`'
def rpc_stop(self) -> (bool, str): def rpc_stop(self) -> (bool, str):
""" """
@ -293,18 +297,18 @@ class RPC(object):
""" """
if self.freqtrade.get_state() == State.RUNNING: if self.freqtrade.get_state() == State.RUNNING:
self.freqtrade.update_state(State.STOPPED) 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!!!! # 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>. Handler for forcesell <id>.
Sells the given trade at current price Sells the given trade at current price
:return: error or None :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 # Check if there is there is an open order
if trade.open_order_id: if trade.open_order_id:
order = exchange.get_order(trade.open_order_id) order = exchange.get_order(trade.open_order_id)
@ -326,13 +330,13 @@ class RPC(object):
# ---- EOF def _exec_forcesell ---- # ---- EOF def _exec_forcesell ----
if self.freqtrade.get_state() != State.RUNNING: if self.freqtrade.get_state() != State.RUNNING:
return (True, '`trader is not running`') return True, '`trader is not running`'
if trade_id == 'all': if trade_id == 'all':
# Execute sell for all open orders # Execute sell for all open orders
for trade in Trade.query.filter(Trade.is_open.is_(True)).all(): for trade in Trade.query.filter(Trade.is_open.is_(True)).all():
_exec_forcesell(trade) _exec_forcesell(trade)
return (False, '') return False, ''
# Query for trade # Query for trade
trade = Trade.query.filter( trade = Trade.query.filter(
@ -343,18 +347,18 @@ class RPC(object):
).first() ).first()
if not trade: if not trade:
self.logger.warning('forcesell: Invalid argument received') self.logger.warning('forcesell: Invalid argument received')
return (True, 'Invalid argument.') return True, 'Invalid argument.'
_exec_forcesell(trade) _exec_forcesell(trade)
return (False, '') return False, ''
def rpc_performance(self) -> None: def rpc_performance(self) -> Tuple[bool, Any]:
""" """
Handler for performance. Handler for performance.
Shows a performance statistic from finished trades Shows a performance statistic from finished trades
""" """
if self.freqtrade.get_state() != State.RUNNING: 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, pair_rates = Trade.session.query(Trade.pair,
sql.func.sum(Trade.close_profit).label('profit_sum'), sql.func.sum(Trade.close_profit).label('profit_sum'),
@ -367,15 +371,15 @@ class RPC(object):
for (pair, rate, count) in pair_rates: for (pair, rate, count) in pair_rates:
trades.append({'pair': pair, 'profit': round(rate * 100, 2), 'count': count}) 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 Returns the number of trades running
:return: None :return: None
""" """
if self.freqtrade.get_state() != State.RUNNING: 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() 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.telegram = None
self._init() self._init()
def _init(self): def _init(self) -> None:
""" """
Init RPC modules Init RPC modules
:return: :return:

View File

@ -5,10 +5,12 @@ This module manage Telegram communication
""" """
from typing import Any, Callable from typing import Any, Callable
from tabulate import tabulate from tabulate import tabulate
from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update
from telegram.error import NetworkError, TelegramError from telegram.error import NetworkError, TelegramError
from telegram.ext import CommandHandler, Updater from telegram.ext import CommandHandler, Updater
from freqtrade.__init__ import __version__ from freqtrade.__init__ import __version__
from freqtrade.rpc.rpc import RPC from freqtrade.rpc.rpc import RPC

View File

@ -2,9 +2,10 @@
import talib.abstract as ta import talib.abstract as ta
from pandas import DataFrame from pandas import DataFrame
import freqtrade.vendor.qtpylib.indicators as qtpylib import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.strategy.interface import IStrategy
from freqtrade.indicator_helpers import fishers_inverse from freqtrade.indicator_helpers import fishers_inverse
from freqtrade.strategy.interface import IStrategy
class_name = 'DefaultStrategy' class_name = 'DefaultStrategy'

View File

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

View File

@ -7,11 +7,12 @@ import importlib
import os import os
import sys import sys
from collections import OrderedDict 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') sys.path.insert(0, r'../../user_data/strategies')
@ -59,7 +60,7 @@ class Strategy(object):
# Minimal ROI designed for the strategy # Minimal ROI designed for the strategy
self.minimal_roi = OrderedDict(sorted( self.minimal_roi = OrderedDict(sorted(
{int(key): value for (key, value) in self.custom_strategy.minimal_roi.items()}.items(), {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 # Optimal stoploss designed for the strategy
self.stoploss = float(self.custom_strategy.stoploss) self.stoploss = float(self.custom_strategy.stoploss)

View File

@ -1,14 +1,15 @@
# pragma pylint: disable=missing-docstring # pragma pylint: disable=missing-docstring
from datetime import datetime
from unittest.mock import MagicMock
from functools import reduce
import logging
import json import json
import logging
from datetime import datetime
from functools import reduce
from unittest.mock import MagicMock
import arrow import arrow
import pytest import pytest
from jsonschema import validate from jsonschema import validate
from telegram import Chat, Message, Update
from sqlalchemy import create_engine from sqlalchemy import create_engine
from telegram import Chat, Message, Update
from freqtrade.analyze import Analyze from freqtrade.analyze import Analyze
from freqtrade.constants import Constants from freqtrade.constants import Constants

View File

@ -1,15 +1,16 @@
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement # pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
# pragma pylint: disable=protected-access # pragma pylint: disable=protected-access
from unittest.mock import MagicMock
from random import randint
import logging import logging
from requests.exceptions import RequestException from random import randint
import pytest from unittest.mock import MagicMock
import pytest
from requests.exceptions import RequestException
import freqtrade.exchange as exchange
from freqtrade import OperationalException from freqtrade import OperationalException
from freqtrade.exchange import init, validate_pairs, buy, sell, get_balance, get_balances, \ from freqtrade.exchange import init, validate_pairs, buy, sell, get_balance, get_balances, \
get_ticker, get_ticker_history, cancel_order, get_name, get_fee get_ticker, get_ticker_history, cancel_order, get_name, get_fee
import freqtrade.exchange as exchange
from freqtrade.tests.conftest import log_has from freqtrade.tests.conftest import log_has
API_INIT = False API_INIT = False

View File

@ -1,10 +1,12 @@
# pragma pylint: disable=missing-docstring, C0103, protected-access, unused-argument # pragma pylint: disable=missing-docstring, C0103, protected-access, unused-argument
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
from requests.exceptions import ContentDecodingError from requests.exceptions import ContentDecodingError
from freqtrade.exchange.bittrex import Bittrex
import freqtrade.exchange.bittrex as btx import freqtrade.exchange.bittrex as btx
from freqtrade.exchange.bittrex import Bittrex
# Eat this flake8 # Eat this flake8

View File

@ -1,20 +1,21 @@
# pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument # pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument
import json import json
import random
import math import math
from typing import List import random
from copy import deepcopy from copy import deepcopy
from typing import List
from unittest.mock import MagicMock 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 # Avoid to reinit the same object again and again
_BACKTESTING = Backtesting(default_conf()) _BACKTESTING = Backtesting(default_conf())

View File

@ -3,6 +3,7 @@ import json
import os import os
from copy import deepcopy from copy import deepcopy
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pandas as pd import pandas as pd
from freqtrade.optimize.__init__ import load_tickerdata_file from freqtrade.optimize.__init__ import load_tickerdata_file

View File

@ -1,13 +1,14 @@
# pragma pylint: disable=missing-docstring, protected-access, C0103 # pragma pylint: disable=missing-docstring, protected-access, C0103
import os
import json import json
import os
import uuid import uuid
from shutil import copyfile from shutil import copyfile
from freqtrade import optimize 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.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 from freqtrade.tests.conftest import log_has
# Change this if modifying BTC_UNITEST testdatafile # Change this if modifying BTC_UNITEST testdatafile

View File

@ -6,23 +6,23 @@ Unit test file for rpc/telegram.py
""" """
import re import re
from copy import deepcopy
from datetime import datetime from datetime import datetime
from random import randint from random import randint
from unittest.mock import MagicMock from unittest.mock import MagicMock
from copy import deepcopy
from sqlalchemy import create_engine from sqlalchemy import create_engine
from telegram import Update, Message, Chat from telegram import Update, Message, Chat
from telegram.error import NetworkError from telegram.error import NetworkError
from freqtrade import __version__ from freqtrade import __version__
from freqtrade.rpc.telegram import authorized_only
from freqtrade.freqtradebot import FreqtradeBot from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.rpc.telegram import Telegram
from freqtrade.persistence import Trade 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.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.conftest import get_patched_freqtradebot, log_has
from freqtrade.tests.test_freqtradebot import patch_get_signal, patch_coinmarketcap
class DummyCls(Telegram): class DummyCls(Telegram):

View File

@ -1,8 +1,10 @@
import json import json
import pytest import pytest
from pandas import DataFrame from pandas import DataFrame
from freqtrade.strategy.default_strategy import DefaultStrategy, class_name
from freqtrade.analyze import Analyze from freqtrade.analyze import Analyze
from freqtrade.strategy.default_strategy import DefaultStrategy, class_name
@pytest.fixture @pytest.fixture

View File

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

View File

@ -5,8 +5,9 @@ Unit test file for analyse.py
""" """
import datetime import datetime
from unittest.mock import MagicMock
import logging import logging
from unittest.mock import MagicMock
import arrow import arrow
from pandas import DataFrame from pandas import DataFrame
@ -14,7 +15,6 @@ from freqtrade.analyze import Analyze, SignalType
from freqtrade.optimize.__init__ import load_tickerdata_file from freqtrade.optimize.__init__ import load_tickerdata_file
from freqtrade.tests.conftest import log_has from freqtrade.tests.conftest import log_has
# Avoid to reinit the same object again and again # Avoid to reinit the same object again and again
_ANALYZE = Analyze({'strategy': 'default_strategy'}) _ANALYZE = Analyze({'strategy': 'default_strategy'})

View File

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

View File

@ -4,10 +4,10 @@
Unit test file for configuration.py Unit test file for configuration.py
""" """
import json import json
from copy import deepcopy from copy import deepcopy
import pytest
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest
from jsonschema import ValidationError from jsonschema import ValidationError
from freqtrade.arguments import Arguments from freqtrade.arguments import Arguments

View File

@ -2,8 +2,8 @@
import pandas import pandas
from freqtrade.optimize import load_data
from freqtrade.analyze import Analyze from freqtrade.analyze import Analyze
from freqtrade.optimize import load_data
from freqtrade.strategy.strategy import Strategy from freqtrade.strategy.strategy import Strategy
_pairs = ['BTC_ETH'] _pairs = ['BTC_ETH']

View File

@ -5,22 +5,23 @@ Unit test file for freqtradebot.py
""" """
import logging import logging
import re
import time import time
from unittest.mock import MagicMock
from copy import deepcopy from copy import deepcopy
from typing import Dict, Optional from typing import Dict, Optional
from unittest.mock import MagicMock
import arrow import arrow
import pytest import pytest
import requests import requests
import re
from sqlalchemy import create_engine from sqlalchemy import create_engine
from freqtrade.tests.conftest import log_has
from freqtrade import DependencyException, OperationalException from freqtrade import DependencyException, OperationalException
from freqtrade.exchange import Exchanges from freqtrade.exchange import Exchanges
from freqtrade.freqtradebot import FreqtradeBot from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.state import State
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.state import State
from freqtrade.tests.conftest import log_has
# Functions for recurrent object patching # Functions for recurrent object patching

View File

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

View File

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

View File

@ -4,6 +4,7 @@ Unit test file for main.py
import logging import logging
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
from freqtrade.main import main, set_loggers from freqtrade.main import main, set_loggers

View File

@ -6,10 +6,11 @@ Unit test file for misc.py
import datetime import datetime
from unittest.mock import MagicMock from unittest.mock import MagicMock
from freqtrade.analyze import Analyze from freqtrade.analyze import Analyze
from freqtrade.optimize.__init__ import load_tickerdata_file
from freqtrade.misc import (shorten_date, datesarray_to_datetimearray, from freqtrade.misc import (shorten_date, datesarray_to_datetimearray,
common_datearray, file_dump_json) common_datearray, file_dump_json)
from freqtrade.optimize.__init__ import load_tickerdata_file
def test_shorten_date() -> None: def test_shorten_date() -> None:

View File

@ -1,7 +1,9 @@
# pragma pylint: disable=missing-docstring, C0103 # pragma pylint: disable=missing-docstring, C0103
import os import os
import pytest import pytest
from sqlalchemy import create_engine from sqlalchemy import create_engine
from freqtrade.exchange import Exchanges from freqtrade.exchange import Exchanges
from freqtrade.persistence import Trade, init, clean_dry_run_db from freqtrade.persistence import Trade, init, clean_dry_run_db

View File

@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""This script generate json data from bittrex""" """This script generate json data from bittrex"""
import sys
import json import json
import sys
from freqtrade import exchange from freqtrade import exchange
from freqtrade.exchange import Bittrex
from freqtrade import misc from freqtrade import misc
from freqtrade.exchange import Bittrex
parser = misc.common_args_parser('download utility') parser = misc.common_args_parser('download utility')
parser.add_argument( parser.add_argument(

View File

@ -13,8 +13,9 @@ Optional Cli parameters
""" """
import sys import sys
from argparse import Namespace
from typing import Dict from typing import List
from plotly import tools from plotly import tools
from plotly.offline import plot from plotly.offline import plot
@ -30,10 +31,9 @@ import freqtrade.optimize as optimize
logger = Logger(name="Graph dataframe").get_logger() 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 Calls analyze() and plots the returned dataframe
:param pair: pair as str
:return: None :return: None
""" """
pair = args.pair.replace('-', '_') pair = args.pair.replace('-', '_')
@ -153,7 +153,7 @@ def plot_analyzed_dataframe(args) -> None:
plot(fig, filename='freqtrade-plot.html') 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 Parse args passed to the script
:param args: Cli arguments :param args: Cli arguments
@ -168,7 +168,7 @@ def plot_parse_args(args):
return arguments.parse_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. This function will initiate the bot and start the trading loop.
:return: None :return: None

View File

@ -13,7 +13,8 @@ Optional Cli parameters
import sys import sys
import json import json
from typing import Dict from argparse import Namespace
from typing import List, Optional
import numpy as np import numpy as np
from plotly import tools from plotly import tools
@ -34,8 +35,11 @@ logger = Logger(name="Graph profits").get_logger()
# data:: [ pair, profit-%, enter, exit, time, duration] # data:: [ pair, profit-%, enter, exit, time, duration]
# data:: ["BTC_ETH", 0.0023975, "1515598200", "1515602100", "2018-01-10 07:30:00+00:00", 65] # 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) pg = np.zeros(px)
filter_pairs = filter_pairs or []
# Go through the trades # Go through the trades
# and make an total profit # and make an total profit
# array # array
@ -63,7 +67,7 @@ def make_profit_array(data, px, min_date, interval, filter_pairs=[]):
return pg return pg
def plot_profit(args) -> None: def plot_profit(args: Namespace) -> None:
""" """
Plots the total profit for all pairs. Plots the total profit for all pairs.
Note, the profit calculation isn't realistic. Note, the profit calculation isn't realistic.
@ -183,14 +187,14 @@ def plot_profit(args) -> None:
plot(fig, filename='freqtrade-profit-plot.html') 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 the index of a specific date
""" """
return int((max_date - min_date) / (interval * 60)) 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 Parse args passed to the script
:param args: Cli arguments :param args: Cli arguments
@ -205,7 +209,7 @@ def plot_parse_args(args):
return arguments.parse_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. This function will initiate the bot and start the trading loop.
:return: None :return: None