Merge branch 'develop' into sell_signal
This commit is contained in:
		| @@ -87,17 +87,17 @@ def download_backtesting_testdata(pair: str, interval: int = 5) -> bool: | ||||
|     )) | ||||
|  | ||||
|     filepair = pair.replace("-", "_") | ||||
|     filename = os.path.join(path, '{}-{}.json'.format( | ||||
|         filepair, | ||||
|         interval, | ||||
|     filename = os.path.join(path, '{pair}-{interval}.json'.format( | ||||
|         pair=filepair, | ||||
|         interval=interval, | ||||
|     )) | ||||
|     filename = filename.replace('USDT_BTC', 'BTC_FAKEBULL') | ||||
|  | ||||
|     if os.path.isfile(filename): | ||||
|         with open(filename, "rt") as fp: | ||||
|             data = json.load(fp) | ||||
|         logger.debug("Current Start:", data[1]['T']) | ||||
|         logger.debug("Current End: ", data[-1:][0]['T']) | ||||
|         logger.debug("Current Start: {}".format(data[1]['T'])) | ||||
|         logger.debug("Current End: {}".format(data[-1:][0]['T'])) | ||||
|     else: | ||||
|         data = [] | ||||
|         logger.debug("Current Start: None") | ||||
| @@ -107,8 +107,8 @@ def download_backtesting_testdata(pair: str, interval: int = 5) -> bool: | ||||
|     for row in new_data: | ||||
|         if row not in data: | ||||
|             data.append(row) | ||||
|     logger.debug("New Start:", data[1]['T']) | ||||
|     logger.debug("New End: ", data[-1:][0]['T']) | ||||
|     logger.debug("New Start: {}".format(data[1]['T'])) | ||||
|     logger.debug("New End: {}".format(data[-1:][0]['T'])) | ||||
|     data = sorted(data, key=lambda data: data['T']) | ||||
|  | ||||
|     with open(filename, "wt") as fp: | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| import logging | ||||
| import re | ||||
| from decimal import Decimal | ||||
| from datetime import timedelta, date, datetime | ||||
| from datetime import timedelta, datetime | ||||
| from typing import Callable, Any | ||||
|  | ||||
| import arrow | ||||
| from pandas import DataFrame | ||||
| from sqlalchemy import and_, func, text, between | ||||
| from sqlalchemy import and_, func, text | ||||
| from tabulate import tabulate | ||||
| from telegram import ParseMode, Bot, Update, ReplyKeyboardMarkup | ||||
| from telegram.error import NetworkError, TelegramError | ||||
| @@ -220,29 +220,28 @@ def _daily(bot: Bot, update: Update) -> None: | ||||
|     :param update: message update | ||||
|     :return: None | ||||
|     """ | ||||
|     today = datetime.utcnow().toordinal() | ||||
|     today = datetime.utcnow().date() | ||||
|     profit_days = {} | ||||
|  | ||||
|     try: | ||||
|         timescale = int(update.message.text.replace('/daily', '').strip()) | ||||
|     except (TypeError, ValueError): | ||||
|         timescale = 5 | ||||
|         timescale = 7 | ||||
|  | ||||
|     if not (isinstance(timescale, int) and timescale > 0): | ||||
|         send_msg('*Daily [n]:* `must be an integer greater than 0`', bot=bot) | ||||
|         return | ||||
|  | ||||
|     for day in range(0, timescale): | ||||
|         # need to query between day+1 and day-1 | ||||
|         nextdate = date.fromordinal(today - day + 1) | ||||
|         prevdate = date.fromordinal(today - day - 1) | ||||
|         profitday = today - timedelta(days=day) | ||||
|         trades = Trade.query \ | ||||
|             .filter(Trade.is_open.is_(False)) \ | ||||
|             .filter(between(Trade.close_date, prevdate, nextdate)) \ | ||||
|             .filter(Trade.close_date >= profitday)\ | ||||
|             .filter(Trade.close_date < (profitday + timedelta(days=1)))\ | ||||
|             .order_by(Trade.close_date)\ | ||||
|             .all() | ||||
|         curdayprofit = sum(trade.calc_profit() for trade in trades) | ||||
|         profit_days[date.fromordinal(today - day)] = format(curdayprofit, '.8f') | ||||
|         profit_days[profitday] = format(curdayprofit, '.8f') | ||||
|  | ||||
|     stats = [ | ||||
|         [ | ||||
|   | ||||
| @@ -1,11 +1,9 @@ | ||||
| # pragma pylint: disable=missing-docstring,W0212 | ||||
|  | ||||
| import os | ||||
| import pandas as pd | ||||
| from freqtrade import exchange, optimize | ||||
| from freqtrade.exchange import Bittrex | ||||
| from freqtrade.optimize.backtesting import backtest, generate_text_table, get_timeframe | ||||
| from freqtrade.optimize.__init__ import testdata_path, download_pairs, download_backtesting_testdata | ||||
|  | ||||
|  | ||||
| def test_generate_text_table(): | ||||
| @@ -40,7 +38,7 @@ def test_backtest(default_conf, mocker): | ||||
|     assert not results.empty | ||||
|  | ||||
|  | ||||
| def test_1min_ticker_interval(default_conf, mocker): | ||||
| def test_backtest_1min_ticker_interval(default_conf, mocker): | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
| @@ -48,75 +46,3 @@ def test_1min_ticker_interval(default_conf, mocker): | ||||
|     data = optimize.load_data(ticker_interval=1, pairs=['BTC_UNITEST']) | ||||
|     results = backtest(default_conf['stake_amount'], optimize.preprocess(data), 1, True) | ||||
|     assert not results.empty | ||||
|  | ||||
|  | ||||
| def test_backtest_with_new_pair(default_conf, ticker_history, mocker): | ||||
|     mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|  | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     optimize.load_data(ticker_interval=1, pairs=['BTC_MEME']) | ||||
|     file = 'freqtrade/tests/testdata/BTC_MEME-1.json' | ||||
|     assert os.path.isfile(file) is True | ||||
|  | ||||
|     # delete file freshly downloaded | ||||
|     if os.path.isfile(file): | ||||
|         os.remove(file) | ||||
|  | ||||
|  | ||||
| def test_testdata_path(): | ||||
|     assert os.path.join('freqtrade', 'tests', 'testdata') in testdata_path() | ||||
|  | ||||
|  | ||||
| def test_download_pairs(default_conf, ticker_history, mocker): | ||||
|     mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     file1_1 = 'freqtrade/tests/testdata/BTC_MEME-1.json' | ||||
|     file1_5 = 'freqtrade/tests/testdata/BTC_MEME-5.json' | ||||
|     file2_1 = 'freqtrade/tests/testdata/BTC_CFI-1.json' | ||||
|     file2_5 = 'freqtrade/tests/testdata/BTC_CFI-5.json' | ||||
|  | ||||
|     assert download_pairs(pairs=['BTC-MEME', 'BTC-CFI']) is True | ||||
|  | ||||
|     assert os.path.isfile(file1_1) is True | ||||
|     assert os.path.isfile(file1_5) is True | ||||
|     assert os.path.isfile(file2_1) is True | ||||
|     assert os.path.isfile(file2_5) is True | ||||
|  | ||||
|     # delete files freshly downloaded | ||||
|     if os.path.isfile(file1_1): | ||||
|         os.remove(file1_1) | ||||
|  | ||||
|     if os.path.isfile(file1_5): | ||||
|         os.remove(file1_5) | ||||
|  | ||||
|     if os.path.isfile(file2_1): | ||||
|         os.remove(file2_1) | ||||
|  | ||||
|     if os.path.isfile(file2_5): | ||||
|         os.remove(file2_5) | ||||
|  | ||||
|  | ||||
| def test_download_backtesting_testdata(default_conf, ticker_history, mocker): | ||||
|     mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     # Download a 1 min ticker file | ||||
|     file1 = 'freqtrade/tests/testdata/BTC_XEL-1.json' | ||||
|     download_backtesting_testdata(pair="BTC-XEL", interval=1) | ||||
|     assert os.path.isfile(file1) is True | ||||
|  | ||||
|     if os.path.isfile(file1): | ||||
|         os.remove(file1) | ||||
|  | ||||
|     # Download a 5 min ticker file | ||||
|     file2 = 'freqtrade/tests/testdata/BTC_STORJ-5.json' | ||||
|     download_backtesting_testdata(pair="BTC-STORJ", interval=5) | ||||
|     assert os.path.isfile(file2) is True | ||||
|  | ||||
|     if os.path.isfile(file2): | ||||
|         os.remove(file2) | ||||
|   | ||||
							
								
								
									
										166
									
								
								freqtrade/tests/optimize/test_optimize.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								freqtrade/tests/optimize/test_optimize.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| # pragma pylint: disable=missing-docstring,W0212 | ||||
|  | ||||
| import os | ||||
| import logging | ||||
| from shutil import copyfile | ||||
| from freqtrade import exchange, optimize | ||||
| from freqtrade.exchange import Bittrex | ||||
| from freqtrade.optimize.__init__ import testdata_path, download_pairs, download_backtesting_testdata | ||||
|  | ||||
|  | ||||
| def _backup_file(file: str, copy_file: bool = False) -> None: | ||||
|     """ | ||||
|     Backup existing file to avoid deleting the user file | ||||
|     :param file: complete path to the file | ||||
|     :param touch_file: create an empty file in replacement | ||||
|     :return: None | ||||
|     """ | ||||
|     file_swp = file + '.swp' | ||||
|     if os.path.isfile(file): | ||||
|         os.rename(file, file_swp) | ||||
|  | ||||
|         if copy_file: | ||||
|             copyfile(file_swp, file) | ||||
|  | ||||
|  | ||||
| def _clean_test_file(file: str) -> None: | ||||
|     """ | ||||
|     Backup existing file to avoid deleting the user file | ||||
|     :param file: complete path to the file | ||||
|     :return: None | ||||
|     """ | ||||
|     file_swp = file + '.swp' | ||||
|     # 1. Delete file from the test | ||||
|     if os.path.isfile(file): | ||||
|         os.remove(file) | ||||
|  | ||||
|     # 2. Rollback to the initial file | ||||
|     if os.path.isfile(file_swp): | ||||
|         os.rename(file_swp, file) | ||||
|  | ||||
|  | ||||
| def test_load_data_5min_ticker(default_conf, ticker_history, mocker, caplog): | ||||
|     mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|  | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     file = 'freqtrade/tests/testdata/BTC_ETH-5.json' | ||||
|     _backup_file(file, copy_file=True) | ||||
|     optimize.load_data(pairs=['BTC_ETH']) | ||||
|     assert os.path.isfile(file) is True | ||||
|     assert ('freqtrade.optimize', | ||||
|             logging.INFO, | ||||
|             'Download the pair: "BTC_ETH", Interval: 5 min' | ||||
|             ) not in caplog.record_tuples | ||||
|     _clean_test_file(file) | ||||
|  | ||||
|  | ||||
| def test_load_data_1min_ticker(default_conf, ticker_history, mocker, caplog): | ||||
|     mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|  | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     file = 'freqtrade/tests/testdata/BTC_ETH-1.json' | ||||
|     _backup_file(file, copy_file=True) | ||||
|     optimize.load_data(ticker_interval=1, pairs=['BTC_ETH']) | ||||
|     assert os.path.isfile(file) is True | ||||
|     assert ('freqtrade.optimize', | ||||
|             logging.INFO, | ||||
|             'Download the pair: "BTC_ETH", Interval: 1 min' | ||||
|             ) not in caplog.record_tuples | ||||
|     _clean_test_file(file) | ||||
|  | ||||
|  | ||||
| def test_load_data_with_new_pair_1min(default_conf, ticker_history, mocker, caplog): | ||||
|     mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|  | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     file = 'freqtrade/tests/testdata/BTC_MEME-1.json' | ||||
|     _backup_file(file) | ||||
|     optimize.load_data(ticker_interval=1, pairs=['BTC_MEME']) | ||||
|     assert os.path.isfile(file) is True | ||||
|     assert ('freqtrade.optimize', | ||||
|             logging.INFO, | ||||
|             'Download the pair: "BTC_MEME", Interval: 1 min' | ||||
|             ) in caplog.record_tuples | ||||
|     _clean_test_file(file) | ||||
|  | ||||
|  | ||||
| def test_testdata_path(): | ||||
|     assert os.path.join('freqtrade', 'tests', 'testdata') in testdata_path() | ||||
|  | ||||
|  | ||||
| def test_download_pairs(default_conf, ticker_history, mocker): | ||||
|     mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     file1_1 = 'freqtrade/tests/testdata/BTC_MEME-1.json' | ||||
|     file1_5 = 'freqtrade/tests/testdata/BTC_MEME-5.json' | ||||
|     file2_1 = 'freqtrade/tests/testdata/BTC_CFI-1.json' | ||||
|     file2_5 = 'freqtrade/tests/testdata/BTC_CFI-5.json' | ||||
|  | ||||
|     _backup_file(file1_1) | ||||
|     _backup_file(file1_5) | ||||
|     _backup_file(file2_1) | ||||
|     _backup_file(file2_5) | ||||
|  | ||||
|     assert download_pairs(pairs=['BTC-MEME', 'BTC-CFI']) is True | ||||
|  | ||||
|     assert os.path.isfile(file1_1) is True | ||||
|     assert os.path.isfile(file1_5) is True | ||||
|     assert os.path.isfile(file2_1) is True | ||||
|     assert os.path.isfile(file2_5) is True | ||||
|  | ||||
|     # clean files freshly downloaded | ||||
|     _clean_test_file(file1_1) | ||||
|     _clean_test_file(file1_5) | ||||
|     _clean_test_file(file2_1) | ||||
|     _clean_test_file(file2_5) | ||||
|  | ||||
|  | ||||
| def test_download_pairs_exception(default_conf, ticker_history, mocker, caplog): | ||||
|     mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch('freqtrade.optimize.__init__.download_backtesting_testdata', | ||||
|                  side_effect=BaseException('File Error')) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     file1_1 = 'freqtrade/tests/testdata/BTC_MEME-1.json' | ||||
|     file1_5 = 'freqtrade/tests/testdata/BTC_MEME-5.json' | ||||
|     _backup_file(file1_1) | ||||
|     _backup_file(file1_5) | ||||
|  | ||||
|     download_pairs(pairs=['BTC-MEME']) | ||||
|     # clean files freshly downloaded | ||||
|     _clean_test_file(file1_1) | ||||
|     _clean_test_file(file1_5) | ||||
|     assert ('freqtrade.optimize.__init__', | ||||
|             logging.INFO, | ||||
|             'Failed to download the pair: "BTC-MEME", Interval: 1 min' | ||||
|             ) in caplog.record_tuples | ||||
|  | ||||
|  | ||||
| def test_download_backtesting_testdata(default_conf, ticker_history, mocker): | ||||
|     mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history) | ||||
|     mocker.patch.dict('freqtrade.main._CONF', default_conf) | ||||
|     exchange._API = Bittrex({'key': '', 'secret': ''}) | ||||
|  | ||||
|     # Download a 1 min ticker file | ||||
|     file1 = 'freqtrade/tests/testdata/BTC_XEL-1.json' | ||||
|     _backup_file(file1) | ||||
|     download_backtesting_testdata(pair="BTC-XEL", interval=1) | ||||
|     assert os.path.isfile(file1) is True | ||||
|     _clean_test_file(file1) | ||||
|  | ||||
|     # Download a 5 min ticker file | ||||
|     file2 = 'freqtrade/tests/testdata/BTC_STORJ-5.json' | ||||
|     _backup_file(file2) | ||||
|  | ||||
|     download_backtesting_testdata(pair="BTC-STORJ", interval=5) | ||||
|     assert os.path.isfile(file2) is True | ||||
|     _clean_test_file(file2) | ||||
		Reference in New Issue
	
	Block a user