Merge branch 'develop' into rpc-refactor

This commit is contained in:
kryofly
2018-01-28 15:38:18 +01:00
28 changed files with 449 additions and 352 deletions

View File

@@ -3,10 +3,13 @@ from datetime import datetime
from unittest.mock import MagicMock
from functools import reduce
import json
import arrow
import pytest
from jsonschema import validate
from telegram import Chat, Message, Update
from freqtrade.analyze import parse_ticker_dataframe
from freqtrade.strategy.strategy import Strategy
from freqtrade.misc import CONF_SCHEMA
@@ -257,6 +260,20 @@ def ticker_history_without_bv():
}
]
@pytest.fixture
def result():
with open('freqtrade/tests/testdata/BTC_ETH-1.json') as data_file:
return parse_ticker_dataframe(json.load(data_file))
@pytest.fixture
def default_strategy():
strategy = Strategy()
strategy.init({'strategy': 'default_strategy'})
return strategy
# FIX:
# Create an fixture/function
# that inserts a trade of some type and open-status

View File

@@ -1,8 +1,9 @@
# pragma pylint: disable=missing-docstring,C0103
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
# pragma pylint: disable=protected-access
from unittest.mock import MagicMock
from requests.exceptions import RequestException
from random import randint
import logging
from requests.exceptions import RequestException
import pytest
from freqtrade import OperationalException
@@ -30,7 +31,7 @@ def test_init(default_conf, mocker, caplog):
) in caplog.record_tuples
def test_init_exception(default_conf, mocker):
def test_init_exception(default_conf):
default_conf['exchange']['name'] = 'wrong_exchange_name'
with pytest.raises(
@@ -171,7 +172,7 @@ def test_get_balances_prod(default_conf, mocker):
# This test is somewhat redundant with
# test_exchange_bittrex.py::test_exchange_bittrex_get_ticker
def test_get_ticker(default_conf, mocker, ticker):
def test_get_ticker(default_conf, mocker):
maybe_init_api(default_conf, mocker)
api_mock = MagicMock()
tick = {"success": True, 'result': {'Bid': 0.00001098, 'Ask': 0.00001099, 'Last': 0.0001}}
@@ -200,7 +201,7 @@ def test_get_ticker(default_conf, mocker, ticker):
assert ticker['ask'] == 1
def test_get_ticker_history(default_conf, mocker, ticker):
def test_get_ticker_history(default_conf, mocker):
api_mock = MagicMock()
tick = 123
api_mock.get_ticker_history = MagicMock(return_value=tick)
@@ -251,7 +252,7 @@ def test_get_order(default_conf, mocker):
api_mock = MagicMock()
api_mock.get_order = MagicMock(return_value=456)
mocker.patch('freqtrade.exchange._API', api_mock)
assert 456 == exchange.get_order('X')
assert exchange.get_order('X') == 456
def test_get_name(default_conf, mocker):
@@ -271,16 +272,16 @@ def test_get_fee(default_conf, mocker):
assert get_fee() == 0.0025
def test_exchange_misc(default_conf, mocker):
def test_exchange_misc(mocker):
api_mock = MagicMock()
mocker.patch('freqtrade.exchange._API', api_mock)
exchange.get_markets()
assert 1 == api_mock.get_markets.call_count
assert api_mock.get_markets.call_count == 1
exchange.get_market_summaries()
assert 1 == api_mock.get_market_summaries.call_count
assert api_mock.get_market_summaries.call_count == 1
api_mock.name = 123
assert 123 == exchange.get_name()
assert exchange.get_name() == 123
api_mock.fee = 456
assert 456 == exchange.get_fee()
assert exchange.get_fee() == 456
exchange.get_wallet_health()
assert 1 == api_mock.get_wallet_health.call_count
assert api_mock.get_wallet_health.call_count == 1

View File

@@ -1,9 +1,8 @@
# pragma pylint: disable=missing-docstring,C0103
# pragma pylint: disable=missing-docstring, C0103, protected-access, unused-argument
import pytest
from unittest.mock import MagicMock
import pytest
from requests.exceptions import ContentDecodingError
from freqtrade.exchange.bittrex import Bittrex
import freqtrade.exchange.bittrex as btx
@@ -88,8 +87,7 @@ class FakeBittrex():
'PricePerUnit': 1,
'Quantity': 1,
'QuantityRemaining': 1,
'Closed': True
},
'Closed': True},
'message': 'lost'}
def fake_cancel_order(self, uuid):
@@ -211,24 +209,18 @@ def test_exchange_bittrex_get_ticker():
def test_exchange_bittrex_get_ticker_bad():
wb = make_wrap_bittrex()
fb = FakeBittrex()
fb.result = {'success': True,
'result': {'Bid': 1, 'Ask': 0}} # incomplete result
fb.result = {'success': True, 'result': {'Bid': 1, 'Ask': 0}} # incomplete result
with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'):
wb.get_ticker('BTC_ETH')
fb.result = {'success': False,
'message': 'gone bad'
}
fb.result = {'success': False, 'message': 'gone bad'}
with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'):
wb.get_ticker('BTC_ETH')
fb.result = {'success': True,
'result': {}} # incomplete result
fb.result = {'success': True, 'result': {}} # incomplete result
with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'):
wb.get_ticker('BTC_ETH')
fb.result = {'success': False,
'message': 'gone bad'
}
fb.result = {'success': False, 'message': 'gone bad'}
with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'):
wb.get_ticker('BTC_ETH')
@@ -353,8 +345,3 @@ def test_validate_response_min_trade_requirement_not_met():
}
with pytest.raises(ContentDecodingError, match=r'.*MIN_TRADE_REQUIREMENT_NOT_MET.*'):
Bittrex._validate_response(response)
def test_custom_requests(mocker):
mocker.patch('freqtrade.exchange.bittrex.requests', MagicMock())
btx.custom_requests('http://', '')

View File

@@ -1,28 +1,19 @@
# pragma pylint: disable=missing-docstring,W0212
# pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103
import logging
import math
import pandas as pd
import pytest
from unittest.mock import MagicMock
import pandas as pd
from freqtrade import exchange, optimize
from freqtrade.exchange import Bittrex
from freqtrade.optimize import preprocess
from freqtrade.optimize.backtesting import backtest, generate_text_table, get_timeframe
import freqtrade.optimize.backtesting as backtesting
from freqtrade.strategy.strategy import Strategy
@pytest.fixture
def default_strategy():
strategy = Strategy()
strategy.init({'strategy': 'default_strategy'})
return strategy
def trim_dictlist(dl, num):
def trim_dictlist(dict_list, num):
new = {}
for pair, pair_data in dl.items():
for pair, pair_data in dict_list.items():
new[pair] = pair_data[num:]
return new
@@ -193,7 +184,8 @@ def test_backtest_start(default_conf, mocker, caplog):
# check the logs, that will contain the backtest result
exists = ['Using max_open_trades: 1 ...',
'Using stake_amount: 0.001 ...',
'Measuring data from 2017-11-14T21:17:00+00:00 up to 2017-11-14T22:59:00+00:00 ...']
'Measuring data from 2017-11-14T21:17:00+00:00 '
'up to 2017-11-14T22:59:00+00:00 (0 days)..']
for line in exists:
assert ('freqtrade.optimize.backtesting',
logging.INFO,

View File

@@ -1,8 +1,7 @@
# pragma pylint: disable=missing-docstring,W0212
# pragma pylint: disable=missing-docstring, protected-access, C0103
import os
import logging
# from unittest.mock import MagicMock
from shutil import copyfile
from freqtrade import exchange, optimize
from freqtrade.exchange import Bittrex
@@ -10,7 +9,7 @@ from freqtrade.optimize.__init__ import make_testdata_path, download_pairs,\
download_backtesting_testdata, load_tickerdata_file
# Change this if modifying BTC_UNITEST testdatafile
_btc_unittest_length = 13681
_BTC_UNITTEST_LENGTH = 13681
def _backup_file(file: str, copy_file: bool = False) -> None:
@@ -56,8 +55,7 @@ def test_load_data_30min_ticker(default_conf, ticker_history, mocker, caplog):
assert os.path.isfile(file) is True
assert ('freqtrade.optimize',
logging.INFO,
'Download the pair: "BTC_ETH", Interval: 30 min'
) not in caplog.record_tuples
'Download the pair: "BTC_ETH", Interval: 30 min') not in caplog.record_tuples
_clean_test_file(file)
@@ -73,8 +71,7 @@ def test_load_data_5min_ticker(default_conf, ticker_history, mocker, caplog):
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
'Download the pair: "BTC_ETH", Interval: 5 min') not in caplog.record_tuples
_clean_test_file(file)
@@ -90,8 +87,7 @@ def test_load_data_1min_ticker(default_conf, ticker_history, mocker, caplog):
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
'Download the pair: "BTC_ETH", Interval: 1 min') not in caplog.record_tuples
_clean_test_file(file)
@@ -107,8 +103,7 @@ def test_load_data_with_new_pair_1min(default_conf, ticker_history, mocker, capl
assert os.path.isfile(file) is True
assert ('freqtrade.optimize',
logging.INFO,
'Download the pair: "BTC_MEME", Interval: 1 min'
) in caplog.record_tuples
'Download the pair: "BTC_MEME", Interval: 1 min') in caplog.record_tuples
_clean_test_file(file)
@@ -174,8 +169,7 @@ def test_download_pairs_exception(default_conf, ticker_history, mocker, caplog):
_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
'Failed to download the pair: "BTC-MEME", Interval: 1 min') in caplog.record_tuples
def test_download_backtesting_testdata(default_conf, ticker_history, mocker):
@@ -199,7 +193,7 @@ def test_download_backtesting_testdata(default_conf, ticker_history, mocker):
_clean_test_file(file2)
def test_download_backtesting_testdata2(default_conf, mocker):
def test_download_backtesting_testdata2(mocker):
tick = [{'T': 'bar'}, {'T': 'foo'}]
mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick)
@@ -210,7 +204,7 @@ def test_download_backtesting_testdata2(default_conf, mocker):
def test_load_tickerdata_file():
assert not load_tickerdata_file(None, 'BTC_UNITEST', 7)
tickerdata = load_tickerdata_file(None, 'BTC_UNITEST', 1)
assert _btc_unittest_length == len(tickerdata)
assert _BTC_UNITTEST_LENGTH == len(tickerdata)
def test_init(default_conf, mocker):
@@ -225,4 +219,4 @@ def test_tickerdata_to_dataframe():
tick = load_tickerdata_file(None, 'BTC_UNITEST', 1, timerange=timerange)
tickerlist = {'BTC_UNITEST': tick}
data = optimize.tickerdata_to_dataframe(tickerlist)
assert 100 == len(data['BTC_UNITEST'])
assert len(data['BTC_UNITEST']) == 100

View File

@@ -1,4 +1,5 @@
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors, C0103
# pragma pylint: disable=unused-argument
import re
from datetime import datetime
from random import randint

View File

@@ -1,14 +1,7 @@
import json
# pragma pylint: disable=missing-docstring, protected-access, C0103
import logging
import pytest
from freqtrade.strategy.strategy import Strategy
from freqtrade.analyze import parse_ticker_dataframe
@pytest.fixture
def result():
with open('freqtrade/tests/testdata/BTC_ETH-1.json') as data_file:
return parse_ticker_dataframe(json.load(data_file))
def test_sanitize_module_name():
@@ -28,8 +21,6 @@ def test_search_strategy():
def test_strategy_structure():
assert hasattr(Strategy, 'init')
assert hasattr(Strategy, 'minimal_roi')
assert hasattr(Strategy, 'stoploss')
assert hasattr(Strategy, 'populate_indicators')
assert hasattr(Strategy, 'populate_buy_trend')
assert hasattr(Strategy, 'populate_sell_trend')

View File

@@ -1,3 +1,5 @@
# pragma pylint: disable=missing-docstring,C0103
from freqtrade.main import refresh_whitelist, gen_pair_whitelist
# whitelist, blacklist, filtering, all of that will
@@ -73,16 +75,9 @@ def get_market_summaries():
def get_health():
return [{'Currency': 'ETH',
'IsActive': True
},
{'Currency': 'TKN',
'IsActive': True
},
{'Currency': 'BLK',
'IsActive': True
}
]
return [{'Currency': 'ETH', 'IsActive': True},
{'Currency': 'TKN', 'IsActive': True},
{'Currency': 'BLK', 'IsActive': True}]
def get_health_empty():

View File

@@ -1,25 +1,17 @@
# pragma pylint: disable=missing-docstring,W0621
import json
# pragma pylint: disable=missing-docstring, C0103
import datetime
from unittest.mock import MagicMock
import freqtrade.tests.conftest as tt # test tools
import arrow
import datetime
import pytest
from pandas import DataFrame
import freqtrade.tests.conftest as tt # test tools
from freqtrade.analyze import (get_signal, parse_ticker_dataframe,
populate_buy_trend, populate_indicators,
populate_sell_trend)
from freqtrade.strategy.strategy import Strategy
@pytest.fixture
def result():
with open('freqtrade/tests/testdata/BTC_ETH-1.json') as data_file:
return parse_ticker_dataframe(json.load(data_file))
def test_dataframe_correct_columns(result):
assert result.columns.tolist() == \
['close', 'high', 'low', 'open', 'date', 'volume']

View File

@@ -1,5 +1,6 @@
import pandas
# pragma pylint: disable=missing-docstring, C0103
import pandas
import freqtrade.optimize
from freqtrade import analyze

View File

@@ -1,4 +1,5 @@
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors, C0103
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors,
# pragma pylint: disable=protected-access, C0103
import time
from unittest.mock import MagicMock
@@ -47,16 +48,19 @@ def test_fiat_convert_is_supported():
def test_fiat_convert_add_pair():
fiat_convert = CryptoToFiatConverter()
assert len(fiat_convert._pairs) == 0
pair_len = len(fiat_convert._pairs)
assert pair_len == 0
fiat_convert._add_pair(crypto_symbol='btc', fiat_symbol='usd', price=12345.0)
assert len(fiat_convert._pairs) == 1
pair_len = len(fiat_convert._pairs)
assert pair_len == 1
assert fiat_convert._pairs[0].crypto_symbol == 'BTC'
assert fiat_convert._pairs[0].fiat_symbol == 'USD'
assert fiat_convert._pairs[0].price == 12345.0
fiat_convert._add_pair(crypto_symbol='btc', fiat_symbol='Eur', price=13000.2)
assert len(fiat_convert._pairs) == 2
pair_len = len(fiat_convert._pairs)
assert pair_len == 2
assert fiat_convert._pairs[1].crypto_symbol == 'BTC'
assert fiat_convert._pairs[1].fiat_symbol == 'EUR'
assert fiat_convert._pairs[1].price == 13000.2
@@ -95,7 +99,8 @@ def test_fiat_convert_get_price(mocker):
fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='US Dollar')
# Check the value return by the method
assert len(fiat_convert._pairs) == 0
pair_len = len(fiat_convert._pairs)
assert pair_len == 0
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 28000.0
assert fiat_convert._pairs[0].crypto_symbol == 'BTC'
assert fiat_convert._pairs[0].fiat_symbol == 'USD'

View File

@@ -1,8 +1,7 @@
# pragma pylint: disable=missing-docstring,C0103
# pragma pylint: disable=missing-docstring, C0103
import copy
import logging
from unittest.mock import MagicMock
import freqtrade.tests.conftest as tt # test tools
import arrow
import pytest
@@ -10,6 +9,7 @@ import requests
from sqlalchemy import create_engine
import freqtrade.main as main
import freqtrade.tests.conftest as tt # test tools
from freqtrade import DependencyException, OperationalException
from freqtrade.exchange import Exchanges
from freqtrade.main import (_process, check_handle_timedout, create_trade,
@@ -50,9 +50,9 @@ def test_main_start_hyperopt(mocker):
def test_process_maybe_execute_buy(default_conf, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.create_trade', return_value=True)
assert main.process_maybe_execute_buy(default_conf, int(default_conf['ticker_interval']))
assert main.process_maybe_execute_buy(int(default_conf['ticker_interval']))
mocker.patch('freqtrade.main.create_trade', return_value=False)
assert not main.process_maybe_execute_buy(default_conf, int(default_conf['ticker_interval']))
assert not main.process_maybe_execute_buy(int(default_conf['ticker_interval']))
def test_process_maybe_execute_sell(default_conf, mocker):
@@ -71,7 +71,7 @@ def test_process_maybe_execute_sell(default_conf, mocker):
def test_process_maybe_execute_buy_exception(default_conf, mocker, caplog):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.create_trade', MagicMock(side_effect=DependencyException))
main.process_maybe_execute_buy(default_conf, int(default_conf['ticker_interval']))
main.process_maybe_execute_buy(int(default_conf['ticker_interval']))
tt.log_has('Unable to create trade:', caplog.record_tuples)
@@ -256,7 +256,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker):
create_trade(default_conf['stake_amount'], int(default_conf['ticker_interval']))
def test_create_trade_no_signal(default_conf, ticker, mocker):
def test_create_trade_no_signal(default_conf, mocker):
default_conf['dry_run'] = True
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', MagicMock(return_value=(False, False)))
@@ -308,7 +308,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
assert trade.close_date is not None
def test_handle_overlpapping_signals(default_conf, ticker, mocker, caplog):
def test_handle_overlpapping_signals(default_conf, ticker, mocker):
default_conf.update({'experimental': {'use_sell_signal': True}})
mocker.patch.dict('freqtrade.main._CONF', default_conf)
@@ -325,27 +325,31 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker, caplog):
# Buy and Sell triggering, so doing nothing ...
trades = Trade.query.all()
assert len(trades) == 0
nb_trades = len(trades)
assert nb_trades == 0
# Buy is triggering, so buying ...
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, False))
create_trade(0.001, int(default_conf['ticker_interval']))
trades = Trade.query.all()
assert len(trades) == 1
nb_trades = len(trades)
assert nb_trades == 1
assert trades[0].is_open is True
# Buy and Sell are not triggering, so doing nothing ...
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, False))
assert handle_trade(trades[0], int(default_conf['ticker_interval'])) is False
trades = Trade.query.all()
assert len(trades) == 1
nb_trades = len(trades)
assert nb_trades == 1
assert trades[0].is_open is True
# Buy and Sell are triggering, so doing nothing ...
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, True))
assert handle_trade(trades[0], int(default_conf['ticker_interval'])) is False
trades = Trade.query.all()
assert len(trades) == 1
nb_trades = len(trades)
assert nb_trades == 1
assert trades[0].is_open is True
# Sell is triggering, guess what : we are Selling!
@@ -468,10 +472,11 @@ def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mo
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(trade_buy.open_order_id)).all()
assert len(trades) == 0
nb_trades = len(trades)
assert nb_trades == 0
def test_handle_timedout_limit_buy(default_conf, mocker):
def test_handle_timedout_limit_buy(mocker):
cancel_order = MagicMock()
mocker.patch('freqtrade.exchange.cancel_order', cancel_order)
Trade.session = MagicMock()
@@ -519,7 +524,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old,
assert trade_sell.is_open is True
def test_handle_timedout_limit_sell(default_conf, mocker):
def test_handle_timedout_limit_sell(mocker):
cancel_order = MagicMock()
mocker.patch('freqtrade.exchange.cancel_order', cancel_order)
trade = MagicMock()

View File

@@ -3,13 +3,13 @@ import argparse
import json
import time
from copy import deepcopy
from unittest.mock import MagicMock
import pytest
from unittest.mock import MagicMock
from jsonschema import ValidationError
from freqtrade.misc import (common_args_parser, load_config, parse_args,
throttle, file_dump_json, parse_timerange)
from freqtrade.misc import (common_args_parser, file_dump_json, load_config,
parse_args, parse_timerange, throttle)
def test_throttle():
@@ -124,7 +124,7 @@ def test_parse_args_backtesting_custom():
assert call_args.refresh_pairs is True
def test_parse_args_hyperopt_custom(mocker):
def test_parse_args_hyperopt_custom():
args = ['-c', 'test_conf.json', 'hyperopt', '--epochs', '20']
call_args = parse_args(args, '')
assert call_args.config == 'test_conf.json'
@@ -134,7 +134,7 @@ def test_parse_args_hyperopt_custom(mocker):
assert call_args.func is not None
def test_file_dump_json(default_conf, mocker):
def test_file_dump_json(mocker):
file_open = mocker.patch('freqtrade.misc.open', MagicMock())
json_dump = mocker.patch('json.dump', MagicMock())
file_dump_json('somefile', [1, 2, 3])

View File

@@ -1,4 +1,4 @@
# pragma pylint: disable=missing-docstring
# pragma pylint: disable=missing-docstring, C0103
import os
import pytest
from sqlalchemy import create_engine
@@ -12,7 +12,7 @@ def test_init_create_session(default_conf, mocker):
# Check if init create a session
init(default_conf)
assert hasattr(Trade, 'session')
assert type(Trade.session).__name__ is 'Session'
assert 'Session' in type(Trade.session).__name__
def test_init_dry_run_db(default_conf, mocker):