Merge with develop

This commit is contained in:
Anton
2018-06-04 01:50:10 +03:00
39 changed files with 506 additions and 250 deletions

View File

@@ -4,8 +4,8 @@ import gzip
import json
import logging
import os
from typing import Optional, List, Dict, Tuple, Any
import arrow
from typing import Optional, List, Dict, Tuple
from freqtrade import misc, constants
from freqtrade.exchange import get_ticker_history
@@ -29,7 +29,7 @@ def trim_tickerlist(tickerlist: List[Dict], timerange: Tuple[Tuple, int, int]) -
if stype[0] == 'index':
start_index = start
elif stype[0] == 'date':
while tickerlist[start_index][0] < start * 1000:
while start_index < len(tickerlist) and tickerlist[start_index][0] < start * 1000:
start_index += 1
if stype[1] == 'line':
@@ -37,7 +37,7 @@ def trim_tickerlist(tickerlist: List[Dict], timerange: Tuple[Tuple, int, int]) -
if stype[1] == 'index':
stop_index = stop
elif stype[1] == 'date':
while tickerlist[stop_index-1][0] > stop * 1000:
while stop_index > 0 and tickerlist[stop_index-1][0] > stop * 1000:
stop_index -= 1
if start_index > stop_index:
@@ -100,15 +100,16 @@ def load_data(datadir: str,
for pair in _pairs:
pairdata = load_tickerdata_file(datadir, pair, ticker_interval, timerange=timerange)
if not pairdata:
# download the tickerdata from exchange
download_backtesting_testdata(datadir,
pair=pair,
tick_interval=ticker_interval,
timerange=timerange)
# and retry reading the pair
pairdata = load_tickerdata_file(datadir, pair, ticker_interval, timerange=timerange)
result[pair] = pairdata
if pairdata:
result[pair] = pairdata
else:
logger.warning(
'No data for pair: "%s", Interval: %s. '
'Use --refresh-pairs-cached to download the data',
pair,
ticker_interval
)
return result
@@ -143,7 +144,9 @@ def download_pairs(datadir, pairs: List[str],
def load_cached_data_for_updating(filename: str,
tick_interval: str,
timerange: Optional[Tuple[Tuple, int, int]]) -> Tuple[list, int]:
timerange: Optional[Tuple[Tuple, int, int]]) -> Tuple[
List[Any],
Optional[int]]:
"""
Load cached data and choose what part of the data should be updated
"""

View File

@@ -33,18 +33,6 @@ class Backtesting(object):
"""
def __init__(self, config: Dict[str, Any]) -> None:
self.config = config
self.analyze = None
self.ticker_interval = None
self.tickerdata_to_dataframe = None
self.populate_buy_trend = None
self.populate_sell_trend = None
self._init()
def _init(self) -> None:
"""
Init objects required for backtesting
:return: None
"""
self.analyze = Analyze(self.config)
self.ticker_interval = self.analyze.strategy.ticker_interval
self.tickerdata_to_dataframe = self.analyze.tickerdata_to_dataframe
@@ -78,7 +66,7 @@ class Backtesting(object):
Generates and returns a text table for the given backtest data and the results dataframe
:return: pretty printed table with tabulate as str
"""
stake_currency = self.config.get('stake_currency')
stake_currency = str(self.config.get('stake_currency'))
floatfmt = ('s', 'd', '.2f', '.8f', '.1f')
tabular_data = []
@@ -106,7 +94,7 @@ class Backtesting(object):
len(results[results.profit_BTC > 0]),
len(results[results.profit_BTC < 0])
])
return tabulate(tabular_data, headers=headers, floatfmt=floatfmt)
return tabulate(tabular_data, headers=headers, floatfmt=floatfmt, tablefmt="pipe")
def _get_sell_trade_entry(
self, pair: str, buy_row: DataFrame,
@@ -168,7 +156,7 @@ class Backtesting(object):
record = args.get('record', None)
records = []
trades = []
trade_count_lock = {}
trade_count_lock: Dict = {}
for pair, pair_data in processed.items():
pair_data['buy'], pair_data['sell'] = 0, 0 # cleanup from previous run
@@ -230,8 +218,9 @@ class Backtesting(object):
else:
logger.info('Using local backtesting data (using whitelist in given config) ...')
timerange = Arguments.parse_timerange(self.config.get('timerange'))
data = optimize.load_data(
timerange = Arguments.parse_timerange(None if self.config.get(
'timerange') is None else str(self.config.get('timerange')))
data = optimize.load_data( # type: ignore # timerange will be refactored
self.config['datadir'],
pairs=pairs,
ticker_interval=self.ticker_interval,

View File

@@ -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
from typing import Dict, Any, Callable, Optional
import numpy
import talib.abstract as ta
@@ -60,7 +60,7 @@ class Hyperopt(Backtesting):
self.expected_max_profit = 3.0
# Configuration and data used by hyperopt
self.processed = None
self.processed: Optional[Dict[str, Any]] = None
# Hyperopt Trials
self.trials_file = os.path.join('user_data', 'hyperopt_trials.pickle')
@@ -344,7 +344,7 @@ class Hyperopt(Backtesting):
"""
Return the space to use during Hyperopt
"""
spaces = {}
spaces: Dict = {}
if self.has_space('buy'):
spaces = {**spaces, **Hyperopt.indicator_space()}
if self.has_space('roi'):
@@ -455,6 +455,7 @@ class Hyperopt(Backtesting):
if trade_count == 0 or trade_duration > self.max_accepted_trade_duration:
print('.', end='')
sys.stdout.flush()
return {
'status': STATUS_FAIL,
'loss': float('inf')
@@ -479,31 +480,32 @@ class Hyperopt(Backtesting):
'result': result_explanation,
}
@staticmethod
def format_results(results: DataFrame) -> str:
def format_results(self, results: DataFrame) -> str:
"""
Return the format result in a string
"""
return ('{:6d} trades. Avg profit {: 5.2f}%. '
'Total profit {: 11.8f} BTC ({:.4f}Σ%). Avg duration {:5.1f} mins.').format(
'Total profit {: 11.8f} {} ({:.4f}Σ%). Avg duration {:5.1f} mins.').format(
len(results.index),
results.profit_percent.mean() * 100.0,
results.profit_BTC.sum(),
self.config['stake_currency'],
results.profit_percent.sum(),
results.duration.mean(),
)
def start(self) -> None:
timerange = Arguments.parse_timerange(self.config.get('timerange'))
data = load_data(
datadir=self.config.get('datadir'),
timerange = Arguments.parse_timerange(None if self.config.get(
'timerange') is None else str(self.config.get('timerange')))
data = load_data( # type: ignore # timerange will be refactored
datadir=str(self.config.get('datadir')),
pairs=self.config['exchange']['pair_whitelist'],
ticker_interval=self.ticker_interval,
timerange=timerange
)
if self.has_space('buy'):
self.analyze.populate_indicators = Hyperopt.populate_indicators
self.analyze.populate_indicators = Hyperopt.populate_indicators # type: ignore
self.processed = self.tickerdata_to_dataframe(data)
if self.config.get('mongodb'):