Merge pull request #291 from gcarq/backtesting_speed_opt

Backtesting speed optimizations
This commit is contained in:
Gérald LONLAS 2018-01-02 23:35:47 -08:00 committed by GitHub
commit 9b09b5aa29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 19 deletions

View File

@ -5,7 +5,7 @@ import logging
from typing import Tuple, Dict
import arrow
from pandas import DataFrame
from pandas import DataFrame, Series
from tabulate import tabulate
from freqtrade import exchange
@ -19,20 +19,17 @@ from freqtrade.persistence import Trade
logger = logging.getLogger(__name__)
def get_timeframe(data: Dict[str, Dict]) -> Tuple[arrow.Arrow, arrow.Arrow]:
def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]:
"""
Get the maximum timeframe for the given backtest data
:param data: dictionary with backtesting data
:param data: dictionary with preprocessed backtesting data
:return: tuple containing min_date, max_date
"""
min_date, max_date = None, None
for values in data.values():
sorted_values = sorted(values, key=lambda d: arrow.get(d['T']))
if not min_date or sorted_values[0]['T'] < min_date:
min_date = sorted_values[0]['T']
if not max_date or sorted_values[-1]['T'] > max_date:
max_date = sorted_values[-1]['T']
return arrow.get(min_date), arrow.get(max_date)
all_dates = Series([])
for pair, pair_data in data.items():
all_dates = all_dates.append(pair_data['date'])
all_dates.sort_values(inplace=True)
return arrow.get(all_dates.iloc[0]), arrow.get(all_dates.iloc[-1])
def generate_text_table(
@ -84,7 +81,8 @@ def backtest(stake_amount: float, processed: Dict[str, DataFrame],
ticker = populate_sell_trend(populate_buy_trend(pair_data))
# for each buy point
lock_pair_until = None
for row in ticker[ticker.buy == 1].itertuples(index=True):
buy_subset = ticker[ticker.buy == 1][['buy', 'open', 'close', 'date', 'sell']]
for row in buy_subset.itertuples(index=True):
if realistic:
if lock_pair_until is not None and row.Index <= lock_pair_until:
continue
@ -106,7 +104,8 @@ def backtest(stake_amount: float, processed: Dict[str, DataFrame],
)
# calculate win/lose forwards from buy point
for row2 in ticker[row.Index + 1:].itertuples(index=True):
sell_subset = ticker[row.Index + 1:][['close', 'date', 'sell']]
for row2 in sell_subset.itertuples(index=True):
if max_open_trades > 0:
# Increase trade_count_lock for every iteration
trade_count_lock[row2.date] = trade_count_lock.get(row2.date, 0) + 1
@ -157,10 +156,6 @@ def start(args):
logger.info('Using stake_currency: %s ...', config['stake_currency'])
logger.info('Using stake_amount: %s ...', config['stake_amount'])
# Print timeframe
min_date, max_date = get_timeframe(data)
logger.info('Measuring data from %s up to %s ...', min_date.isoformat(), max_date.isoformat())
max_open_trades = 0
if args.realistic_simulation:
logger.info('Using max_open_trades: %s ...', config['max_open_trades'])
@ -170,9 +165,14 @@ def start(args):
from freqtrade import main
main._CONF = config
preprocessed = preprocess(data)
# Print timeframe
min_date, max_date = get_timeframe(preprocessed)
logger.info('Measuring data from %s up to %s ...', min_date.isoformat(), max_date.isoformat())
# Execute backtest and print results
results = backtest(
config['stake_amount'], preprocess(data), max_open_trades, args.realistic_simulation
config['stake_amount'], preprocessed, max_open_trades, args.realistic_simulation
)
logger.info(
'\n====================== BACKTESTING REPORT ================================\n%s',

View File

@ -5,6 +5,7 @@ import pandas as pd
# from unittest.mock import MagicMock
from freqtrade import exchange, optimize
from freqtrade.exchange import Bittrex
from freqtrade.optimize import preprocess
from freqtrade.optimize.backtesting import backtest, generate_text_table, get_timeframe
# import freqtrade.optimize.backtesting as backtesting
@ -27,7 +28,7 @@ def test_generate_text_table():
def test_get_timeframe():
data = optimize.load_data(ticker_interval=1, pairs=['BTC_UNITEST'])
data = preprocess(optimize.load_data(ticker_interval=1, pairs=['BTC_UNITEST']))
min_date, max_date = get_timeframe(data)
assert min_date.isoformat() == '2017-11-04T23:02:00+00:00'
assert max_date.isoformat() == '2017-11-14T22:59:00+00:00'