stable/freqtrade/tests/conftest.py

386 lines
9.3 KiB
Python
Raw Normal View History

# pragma pylint: disable=missing-docstring
2018-03-17 21:44:47 +00:00
import json
import logging
2017-11-07 19:12:56 +00:00
from datetime import datetime
from functools import reduce
2018-03-17 21:44:47 +00:00
from unittest.mock import MagicMock
import arrow
2018-01-10 07:51:36 +00:00
import pytest
2017-11-07 19:12:56 +00:00
from jsonschema import validate
2018-03-02 13:47:00 +00:00
from sqlalchemy import create_engine
2018-03-17 21:44:47 +00:00
from telegram import Chat, Message, Update
from freqtrade.analyze import Analyze
from freqtrade.constants import Constants
from freqtrade.freqtradebot import FreqtradeBot
2017-11-07 19:12:56 +00:00
logging.getLogger('').setLevel(logging.INFO)
2017-11-07 15:18:29 +00:00
def log_has(line, logs):
# caplog mocker returns log as a tuple: ('freqtrade.analyze', logging.WARNING, 'foobar')
# and we want to match line against foobar in the tuple
return reduce(lambda a, b: a or b,
filter(lambda x: x[2] == line, logs),
False)
# Functions for recurrent object patching
def get_patched_freqtradebot(mocker, config) -> FreqtradeBot:
"""
This function patch _init_modules() to not call dependencies
:param mocker: a Mocker object to apply patches
:param config: Config to pass to the bot
:return: None
"""
mocker.patch('freqtrade.fiat_convert.Market', {'price_usd': 12345.0})
mocker.patch('freqtrade.freqtradebot.Analyze', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
mocker.patch('freqtrade.freqtradebot.exchange.init', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager._init', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager.send_msg', MagicMock())
mocker.patch('freqtrade.freqtradebot.Analyze.get_signal', MagicMock())
2018-03-02 13:47:00 +00:00
return FreqtradeBot(config, create_engine('sqlite://'))
2017-11-07 15:18:29 +00:00
@pytest.fixture(scope="module")
2017-11-07 19:12:56 +00:00
def default_conf():
""" Returns validated configuration suitable for most tests """
configuration = {
2017-11-07 21:27:44 +00:00
"max_open_trades": 1,
2017-11-07 19:12:56 +00:00
"stake_currency": "BTC",
2017-12-17 21:07:56 +00:00
"stake_amount": 0.001,
2017-12-25 07:51:41 +00:00
"fiat_display_currency": "USD",
"ticker_interval": '5m',
2017-11-07 19:12:56 +00:00
"dry_run": True,
"minimal_roi": {
2018-01-10 09:29:41 +00:00
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
2017-11-07 19:12:56 +00:00
},
2017-11-23 16:43:19 +00:00
"stoploss": -0.10,
"unfilledtimeout": 600,
2017-11-07 19:12:56 +00:00
"bid_strategy": {
"ask_last_balance": 0.0
},
"exchange": {
"name": "bittrex",
"enabled": True,
"key": "key",
"secret": "secret",
"pair_whitelist": [
2018-03-24 19:02:13 +00:00
"ETH/BTC",
"TKN/BTC",
"TRST/BTC",
"SWT/BTC",
"BCC/BTC"
2017-11-07 19:12:56 +00:00
]
},
"telegram": {
"enabled": True,
"token": "token",
"chat_id": "0"
},
2018-03-02 13:47:00 +00:00
"initial_state": "running",
"loglevel": logging.DEBUG
2017-11-07 19:12:56 +00:00
}
validate(configuration, Constants.CONF_SCHEMA)
2017-11-07 19:12:56 +00:00
return configuration
@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={
2017-12-17 21:07:56 +00:00
'bid': 0.00001098,
'ask': 0.00001099,
'last': 0.00001098,
2017-11-07 19:12:56 +00:00
})
2017-12-17 21:07:56 +00:00
@pytest.fixture
def ticker_sell_up():
return MagicMock(return_value={
'bid': 0.00001172,
'ask': 0.00001173,
'last': 0.00001172,
})
2017-12-17 21:07:56 +00:00
@pytest.fixture
def ticker_sell_down():
return MagicMock(return_value={
'bid': 0.00001044,
'ask': 0.00001043,
'last': 0.00001044,
})
2017-11-07 19:12:56 +00:00
@pytest.fixture
def markets():
return MagicMock(return_value=[
{
'id': 'ethbtc',
'symbol': 'ETH/BTC',
2018-04-07 15:05:44 +00:00
'base': 'ETH',
'quote': 'BTC',
2018-04-07 15:05:44 +00:00
'active': True,
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': 500000,
},
'info': '',
2018-04-07 15:05:44 +00:00
},
{
'id': 'tknbtc',
'symbol': 'TKN/BTC',
'base': 'TKN',
'quote': 'BTC',
2018-04-07 15:05:44 +00:00
'active': True,
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': 500000,
},
'info': '',
2018-04-07 15:05:44 +00:00
},
{
'id': 'blkbtc',
'symbol': 'BLK/BTC',
'base': 'BLK',
'quote': 'BTC',
2018-04-07 15:05:44 +00:00
'active': True,
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': 500000,
},
'info': '',
}
])
@pytest.fixture
def markets_empty():
return MagicMock(return_value=[])
2017-11-07 19:12:56 +00:00
@pytest.fixture
def limit_buy_order():
return {
'id': 'mocked_limit_buy',
'type': 'limit',
'side': 'buy',
2017-11-07 19:12:56 +00:00
'pair': 'mocked',
'datetime': arrow.utcnow().isoformat(),
'price': 0.00001099,
2017-12-17 21:07:56 +00:00
'amount': 90.99181073,
2017-11-07 19:12:56 +00:00
'remaining': 0.0,
'status': 'closed'
}
@pytest.fixture
def limit_buy_order_old():
return {
'id': 'mocked_limit_buy_old',
'type': 'limit',
'side': 'buy',
'pair': 'mocked',
'datetime': str(arrow.utcnow().shift(minutes=-601).datetime),
'price': 0.00001099,
'amount': 90.99181073,
'remaining': 90.99181073,
'status': 'open'
}
@pytest.fixture
def limit_sell_order_old():
return {
'id': 'mocked_limit_sell_old',
'type': 'limit',
'side': 'sell',
2018-03-24 19:02:13 +00:00
'pair': 'ETH/BTC',
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'price': 0.00001099,
'amount': 90.99181073,
'remaining': 90.99181073,
'status': 'open'
}
@pytest.fixture
def limit_buy_order_old_partial():
return {
'id': 'mocked_limit_buy_old_partial',
'type': 'limit',
'side': 'buy',
2018-03-24 19:02:13 +00:00
'pair': 'ETH/BTC',
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
'price': 0.00001099,
'amount': 90.99181073,
'remaining': 67.99181073,
'status': 'open'
2017-11-07 19:12:56 +00:00
}
@pytest.fixture
def limit_sell_order():
return {
'id': 'mocked_limit_sell',
'type': 'limit',
'side': 'sell',
2017-11-07 19:12:56 +00:00
'pair': 'mocked',
'datetime': arrow.utcnow().isoformat(),
'price': 0.00001173,
2017-12-17 21:07:56 +00:00
'amount': 90.99181073,
2017-11-07 19:12:56 +00:00
'remaining': 0.0,
'status': 'closed'
2017-11-07 19:12:56 +00:00
}
@pytest.fixture
def ticker_history_api():
return [
[
1511686200000, # unix timestamp ms
8.794e-05, # open
8.948e-05, # high
8.794e-05, # low
8.88e-05, # close
0.0877869, # volume (in quote currency)
],
[
1511686500000,
8.88e-05,
8.942e-05,
8.88e-05,
8.893e-05,
0.05874751,
],
[
1511686800,
8.891e-05,
8.893e-05,
8.875e-05,
8.877e-05,
0.7039405
]
]
@pytest.fixture
def ticker_history():
return [
{
"O": 8.794e-05,
"H": 8.948e-05,
"L": 8.794e-05,
"C": 8.88e-05,
"V": 991.09056638,
"T": "2017-11-26T08:50:00",
"BV": 0.0877869
},
{
"O": 8.88e-05,
"H": 8.942e-05,
"L": 8.88e-05,
"C": 8.893e-05,
"V": 658.77935965,
"T": "2017-11-26T08:55:00",
"BV": 0.05874751
},
{
"O": 8.891e-05,
"H": 8.893e-05,
"L": 8.875e-05,
"C": 8.877e-05,
"V": 7920.73570705,
"T": "2017-11-26T09:00:00",
"BV": 0.7039405
}
]
@pytest.fixture
def ticker_history_without_bv():
return [
{
"O": 8.794e-05,
"H": 8.948e-05,
"L": 8.794e-05,
"C": 8.88e-05,
"V": 991.09056638,
"T": "2017-11-26T08:50:00"
},
{
"O": 8.88e-05,
"H": 8.942e-05,
"L": 8.88e-05,
"C": 8.893e-05,
"V": 658.77935965,
"T": "2017-11-26T08:55:00"
},
{
"O": 8.891e-05,
"H": 8.893e-05,
"L": 8.875e-05,
"C": 8.877e-05,
"V": 7920.73570705,
"T": "2017-11-26T09:00:00"
}
2017-12-17 21:07:56 +00:00
]
2018-01-28 07:38:41 +00:00
@pytest.fixture
def result():
with open('freqtrade/tests/testdata/UNITTEST_BTC-1m.json') as data_file:
return Analyze.parse_ticker_dataframe(json.load(data_file))
2018-01-28 07:38:41 +00:00
# FIX:
# Create an fixture/function
# that inserts a trade of some type and open-status
# return the open-order-id
# See tests in rpc/main that could use this