define common fixtures

This commit is contained in:
gcarq 2017-11-07 20:12:56 +01:00
parent 8eeb02e592
commit abdddd5193
6 changed files with 169 additions and 249 deletions

View File

@ -1,10 +1,58 @@
# pragma pylint: disable=missing-docstring
import json
from datetime import datetime
from unittest.mock import MagicMock
import pytest
from jsonschema import validate
from telegram import Message, Chat, Update
from freqtrade.misc import CONF_SCHEMA
@pytest.fixture(scope="module")
def conf():
def default_conf():
""" Returns validated configuration suitable for most tests """
configuration = {
"max_open_trades": 3,
"stake_currency": "BTC",
"stake_amount": 0.05,
"dry_run": True,
"minimal_roi": {
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
},
"stoploss": -0.05,
"bid_strategy": {
"ask_last_balance": 0.0
},
"exchange": {
"name": "bittrex",
"enabled": True,
"key": "key",
"secret": "secret",
"pair_whitelist": [
"BTC_ETH",
"BTC_TKN",
"BTC_TRST",
"BTC_SWT"
]
},
"telegram": {
"enabled": True,
"token": "token",
"chat_id": "0"
},
"initial_state": "running"
}
validate(configuration, CONF_SCHEMA)
return configuration
@pytest.fixture(scope="module")
def backtest_conf():
return {
"minimal_roi": {
"40": 0.0,
@ -24,3 +72,47 @@ def backdata():
with open('freqtrade/tests/testdata/' + pair + '.json') as data_file:
result[pair] = json.load(data_file)
return result
@pytest.fixture
def update():
_update = Update(0)
_update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
return _update
@pytest.fixture
def ticker():
return MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061,
})
@pytest.fixture
def limit_buy_order():
return {
'id': 'mocked_limit_buy',
'type': 'LIMIT_BUY',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.07256061,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
}
@pytest.fixture
def limit_sell_order():
return {
'id': 'mocked_limit_sell',
'type': 'LIMIT_SELL',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.0802134,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
}

View File

@ -14,12 +14,12 @@ def result():
return parse_ticker_dataframe(json.load(data_file))
def test_dataframe_has_correct_columns(result):
def test_dataframe_correct_columns(result):
assert result.columns.tolist() == \
['close', 'high', 'low', 'open', 'date', 'volume']
def test_dataframe_has_correct_length(result):
def test_dataframe_correct_length(result):
assert len(result.index) == 5751

View File

@ -1,5 +1,4 @@
# pragma pylint: disable=missing-docstring
import json
import logging
import os
@ -26,11 +25,11 @@ def print_pair_results(pair, results):
print(format_results(results[results.currency == pair]))
def backtest(conf, backdata, mocker):
def backtest(backtest_conf, backdata, mocker):
trades = []
exchange._API = Bittrex({'key': '', 'secret': ''})
mocked_history = mocker.patch('freqtrade.analyze.get_ticker_history')
mocker.patch.dict('freqtrade.main._CONF', conf)
mocker.patch.dict('freqtrade.main._CONF', backtest_conf)
mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00'))
for pair, pair_data in backdata.items():
mocked_history.return_value = pair_data
@ -56,8 +55,8 @@ def backtest(conf, backdata, mocker):
@pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set")
def test_backtest(conf, backdata, mocker, report=True):
results = backtest(conf, backdata, mocker)
def test_backtest(backtest_conf, backdata, mocker, report=True):
results = backtest(backtest_conf, backdata, mocker)
print('====================== BACKTESTING REPORT ================================')
for pair in backdata:

View File

@ -63,13 +63,13 @@ def buy_strategy_generator(params):
@pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set")
def test_hyperopt(conf, backdata, mocker):
def test_hyperopt(backtest_conf, backdata, mocker):
mocked_buy_trend = mocker.patch('freqtrade.analyze.populate_buy_trend')
def optimizer(params):
mocked_buy_trend.side_effect = buy_strategy_generator(params)
results = backtest(conf, backdata, mocker)
results = backtest(backtest_conf, backdata, mocker)
result = format_results(results)
print(result)

View File

@ -1,71 +1,25 @@
# pragma pylint: disable=missing-docstring
import copy
from datetime import datetime
from unittest.mock import MagicMock, call
import pytest
from jsonschema import validate
from freqtrade.exchange import Exchanges
from freqtrade.main import create_trade, handle_trade, close_trade_if_fulfilled, init, \
get_target_bid
from freqtrade.misc import CONF_SCHEMA
from freqtrade.persistence import Trade
@pytest.fixture
def conf():
configuration = {
"max_open_trades": 3,
"stake_currency": "BTC",
"stake_amount": 0.05,
"dry_run": True,
"minimal_roi": {
"2880": 0.005,
"720": 0.01,
"0": 0.02
},
"bid_strategy": {
"ask_last_balance": 0.0
},
"exchange": {
"name": "bittrex",
"enabled": True,
"key": "key",
"secret": "secret",
"pair_whitelist": [
"BTC_ETH",
"BTC_TKN",
"BTC_TRST",
"BTC_SWT",
]
},
"telegram": {
"enabled": True,
"token": "token",
"chat_id": "chat_id"
}
}
validate(configuration, CONF_SCHEMA)
return configuration
def test_create_trade(conf, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
buy_signal = mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'))
# Save state of current whitelist
whitelist = copy.deepcopy(conf['exchange']['pair_whitelist'])
whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist'])
init(conf, 'sqlite://')
init(default_conf, 'sqlite://')
for _ in ['BTC_ETH', 'BTC_TKN', 'BTC_TRST', 'BTC_SWT']:
trade = create_trade(15.0)
Trade.session.add(trade)
@ -77,29 +31,20 @@ def test_create_trade(conf, mocker):
assert trade.exchange == Exchanges.BITTREX.name
# Simulate fulfilled LIMIT_BUY order for trade
trade.update({
'id': 'mocked_limit_buy',
'type': 'LIMIT_BUY',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.072661,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
})
trade.update(limit_buy_order)
assert trade.open_rate == 0.072661
assert trade.open_rate == 0.07256061
assert trade.amount == 206.43811673387373
assert whitelist == conf['exchange']['pair_whitelist']
assert whitelist == default_conf['exchange']['pair_whitelist']
buy_signal.assert_has_calls(
[call('BTC_ETH'), call('BTC_TKN'), call('BTC_TRST'), call('BTC_SWT')]
)
def test_handle_trade(conf, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_handle_trade(default_conf, limit_sell_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch.multiple('freqtrade.main.telegram', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
@ -116,24 +61,15 @@ def test_handle_trade(conf, mocker):
assert trade.open_order_id == 'mocked_limit_sell'
# Simulate fulfilled LIMIT_SELL order for trade
trade.update({
'id': 'mocked_sell_limit',
'type': 'LIMIT_SELL',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.17256061,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
})
trade.update(limit_sell_order)
assert trade.close_rate == 0.17256061
assert trade.close_profit == 1.3698725
assert trade.close_rate == 0.0802134
assert trade.close_profit == 0.10046755
assert trade.close_date is not None
def test_close_trade(conf, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_close_trade(default_conf, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
trade = Trade.query.filter(Trade.is_open.is_(True)).first()
assert trade
@ -155,6 +91,6 @@ def test_balance_fully_last_side(mocker):
assert get_target_bid({'ask': 20, 'last': 10}) == 10
def test_balance_when_last_bigger_than_ask(mocker):
def test_balance_bigger_last_ask(mocker):
mocker.patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}})
assert get_target_bid({'ask': 5, 'last': 10}) == 5

View File

@ -1,85 +1,34 @@
# pragma pylint: disable=missing-docstring
import logging
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors
import re
from datetime import datetime
from unittest.mock import MagicMock
import pytest
from jsonschema import validate
from telegram import Bot, Update, Message, Chat
from telegram import Bot
from freqtrade import exchange
from freqtrade.main import init, create_trade
from freqtrade.misc import update_state, State, get_state, CONF_SCHEMA
from freqtrade.misc import update_state, State, get_state
from freqtrade.persistence import Trade
from freqtrade.rpc.telegram import (
_status, _status_table, _profit, _forcesell, _performance, _count, _start, _stop, _balance
)
@pytest.fixture
def conf():
configuration = {
"max_open_trades": 3,
"stake_currency": "BTC",
"stake_amount": 0.05,
"dry_run": True,
"minimal_roi": {
"2880": 0.005,
"720": 0.01,
"0": 0.02
},
"bid_strategy": {
"ask_last_balance": 0.0
},
"exchange": {
"name": "bittrex",
"enabled": True,
"key": "key",
"secret": "secret",
"pair_whitelist": [
"BTC_ETH",
"BTC_ETC"
]
},
"telegram": {
"enabled": True,
"token": "token",
"chat_id": "0"
},
"initial_state": "running"
}
validate(configuration, CONF_SCHEMA)
return configuration
@pytest.fixture
def update():
_update = Update(0)
_update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
return _update
class MagicBot(MagicMock, Bot):
pass
def test_status_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_status_handle(default_conf, update, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}))
init(conf, 'sqlite://')
get_ticker=ticker)
init(default_conf, 'sqlite://')
# Create some test data
trade = create_trade(15.0)
@ -94,24 +43,20 @@ def test_status_handle(conf, update, mocker):
assert '[BTC_ETH]' in msg_mock.call_args_list[-1][0][0]
def test_status_table_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_status_table_handle(default_conf, update, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_order_id'))
init(conf, 'sqlite://')
init(default_conf, 'sqlite://')
# Create some test data
trade = create_trade(15.0)
@ -121,7 +66,7 @@ def test_status_table_handle(conf, update, mocker):
_status_table(bot=MagicBot(), update=update)
text = re.sub('<\/?pre>', '', msg_mock.call_args_list[-1][0][0])
text = re.sub('</?pre>', '', msg_mock.call_args_list[-1][0][0])
line = text.split("\n")
fields = re.sub('[ ]+', ' ', line[2].strip()).split(' ')
@ -130,49 +75,27 @@ def test_status_table_handle(conf, update, mocker):
assert msg_mock.call_count == 2
def test_profit_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}))
init(conf, 'sqlite://')
get_ticker=ticker)
init(default_conf, 'sqlite://')
# Create some test data
trade = create_trade(15.0)
assert trade
# Simulate fulfilled LIMIT_BUY order for trade
trade.update({
'id': 'mocked_limit_buy',
'type': 'LIMIT_BUY',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.07256061,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
})
trade.update(limit_buy_order)
# Simulate fulfilled LIMIT_SELL order for trade
trade.update({
'id': 'mocked_limit_sell',
'type': 'LIMIT_SELL',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.0802134,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
})
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
@ -185,22 +108,18 @@ def test_profit_handle(conf, update, mocker):
assert 'Best Performing:* `BTC_ETH: 10.05%`' in msg_mock.call_args_list[-1][0][0]
def test_forcesell_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_forcesell_handle(default_conf, update, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}))
init(conf, 'sqlite://')
get_ticker=ticker)
init(default_conf, 'sqlite://')
# Create some test data
trade = create_trade(15.0)
@ -217,50 +136,28 @@ def test_forcesell_handle(conf, update, mocker):
assert '0.07256061 (profit: ~-0.64%)' in msg_mock.call_args_list[-1][0][0]
def test_performance_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_performance_handle(default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}))
init(conf, 'sqlite://')
get_ticker=ticker)
init(default_conf, 'sqlite://')
# Create some test data
trade = create_trade(15.0)
assert trade
# Simulate fulfilled LIMIT_BUY order for trade
trade.update({
'id': 'mocked_limit_buy',
'type': 'LIMIT_BUY',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.07256061,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
})
trade.update(limit_buy_order)
# Simulate fulfilled LIMIT_SELL order for trade
trade.update({
'id': 'mocked_limit_sell',
'type': 'LIMIT_SELL',
'pair': 'mocked',
'opened': datetime.utcnow(),
'rate': 0.0802134,
'amount': 206.43811673387373,
'remaining': 0.0,
'closed': datetime.utcnow(),
})
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
@ -273,24 +170,20 @@ def test_performance_handle(conf, update, mocker):
assert '<code>BTC_ETH\t10.05%</code>' in msg_mock.call_args_list[-1][0][0]
def test_count_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_count_handle(default_conf, update, ticker, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_buy_signal', side_effect=lambda _: True)
msg_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': 0.07256061,
'ask': 0.072661,
'last': 0.07256061
}),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_order_id'))
init(conf, 'sqlite://')
init(default_conf, 'sqlite://')
# Create some test data
trade = create_trade(15.0)
@ -303,20 +196,20 @@ def test_count_handle(conf, update, mocker):
_count(bot=MagicBot(), update=update)
line = msg_mock.call_args_list[-1][0][0].split("\n")
assert line[2] == '{}/{}'.format(2, conf['max_open_trades'])
assert line[2] == '{}/{}'.format(2, default_conf['max_open_trades'])
def test_start_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_start_handle(default_conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
_CONF=conf,
_CONF=default_conf,
init=MagicMock())
init(conf, 'sqlite://')
init(default_conf, 'sqlite://')
update_state(State.STOPPED)
assert get_state() == State.STOPPED
@ -325,17 +218,17 @@ def test_start_handle(conf, update, mocker):
assert msg_mock.call_count == 0
def test_stop_handle(conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', conf)
def test_stop_handle(default_conf, update, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',
_CONF=conf,
_CONF=default_conf,
init=MagicMock())
init(conf, 'sqlite://')
init(default_conf, 'sqlite://')
update_state(State.RUNNING)
assert get_state() == State.RUNNING
@ -345,17 +238,17 @@ def test_stop_handle(conf, update, mocker):
assert 'Stopping trader' in msg_mock.call_args_list[0][0][0]
def test_balance_handle(conf, update, mocker):
def test_balance_handle(default_conf, update, mocker):
mock_balance = [{
'Currency': 'BTC',
'Balance': 10.0,
'Available': 12.0,
'Pending': 0.0,
'CryptoAddress': 'XXXX'}]
mocker.patch.dict('freqtrade.main._CONF', conf)
mocker.patch.dict('freqtrade.main._CONF', default_conf)
msg_mock = MagicMock()
mocker.patch.multiple('freqtrade.main.telegram',
_CONF=conf,
_CONF=default_conf,
init=MagicMock(),
send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange',