Merge pull request #85 from gcarq/datetime_fixes

Performance improvements for backtesting
This commit is contained in:
Michael Egger 2017-10-29 15:56:20 +01:00 committed by GitHub
commit 871b5e17ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 22 deletions

View File

@ -4,7 +4,7 @@ from datetime import timedelta
import arrow import arrow
import talib.abstract as ta import talib.abstract as ta
from pandas import DataFrame from pandas import DataFrame, to_datetime
from qtpylib.indicators import awesome_oscillator, crossed_above from qtpylib.indicators import awesome_oscillator, crossed_above
from freqtrade import exchange from freqtrade import exchange
@ -15,7 +15,7 @@ logging.basicConfig(level=logging.DEBUG,
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def parse_ticker_dataframe(ticker: list, minimum_date: arrow.Arrow) -> DataFrame: def parse_ticker_dataframe(ticker: list) -> DataFrame:
""" """
Analyses the trend for the given pair Analyses the trend for the given pair
:param pair: pair as str in format BTC_ETH or BTC-ETH :param pair: pair as str in format BTC_ETH or BTC-ETH
@ -23,8 +23,9 @@ def parse_ticker_dataframe(ticker: list, minimum_date: arrow.Arrow) -> DataFrame
""" """
df = DataFrame(ticker) \ df = DataFrame(ticker) \
.drop('BV', 1) \ .drop('BV', 1) \
.rename(columns={'C':'close', 'V':'volume', 'O':'open', 'H':'high', 'L':'low', 'T':'date'}) \ .rename(columns={'C':'close', 'V':'volume', 'O':'open', 'H':'high', 'L':'low', 'T':'date'})
.sort_values('date') df['date'] = to_datetime(df['date'], utc=True, infer_datetime_format=True)
df.sort_values('date', inplace=True)
return df return df
@ -53,14 +54,14 @@ def populate_buy_trend(dataframe: DataFrame) -> DataFrame:
:param dataframe: DataFrame :param dataframe: DataFrame
:return: DataFrame with buy column :return: DataFrame with buy column
""" """
dataframe.loc[ dataframe.ix[
(dataframe['close'] < dataframe['sma']) & (dataframe['close'] < dataframe['sma']) &
(dataframe['tema'] <= dataframe['blower']) & (dataframe['tema'] <= dataframe['blower']) &
(dataframe['mfi'] < 25) & (dataframe['mfi'] < 25) &
(dataframe['fastd'] < 25) & (dataframe['fastd'] < 25) &
(dataframe['adx'] > 30), (dataframe['adx'] > 30),
'buy'] = 1 'buy'] = 1
dataframe.loc[dataframe['buy'] == 1, 'buy_price'] = dataframe['close'] dataframe.ix[dataframe['buy'] == 1, 'buy_price'] = dataframe['close']
return dataframe return dataframe
@ -73,7 +74,7 @@ def analyze_ticker(pair: str) -> DataFrame:
""" """
minimum_date = arrow.utcnow().shift(hours=-24) minimum_date = arrow.utcnow().shift(hours=-24)
data = get_ticker_history(pair, minimum_date) data = get_ticker_history(pair, minimum_date)
dataframe = parse_ticker_dataframe(data['result'], minimum_date) dataframe = parse_ticker_dataframe(data['result'])
if dataframe.empty: if dataframe.empty:
logger.warning('Empty dataframe for pair %s', pair) logger.warning('Empty dataframe for pair %s', pair)

View File

@ -1,7 +1,7 @@
# pragma pylint: disable=missing-docstring # pragma pylint: disable=missing-docstring
from datetime import datetime
import json import json
import pytest import pytest
import arrow
from pandas import DataFrame from pandas import DataFrame
from freqtrade.analyze import parse_ticker_dataframe, populate_buy_trend, populate_indicators, \ from freqtrade.analyze import parse_ticker_dataframe, populate_buy_trend, populate_indicators, \
@ -12,7 +12,7 @@ def result():
with open('freqtrade/tests/testdata/btc-eth.json') as data_file: with open('freqtrade/tests/testdata/btc-eth.json') as data_file:
data = json.load(data_file) data = json.load(data_file)
return parse_ticker_dataframe(data['result'], arrow.get('2017-08-30T10:00:00')) return parse_ticker_dataframe(data['result'])
def test_dataframe_has_correct_columns(result): def test_dataframe_has_correct_columns(result):
assert result.columns.tolist() == \ assert result.columns.tolist() == \
@ -27,10 +27,10 @@ def test_populates_buy_trend(result):
assert 'buy_price' in dataframe.columns assert 'buy_price' in dataframe.columns
def test_returns_latest_buy_signal(mocker): def test_returns_latest_buy_signal(mocker):
buydf = DataFrame([{'buy': 1, 'date': arrow.utcnow()}]) buydf = DataFrame([{'buy': 1, 'date': datetime.today()}])
mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf)
assert get_buy_signal('BTC-ETH') assert get_buy_signal('BTC-ETH')
buydf = DataFrame([{'buy': 0, 'date': arrow.utcnow()}]) buydf = DataFrame([{'buy': 0, 'date': datetime.today()}])
mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=buydf)
assert not get_buy_signal('BTC-ETH') assert not get_buy_signal('BTC-ETH')

View File

@ -51,20 +51,16 @@ def backtest(conf, pairs, mocker):
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=data) mocker.patch('freqtrade.analyze.get_ticker_history', return_value=data)
mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')) mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00'))
ticker = analyze_ticker(pair) ticker = analyze_ticker(pair)[['close', 'date', 'buy']].copy()
# for each buy point # for each buy point
for index, row in ticker[ticker.buy == 1].iterrows(): for row in ticker[ticker.buy == 1].itertuples(index=True):
trade = Trade( trade = Trade(open_rate=row.close, open_date=row.date, amount=1)
open_rate=row['close'],
open_date=arrow.get(row['date']).datetime,
amount=1,
)
# calculate win/lose forwards from buy point # calculate win/lose forwards from buy point
for index2, row2 in ticker[index:].iterrows(): for row2 in ticker[row.Index:].itertuples(index=True):
if should_sell(trade, row2['close'], arrow.get(row2['date']).datetime): if should_sell(trade, row2.close, row2.date):
current_profit = (row2['close'] - trade.open_rate) / trade.open_rate current_profit = (row2.close - trade.open_rate) / trade.open_rate
trades.append((pair, current_profit, index2 - index)) trades.append((pair, current_profit, row2.Index - row.Index))
break break
labels = ['currency', 'profit', 'duration'] labels = ['currency', 'profit', 'duration']
results = DataFrame.from_records(trades, columns=labels) results = DataFrame.from_records(trades, columns=labels)