Merge pull request #591 from gcarq/feature/remove-duplicate-ticks
Aggregate ticks in parse_ticker_dataframe
This commit is contained in:
commit
2efc0113fe
@ -46,12 +46,20 @@ class Analyze(object):
|
|||||||
:return: DataFrame
|
:return: DataFrame
|
||||||
"""
|
"""
|
||||||
columns = {'C': 'close', 'V': 'volume', 'O': 'open', 'H': 'high', 'L': 'low', 'T': 'date'}
|
columns = {'C': 'close', 'V': 'volume', 'O': 'open', 'H': 'high', 'L': 'low', 'T': 'date'}
|
||||||
frame = DataFrame(ticker) \
|
frame = DataFrame(ticker).rename(columns=columns)
|
||||||
.rename(columns=columns)
|
|
||||||
if 'BV' in frame:
|
if 'BV' in frame:
|
||||||
frame.drop('BV', 1, inplace=True)
|
frame.drop('BV', axis=1, inplace=True)
|
||||||
|
|
||||||
frame['date'] = to_datetime(frame['date'], utc=True, infer_datetime_format=True)
|
frame['date'] = to_datetime(frame['date'], utc=True, infer_datetime_format=True)
|
||||||
frame.sort_values('date', inplace=True)
|
|
||||||
|
# group by index and aggregate results to eliminate duplicate ticks
|
||||||
|
frame = frame.groupby(by='date', as_index=False, sort=True).agg({
|
||||||
|
'close': 'last',
|
||||||
|
'high': 'max',
|
||||||
|
'low': 'min',
|
||||||
|
'open': 'first',
|
||||||
|
'volume': 'max',
|
||||||
|
})
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
||||||
|
@ -111,45 +111,38 @@ def download_pairs(datadir, pairs: List[str], ticker_interval: int) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
# FIX: 20180110, suggest rename interval to tick_interval
|
# FIX: 20180110, suggest rename interval to tick_interval
|
||||||
def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) -> bool:
|
def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) -> None:
|
||||||
"""
|
"""
|
||||||
Download the latest 1 and 5 ticker intervals from Bittrex for the pairs passed in parameters
|
Download the latest 1 and 5 ticker intervals from Bittrex for the pairs passed in parameters
|
||||||
Based on @Rybolov work: https://github.com/rybolov/freqtrade-data
|
Based on @Rybolov work: https://github.com/rybolov/freqtrade-data
|
||||||
:param pairs: list of pairs to download
|
|
||||||
:return: bool
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = make_testdata_path(datadir)
|
path = make_testdata_path(datadir)
|
||||||
logger.info(
|
logger.info(
|
||||||
'Download the pair: "%s", Interval: %s min',
|
'Download the pair: "%s", Interval: %s min', pair, interval
|
||||||
pair,
|
|
||||||
interval
|
|
||||||
)
|
)
|
||||||
|
|
||||||
filepair = pair.replace("-", "_")
|
|
||||||
filename = os.path.join(path, '{pair}-{interval}.json'.format(
|
filename = os.path.join(path, '{pair}-{interval}.json'.format(
|
||||||
pair=filepair,
|
pair=pair.replace("-", "_"),
|
||||||
interval=interval,
|
interval=interval,
|
||||||
))
|
))
|
||||||
|
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
with open(filename, "rt") as file:
|
with open(filename, "rt") as file:
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
logger.debug("Current Start: %s", data[1]['T'])
|
|
||||||
logger.debug("Current End: %s", data[-1:][0]['T'])
|
|
||||||
else:
|
else:
|
||||||
data = []
|
data = []
|
||||||
logger.debug("Current Start: None")
|
|
||||||
logger.debug("Current End: None")
|
|
||||||
|
|
||||||
new_data = get_ticker_history(pair=pair, tick_interval=int(interval))
|
logger.debug('Current Start: %s', data[1]['T'] if data else None)
|
||||||
for row in new_data:
|
logger.debug('Current End: %s', data[-1:][0]['T'] if data else None)
|
||||||
if row not in data:
|
|
||||||
data.append(row)
|
|
||||||
logger.debug("New Start: %s", data[1]['T'])
|
|
||||||
logger.debug("New End: %s", data[-1:][0]['T'])
|
|
||||||
data = sorted(data, key=lambda data: data['T'])
|
|
||||||
|
|
||||||
|
# Extend data with new ticker history
|
||||||
|
data.extend([
|
||||||
|
row for row in get_ticker_history(pair=pair, tick_interval=int(interval))
|
||||||
|
if row not in data
|
||||||
|
])
|
||||||
|
|
||||||
|
data = sorted(data, key=lambda _data: _data['T'])
|
||||||
|
logger.debug('New Start: %s', data[1]['T'])
|
||||||
|
logger.debug('New End: %s', data[-1:][0]['T'])
|
||||||
misc.file_dump_json(filename, data)
|
misc.file_dump_json(filename, data)
|
||||||
|
|
||||||
return True
|
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
This module contains the backtesting logic
|
This module contains the backtesting logic
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
import operator
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from typing import Dict, Tuple, Any, List, Optional
|
from typing import Dict, Tuple, Any, List, Optional
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
from pandas import DataFrame, Series
|
from pandas import DataFrame
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
import freqtrade.optimize as optimize
|
import freqtrade.optimize as optimize
|
||||||
@ -60,11 +61,12 @@ class Backtesting(object):
|
|||||||
:param data: dictionary with preprocessed backtesting data
|
:param data: dictionary with preprocessed backtesting data
|
||||||
:return: tuple containing min_date, max_date
|
:return: tuple containing min_date, max_date
|
||||||
"""
|
"""
|
||||||
all_dates = Series([])
|
timeframe = [
|
||||||
for pair_data in data.values():
|
(arrow.get(min(frame.date)), arrow.get(max(frame.date)))
|
||||||
all_dates = all_dates.append(pair_data['date'])
|
for frame in data.values()
|
||||||
all_dates.sort_values(inplace=True)
|
]
|
||||||
return arrow.get(all_dates.iloc[0]), arrow.get(all_dates.iloc[-1])
|
return min(timeframe, key=operator.itemgetter(0))[0], \
|
||||||
|
max(timeframe, key=operator.itemgetter(1))[1]
|
||||||
|
|
||||||
def _generate_text_table(self, data: Dict[str, Dict], results: DataFrame) -> str:
|
def _generate_text_table(self, data: Dict[str, Dict], results: DataFrame) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -182,10 +182,11 @@ def test_download_backtesting_testdata(ticker_history, mocker) -> None:
|
|||||||
|
|
||||||
def test_download_backtesting_testdata2(mocker) -> None:
|
def test_download_backtesting_testdata2(mocker) -> None:
|
||||||
tick = [{'T': 'bar'}, {'T': 'foo'}]
|
tick = [{'T': 'bar'}, {'T': 'foo'}]
|
||||||
mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
|
json_dump_mock = mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
|
||||||
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick)
|
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick)
|
||||||
assert download_backtesting_testdata(None, pair="BTC-UNITEST", interval=1)
|
download_backtesting_testdata(None, pair="BTC-UNITEST", interval=1)
|
||||||
assert download_backtesting_testdata(None, pair="BTC-UNITEST", interval=3)
|
download_backtesting_testdata(None, pair="BTC-UNITEST", interval=3)
|
||||||
|
assert json_dump_mock.call_count == 2
|
||||||
|
|
||||||
|
|
||||||
def test_load_tickerdata_file() -> None:
|
def test_load_tickerdata_file() -> None:
|
||||||
|
@ -50,7 +50,7 @@ def test_dataframe_correct_length(result):
|
|||||||
|
|
||||||
def test_dataframe_correct_columns(result):
|
def test_dataframe_correct_columns(result):
|
||||||
assert result.columns.tolist() == \
|
assert result.columns.tolist() == \
|
||||||
['close', 'high', 'low', 'open', 'date', 'volume']
|
['date', 'close', 'high', 'low', 'open', 'volume']
|
||||||
|
|
||||||
|
|
||||||
def test_populates_buy_trend(result):
|
def test_populates_buy_trend(result):
|
||||||
@ -170,7 +170,7 @@ def test_get_signal_handles_exceptions(mocker):
|
|||||||
|
|
||||||
|
|
||||||
def test_parse_ticker_dataframe(ticker_history, ticker_history_without_bv):
|
def test_parse_ticker_dataframe(ticker_history, ticker_history_without_bv):
|
||||||
columns = ['close', 'high', 'low', 'open', 'date', 'volume']
|
columns = ['date', 'close', 'high', 'low', 'open', 'volume']
|
||||||
|
|
||||||
# Test file with BV data
|
# Test file with BV data
|
||||||
dataframe = Analyze.parse_ticker_dataframe(ticker_history)
|
dataframe = Analyze.parse_ticker_dataframe(ticker_history)
|
||||||
|
Loading…
Reference in New Issue
Block a user