Merge branch 'develop' into tests_dec28

This commit is contained in:
Janne Sinivirta 2017-12-29 16:33:12 +02:00 committed by GitHub
commit 133c467cf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 230 additions and 25 deletions

View File

@ -179,18 +179,21 @@ def handle_trade(trade: Trade) -> bool:
current_rate = exchange.get_ticker(trade.pair)['bid']
# Check if minimal roi has been reached
if not min_roi_reached(trade, current_rate, datetime.utcnow()):
return False
if min_roi_reached(trade, current_rate, datetime.utcnow()):
logger.debug('Executing sell due to ROI ...')
execute_sell(trade, current_rate)
return True
# Check if sell signal has been enabled and triggered
if _CONF.get('experimental', {}).get('use_sell_signal'):
logger.debug('Checking sell_signal ...')
if not get_signal(trade.pair, SignalType.SELL):
return False
if get_signal(trade.pair, SignalType.SELL):
logger.debug('Executing sell due to sell signal ...')
execute_sell(trade, current_rate)
return True
return False
def get_target_bid(ticker: Dict[str, float]) -> float:
""" Calculates bid target between current ask price and last price """

View File

@ -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:

View File

@ -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 = [
[

View File

@ -1,10 +1,11 @@
# pragma pylint: disable=missing-docstring,W0212
import math
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():
@ -39,7 +40,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': ''})

View 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)

View File

@ -217,7 +217,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
assert trade.close_date is not None
def test_handle_trade_experimental(default_conf, ticker, limit_buy_order, mocker, caplog):
def test_handle_trade_roi(default_conf, ticker, limit_buy_order, mocker, caplog):
default_conf.update({'experimental': {'use_sell_signal': True}})
mocker.patch.dict('freqtrade.main._CONF', default_conf)
@ -235,10 +235,46 @@ def test_handle_trade_experimental(default_conf, ticker, limit_buy_order, mocker
trade = Trade.query.first()
trade.is_open = True
# FIX: sniffing logs, suggest handle_trade should not execute_sell
# instead that responsibility should be moved out of handle_trade(),
# we might just want to check if we are in a sell condition without
# executing
# if ROI is reached we must sell
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: False)
assert handle_trade(trade)
assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples
# if ROI is reached we must sell even if sell-signal is not signalled
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
assert handle_trade(trade)
assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples
def test_handle_trade_experimental(default_conf, ticker, limit_buy_order, mocker, caplog):
default_conf.update({'experimental': {'use_sell_signal': True}})
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'))
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
init(default_conf, create_engine('sqlite://'))
create_trade(0.001)
trade = Trade.query.first()
trade.is_open = True
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: False)
value_returned = handle_trade(trade)
assert ('freqtrade', logging.DEBUG, 'Checking sell_signal ...') in caplog.record_tuples
assert value_returned is False
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
assert handle_trade(trade)
s = 'Executing sell due to sell signal ...'
assert ('freqtrade', logging.DEBUG, s) in caplog.record_tuples
def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mocker):