mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 18:23:55 +00:00
Merge pull request #291 from gcarq/backtesting_speed_opt
Backtesting speed optimizations
This commit is contained in:
commit
9b09b5aa29
|
@ -5,7 +5,7 @@ import logging
|
||||||
from typing import Tuple, Dict
|
from typing import Tuple, Dict
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame, Series
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
from freqtrade import exchange
|
from freqtrade import exchange
|
||||||
|
@ -19,20 +19,17 @@ from freqtrade.persistence import Trade
|
||||||
logger = logging.getLogger(__name__)
|
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
|
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
|
:return: tuple containing min_date, max_date
|
||||||
"""
|
"""
|
||||||
min_date, max_date = None, None
|
all_dates = Series([])
|
||||||
for values in data.values():
|
for pair, pair_data in data.items():
|
||||||
sorted_values = sorted(values, key=lambda d: arrow.get(d['T']))
|
all_dates = all_dates.append(pair_data['date'])
|
||||||
if not min_date or sorted_values[0]['T'] < min_date:
|
all_dates.sort_values(inplace=True)
|
||||||
min_date = sorted_values[0]['T']
|
return arrow.get(all_dates.iloc[0]), arrow.get(all_dates.iloc[-1])
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
def generate_text_table(
|
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))
|
ticker = populate_sell_trend(populate_buy_trend(pair_data))
|
||||||
# for each buy point
|
# for each buy point
|
||||||
lock_pair_until = None
|
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 realistic:
|
||||||
if lock_pair_until is not None and row.Index <= lock_pair_until:
|
if lock_pair_until is not None and row.Index <= lock_pair_until:
|
||||||
continue
|
continue
|
||||||
|
@ -106,7 +104,8 @@ def backtest(stake_amount: float, processed: Dict[str, DataFrame],
|
||||||
)
|
)
|
||||||
|
|
||||||
# calculate win/lose forwards from buy point
|
# 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:
|
if max_open_trades > 0:
|
||||||
# Increase trade_count_lock for every iteration
|
# Increase trade_count_lock for every iteration
|
||||||
trade_count_lock[row2.date] = trade_count_lock.get(row2.date, 0) + 1
|
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_currency: %s ...', config['stake_currency'])
|
||||||
logger.info('Using stake_amount: %s ...', config['stake_amount'])
|
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
|
max_open_trades = 0
|
||||||
if args.realistic_simulation:
|
if args.realistic_simulation:
|
||||||
logger.info('Using max_open_trades: %s ...', config['max_open_trades'])
|
logger.info('Using max_open_trades: %s ...', config['max_open_trades'])
|
||||||
|
@ -170,9 +165,14 @@ def start(args):
|
||||||
from freqtrade import main
|
from freqtrade import main
|
||||||
main._CONF = config
|
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
|
# Execute backtest and print results
|
||||||
results = backtest(
|
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(
|
logger.info(
|
||||||
'\n====================== BACKTESTING REPORT ================================\n%s',
|
'\n====================== BACKTESTING REPORT ================================\n%s',
|
||||||
|
|
|
@ -5,6 +5,7 @@ import pandas as pd
|
||||||
# from unittest.mock import MagicMock
|
# from unittest.mock import MagicMock
|
||||||
from freqtrade import exchange, optimize
|
from freqtrade import exchange, optimize
|
||||||
from freqtrade.exchange import Bittrex
|
from freqtrade.exchange import Bittrex
|
||||||
|
from freqtrade.optimize import preprocess
|
||||||
from freqtrade.optimize.backtesting import backtest, generate_text_table, get_timeframe
|
from freqtrade.optimize.backtesting import backtest, generate_text_table, get_timeframe
|
||||||
# import freqtrade.optimize.backtesting as backtesting
|
# import freqtrade.optimize.backtesting as backtesting
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ def test_generate_text_table():
|
||||||
|
|
||||||
|
|
||||||
def test_get_timeframe():
|
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)
|
min_date, max_date = get_timeframe(data)
|
||||||
assert min_date.isoformat() == '2017-11-04T23:02:00+00:00'
|
assert min_date.isoformat() == '2017-11-04T23:02:00+00:00'
|
||||||
assert max_date.isoformat() == '2017-11-14T22:59:00+00:00'
|
assert max_date.isoformat() == '2017-11-14T22:59:00+00:00'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user