stable/freqtrade/misc.py

162 lines
4.7 KiB
Python
Raw Normal View History

2018-02-04 07:33:54 +00:00
"""
Various tool function for Freqtrade and scripts
"""
2018-07-04 07:31:35 +00:00
import gzip
import logging
2018-03-17 21:44:47 +00:00
import re
from datetime import datetime
2018-03-17 21:12:42 +00:00
from typing import Dict
from ccxt import Exchange
import numpy as np
2018-03-17 21:12:42 +00:00
from pandas import DataFrame
2018-12-28 09:01:16 +00:00
import rapidjson
2017-11-11 15:47:19 +00:00
logger = logging.getLogger(__name__)
2018-03-17 21:12:42 +00:00
def shorten_date(_date: str) -> str:
2018-02-04 07:33:54 +00:00
"""
Trim the date so it fits on small screens
"""
new_date = re.sub('seconds?', 'sec', _date)
new_date = re.sub('minutes?', 'min', new_date)
new_date = re.sub('hours?', 'h', new_date)
new_date = re.sub('days?', 'd', new_date)
new_date = re.sub('^an?', '1', new_date)
return new_date
############################################
# Used by scripts #
# Matplotlib doesn't support ::datetime64, #
# so we need to convert it into ::datetime #
############################################
2018-03-17 21:12:42 +00:00
def datesarray_to_datetimearray(dates: np.ndarray) -> np.ndarray:
"""
Convert an pandas-array of timestamps into
An numpy-array of datetimes
:return: numpy-array of datetime
"""
return dates.dt.to_pydatetime()
2018-03-17 21:12:42 +00:00
def common_datearray(dfs: Dict[str, DataFrame]) -> np.ndarray:
2018-02-04 07:33:54 +00:00
"""
Return dates from Dataframe
2018-03-17 21:12:42 +00:00
:param dfs: Dict with format pair: pair_data
2018-02-04 07:33:54 +00:00
:return: List of dates
"""
alldates = {}
for pair, pair_data in dfs.items():
dates = datesarray_to_datetimearray(pair_data['date'])
for date in dates:
alldates[date] = 1
lst = []
for date, _ in alldates.items():
lst.append(date)
arr = np.array(lst)
return np.sort(arr, axis=0)
2018-03-30 21:30:23 +00:00
def file_dump_json(filename, data, is_zip=False) -> None:
"""
2018-02-04 07:33:54 +00:00
Dump JSON data into a file
:param filename: file to create
:param data: JSON Data to save
:return:
"""
logger.info(f'dumping json to "{filename}"')
if is_zip:
2018-03-30 21:30:23 +00:00
if not filename.endswith('.gz'):
filename = filename + '.gz'
with gzip.open(filename, 'w') as fp:
2018-12-28 09:01:16 +00:00
rapidjson.dump(data, fp, default=str, number_mode=rapidjson.NM_NATIVE)
else:
with open(filename, 'w') as fp:
2018-12-28 09:01:16 +00:00
rapidjson.dump(data, fp, default=str, number_mode=rapidjson.NM_NATIVE)
2018-03-25 11:38:17 +00:00
logger.debug(f'done json to "{filename}"')
2018-03-25 11:38:17 +00:00
def json_load(datafile):
2018-12-28 09:04:28 +00:00
"""
load data with rapidjson
Use this to have a consistent experience,
sete number_mode to "NM_NATIVE" for greatest speed
"""
return rapidjson.load(datafile, number_mode=rapidjson.NM_NATIVE)
def file_load_json(file):
gzipfile = file.with_suffix(file.suffix + '.gz')
# Try gzip file first, otherwise regular json file.
if gzipfile.is_file():
logger.debug('Loading ticker data from file %s', gzipfile)
with gzip.open(gzipfile) as tickerdata:
pairdata = json_load(tickerdata)
elif file.is_file():
logger.debug('Loading ticker data from file %s', file)
with open(file) as tickerdata:
pairdata = json_load(tickerdata)
else:
return None
return pairdata
2018-12-28 09:04:28 +00:00
2018-05-30 20:38:09 +00:00
def format_ms_time(date: int) -> str:
2018-03-25 11:38:17 +00:00
"""
convert MS date to readable format.
: epoch-string in ms
"""
return datetime.fromtimestamp(date/1000.0).strftime('%Y-%m-%dT%H:%M:%S')
2019-02-19 12:14:47 +00:00
def deep_merge_dicts(source, destination):
"""
>>> a = { 'first' : { 'rows' : { 'pass' : 'dog', 'number' : '1' } } }
>>> b = { 'first' : { 'rows' : { 'fail' : 'cat', 'number' : '5' } } }
>>> merge(b, a) == { 'first' : { 'rows' : { 'pass' : 'dog', 'fail' : 'cat', 'number' : '5' } } }
True
"""
for key, value in source.items():
if isinstance(value, dict):
# get node or create one
node = destination.setdefault(key, {})
deep_merge_dicts(value, node)
else:
destination[key] = value
return destination
def timeframe_to_seconds(ticker_interval: str) -> int:
2019-04-06 20:36:55 +00:00
"""
This function uses ccxt to parse the timeframe interval value written in the human readable
form ('1m', '5m', '1h', '1d', '1w', etc.) and returns the number
of seconds for one timeframe interval.
"""
return Exchange.parse_timeframe(ticker_interval)
def timeframe_to_minutes(ticker_interval: str) -> int:
2019-04-06 20:36:55 +00:00
"""
This function uses ccxt to parse the timeframe interval value written in the human readable
form ('1m', '5m', '1h', '1d', '1w', etc.) and returns the number
of minutes for one timeframe interval.
"""
return Exchange.parse_timeframe(ticker_interval) // 60
def timeframe_to_msecs(ticker_interval: str) -> int:
2019-04-06 20:36:55 +00:00
"""
This function uses ccxt to parse the timeframe interval value written in the human readable
form ('1m', '5m', '1h', '1d', '1w', etc.) and returns the number
of milliseconds for one timeframe interval.
"""
return Exchange.parse_timeframe(ticker_interval) * 1000