Merge pull request #603 from enenn/ccxt-objectify-pr3_1

[3/3] Add support for multiple exchanges with ccxt (objectified version)
This commit is contained in:
Samuel Husso
2018-04-18 15:23:33 +03:00
committed by GitHub
18 changed files with 664 additions and 459 deletions

View File

@@ -99,6 +99,11 @@ def update():
return _update
@pytest.fixture
def fee():
return MagicMock(return_value=0.0025)
@pytest.fixture
def ticker():
return MagicMock(return_value={
@@ -127,32 +132,80 @@ def ticker_sell_down():
@pytest.fixture
def health():
return MagicMock(return_value={
"ETH/BTC": {
def markets():
return MagicMock(return_value=[
{
'id': 'ethbtc',
'symbol': 'ETH/BTC',
'base': 'ETH',
'quote': 'BTC',
'active': True,
'LastChecked': '2017-11-13T20:15:00.00',
'Notice': None
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': 500000,
},
'info': '',
},
"TRST/BTC": {
'base': 'TRST',
{
'id': 'tknbtc',
'symbol': 'TKN/BTC',
'base': 'TKN',
'quote': 'BTC',
'active': True,
'LastChecked': '2017-11-13T20:15:00.00',
'Notice': None
'precision': {
'price': 8,
'amount': 8,
'cost': 8,
},
'lot': 0.00000001,
'limits': {
'amount': {
'min': 0.01,
'max': 1000,
},
'price': 500000,
'cost': 500000,
},
'info': '',
},
"SWT/BTC": {
'base': 'SWT',
{
'id': 'blkbtc',
'symbol': 'BLK/BTC',
'base': 'BLK',
'quote': 'BTC',
'active': True,
'LastChecked': '2017-11-13T20:15:00.00',
'Notice': None
},
"BCC/BTC": {
'base': 'BCC',
'active': False,
'LastChecked': '2017-11-13T20:15:00.00',
'Notice': None
}})
'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=[])
@pytest.fixture
@@ -231,7 +284,7 @@ def limit_sell_order():
@pytest.fixture
def ticker_history_api():
def ticker_history():
return [
[
1511686200000, # unix timestamp ms
@@ -261,66 +314,179 @@ def ticker_history_api():
@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
def tickers():
return MagicMock(return_value={
'ETH/BTC': {
'symbol': 'ETH/BTC',
'timestamp': 1522014806207,
'datetime': '2018-03-25T21:53:26.207Z',
'high': 0.061697,
'low': 0.060531,
'bid': 0.061588,
'bidVolume': 3.321,
'ask': 0.061655,
'askVolume': 0.212,
'vwap': 0.06105296,
'open': 0.060809,
'close': 0.060761,
'first': None,
'last': 0.061588,
'change': 1.281,
'percentage': None,
'average': None,
'baseVolume': 111649.001,
'quoteVolume': 6816.50176926,
'info': {}
},
{
"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
'TKN/BTC': {
'symbol': 'TKN/BTC',
'timestamp': 1522014806169,
'datetime': '2018-03-25T21:53:26.169Z',
'high': 0.01885,
'low': 0.018497,
'bid': 0.018799,
'bidVolume': 8.38,
'ask': 0.018802,
'askVolume': 15.0,
'vwap': 0.01869197,
'open': 0.018585,
'close': 0.018573,
'baseVolume': 81058.66,
'quoteVolume': 2247.48374509,
},
{
"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
'BLK/BTC': {
'symbol': 'BLK/BTC',
'timestamp': 1522014806072,
'datetime': '2018-03-25T21:53:26.720Z',
'high': 0.007745,
'low': 0.007512,
'bid': 0.007729,
'bidVolume': 0.01,
'ask': 0.007743,
'askVolume': 21.37,
'vwap': 0.00761466,
'open': 0.007653,
'close': 0.007652,
'first': None,
'last': 0.007743,
'change': 1.176,
'percentage': None,
'average': None,
'baseVolume': 295152.26,
'quoteVolume': 1515.14631229,
'info': {}
},
'LTC/BTC': {
'symbol': 'LTC/BTC',
'timestamp': 1523787258992,
'datetime': '2018-04-15T10:14:19.992Z',
'high': 0.015978,
'low': 0.0157,
'bid': 0.015954,
'bidVolume': 12.83,
'ask': 0.015957,
'askVolume': 0.49,
'vwap': 0.01581636,
'open': 0.015823,
'close': 0.01582,
'first': None,
'last': 0.015951,
'change': 0.809,
'percentage': None,
'average': None,
'baseVolume': 88620.68,
'quoteVolume': 1401.65697943,
'info': {}
},
'ETH/USDT': {
'symbol': 'ETH/USDT',
'timestamp': 1522014804118,
'datetime': '2018-03-25T21:53:24.118Z',
'high': 530.88,
'low': 512.0,
'bid': 529.73,
'bidVolume': 0.2,
'ask': 530.21,
'askVolume': 0.2464,
'vwap': 521.02438405,
'open': 527.27,
'close': 528.42,
'first': None,
'last': 530.21,
'change': 0.558,
'percentage': None,
'average': None,
'baseVolume': 72300.0659,
'quoteVolume': 37670097.3022171,
'info': {}
},
'TKN/USDT': {
'symbol': 'TKN/USDT',
'timestamp': 1522014806198,
'datetime': '2018-03-25T21:53:26.198Z',
'high': 8718.0,
'low': 8365.77,
'bid': 8603.64,
'bidVolume': 0.15846,
'ask': 8603.67,
'askVolume': 0.069147,
'vwap': 8536.35621697,
'open': 8680.0,
'close': 8680.0,
'first': None,
'last': 8603.67,
'change': -0.879,
'percentage': None,
'average': None,
'baseVolume': 30414.604298,
'quoteVolume': 259629896.48584127,
'info': {}
},
'BLK/USDT': {
'symbol': 'BLK/USDT',
'timestamp': 1522014806145,
'datetime': '2018-03-25T21:53:26.145Z',
'high': 66.95,
'low': 63.38,
'bid': 66.473,
'bidVolume': 4.968,
'ask': 66.54,
'askVolume': 2.704,
'vwap': 65.0526901,
'open': 66.43,
'close': 66.383,
'first': None,
'last': 66.5,
'change': 0.105,
'percentage': None,
'average': None,
'baseVolume': 294106.204,
'quoteVolume': 19132399.743954,
'info': {}
},
'LTC/USDT': {
'symbol': 'LTC/USDT',
'timestamp': 1523787257812,
'datetime': '2018-04-15T10:14:18.812Z',
'high': 129.94,
'low': 124.0,
'bid': 129.28,
'bidVolume': 0.03201,
'ask': 129.52,
'askVolume': 0.14529,
'vwap': 126.92838682,
'open': 127.0,
'close': 127.1,
'first': None,
'last': 129.28,
'change': 1.795,
'percentage': None,
'average': None,
'baseVolume': 59698.79897,
'quoteVolume': 29132399.743954,
'info': {}
}
]
@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"
}
]
})
@pytest.fixture
@@ -328,7 +494,6 @@ def result():
with open('freqtrade/tests/testdata/UNITTEST_BTC-1m.json') as data_file:
return Analyze.parse_ticker_dataframe(json.load(data_file))
# FIX:
# Create an fixture/function
# that inserts a trade of some type and open-status

View File

@@ -68,7 +68,8 @@ def test_validate_pairs_not_compatible(default_conf, mocker):
api_mock.load_markets = MagicMock(return_value={
'ETH/BTC': '', 'TKN/BTC': '', 'TRST/BTC': '', 'SWT/BTC': '', 'BCC/BTC': ''
})
default_conf['stake_currency'] = 'ETH'
conf = deepcopy(default_conf)
conf['stake_currency'] = 'ETH'
mocker.patch('freqtrade.exchange._API', api_mock)
mocker.patch.dict('freqtrade.exchange._CONF', conf)
with pytest.raises(OperationalException, match=r'not compatible'):
@@ -78,18 +79,20 @@ def test_validate_pairs_not_compatible(default_conf, mocker):
def test_validate_pairs_exception(default_conf, mocker, caplog):
caplog.set_level(logging.INFO)
api_mock = MagicMock()
api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError())
api_mock.name = 'binance'
api_mock.name = 'Binance'
mocker.patch('freqtrade.exchange._API', api_mock)
mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
with pytest.raises(OperationalException, match=r'Pair ETH/BTC is not available at binance'):
api_mock.load_markets = MagicMock(return_value={})
with pytest.raises(OperationalException, match=r'Pair ETH/BTC is not available at Binance'):
validate_pairs(default_conf['exchange']['pair_whitelist'])
api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError())
validate_pairs(default_conf['exchange']['pair_whitelist'])
assert log_has('Unable to validate pairs (assuming they are correct). Reason: ',
caplog.record_tuples)
def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
caplog.set_level(logging.INFO)
conf = deepcopy(default_conf)
@@ -105,6 +108,7 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
):
validate_pairs(default_conf['exchange']['pair_whitelist'])
def test_buy_dry_run(default_conf, mocker):
default_conf['dry_run'] = True
mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
@@ -113,6 +117,7 @@ def test_buy_dry_run(default_conf, mocker):
assert 'id' in order
assert 'dry_run_buy_' in order['id']
def test_buy_prod(default_conf, mocker):
api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))

View File

@@ -6,6 +6,7 @@ import random
from copy import deepcopy
from typing import List
from unittest.mock import MagicMock
import pytest
import numpy as np
import pandas as pd
@@ -15,10 +16,20 @@ from freqtrade import optimize
from freqtrade.analyze import Analyze
from freqtrade.arguments import Arguments
from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration
from freqtrade.tests.conftest import default_conf, log_has
from freqtrade.tests.conftest import log_has
# Avoid to reinit the same object again and again
_BACKTESTING = Backtesting(default_conf())
_BACKTESTING = None
_BACKTESTING_INITIALIZED = False
@pytest.fixture(scope='function')
def init_backtesting(default_conf, mocker):
global _BACKTESTING_INITIALIZED, _BACKTESTING
if not _BACKTESTING_INITIALIZED:
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
_BACKTESTING = Backtesting(default_conf)
_BACKTESTING_INITIALIZED = True
def get_args(args) -> List[str]:
@@ -34,44 +45,54 @@ def trim_dictlist(dict_list, num):
def load_data_test(what):
timerange = ((None, 'line'), None, -100)
data = optimize.load_data(None, ticker_interval='1m', pairs=['UNITTEST/BTC'], timerange=timerange)
data = optimize.load_data(None, ticker_interval='1m',
pairs=['UNITTEST/BTC'], timerange=timerange)
pair = data['UNITTEST/BTC']
datalen = len(pair)
# Depending on the what parameter we now adjust the
# loaded data looks:
# pair :: [{'O': 0.123, 'H': 0.123, 'L': 0.123,
# 'C': 0.123, 'V': 123.123,
# 'T': '2017-11-04T23:02:00', 'BV': 0.123}]
# pair :: [[ 1509836520000, unix timestamp in ms
# 0.00162008, open
# 0.00162008, high
# 0.00162008, low
# 0.00162008, close
# 108.14853839 base volume
# ]]
base = 0.001
if what == 'raise':
return {'UNITTEST/BTC':
[{'T': pair[x]['T'], # Keep old dates
'V': pair[x]['V'], # Keep old volume
'BV': pair[x]['BV'], # keep too
'O': x * base, # But replace O,H,L,C
'H': x * base + 0.0001,
'L': x * base - 0.0001,
'C': x * base} for x in range(0, datalen)]}
return {'UNITTEST/BTC': [
[
pair[x][0], # Keep old dates
x * base, # But replace O,H,L,C
x * base + 0.0001,
x * base - 0.0001,
x * base,
pair[x][5], # Keep old volume
] for x in range(0, datalen)
]}
if what == 'lower':
return {'UNITTEST/BTC':
[{'T': pair[x]['T'], # Keep old dates
'V': pair[x]['V'], # Keep old volume
'BV': pair[x]['BV'], # keep too
'O': 1 - x * base, # But replace O,H,L,C
'H': 1 - x * base + 0.0001,
'L': 1 - x * base - 0.0001,
'C': 1 - x * base} for x in range(0, datalen)]}
return {'UNITTEST/BTC': [
[
pair[x][0], # Keep old dates
1 - x * base, # But replace O,H,L,C
1 - x * base + 0.0001,
1 - x * base - 0.0001,
1 - x * base,
pair[x][5] # Keep old volume
] for x in range(0, datalen)
]}
if what == 'sine':
hz = 0.1 # frequency
return {'UNITTEST/BTC':
[{'T': pair[x]['T'], # Keep old dates
'V': pair[x]['V'], # Keep old volume
'BV': pair[x]['BV'], # keep too
# But replace O,H,L,C
'O': math.sin(x * hz) / 1000 + base,
'H': math.sin(x * hz) / 1000 + base + 0.0001,
'L': math.sin(x * hz) / 1000 + base - 0.0001,
'C': math.sin(x * hz) / 1000 + base} for x in range(0, datalen)]}
return {'UNITTEST/BTC': [
[
pair[x][0], # Keep old dates
math.sin(x * hz) / 1000 + base, # But replace O,H,L,C
math.sin(x * hz) / 1000 + base + 0.0001,
math.sin(x * hz) / 1000 + base - 0.0001,
math.sin(x * hz) / 1000 + base,
pair[x][5] # Keep old volume
] for x in range(0, datalen)
]}
return data
@@ -247,11 +268,11 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
assert 'live' in config
assert log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert 'realistic_simulation'in config
assert 'realistic_simulation' in config
assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples)
assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples)
assert 'refresh_pairs'in config
assert 'refresh_pairs' in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert 'timerange' in config
assert log_has(
@@ -266,7 +287,7 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
)
def test_start(mocker, default_conf, caplog) -> None:
def test_start(mocker, init_backtesting, default_conf, caplog) -> None:
"""
Test start() function
"""
@@ -306,10 +327,11 @@ def test_backtesting__init__(mocker, default_conf) -> None:
assert init_mock.call_count == 1
def test_backtesting_init(default_conf) -> None:
def test_backtesting_init(mocker, default_conf) -> None:
"""
Test Backtesting._init() method
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
backtesting = Backtesting(default_conf)
assert backtesting.config == default_conf
assert isinstance(backtesting.analyze, Analyze)
@@ -319,7 +341,7 @@ def test_backtesting_init(default_conf) -> None:
assert callable(backtesting.populate_sell_trend)
def test_tickerdata_to_dataframe(default_conf) -> None:
def test_tickerdata_to_dataframe(init_backtesting, default_conf) -> None:
"""
Test Backtesting.tickerdata_to_dataframe() method
"""
@@ -338,7 +360,7 @@ def test_tickerdata_to_dataframe(default_conf) -> None:
assert data['UNITTEST/BTC'].equals(data2['UNITTEST/BTC'])
def test_get_timeframe() -> None:
def test_get_timeframe(init_backtesting) -> None:
"""
Test Backtesting.get_timeframe() method
"""
@@ -356,7 +378,7 @@ def test_get_timeframe() -> None:
assert max_date.isoformat() == '2017-11-14T22:59:00+00:00'
def test_generate_text_table():
def test_generate_text_table(init_backtesting):
"""
Test Backtesting.generate_text_table() method
"""
@@ -391,12 +413,14 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
"""
Test Backtesting.start() method
"""
def get_timeframe(input1, input2):
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
mocker.patch('freqtrade.freqtradebot.Analyze', MagicMock())
mocker.patch('freqtrade.optimize.load_data', mocked_load_data)
mocker.patch('freqtrade.exchange.get_ticker_history')
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch.multiple(
'freqtrade.optimize.backtesting.Backtesting',
backtest=MagicMock(),
@@ -426,7 +450,7 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
assert log_has(line, caplog.record_tuples)
def test_backtest(default_conf) -> None:
def test_backtest(init_backtesting, default_conf) -> None:
"""
Test Backtesting.backtest() method
"""
@@ -445,7 +469,7 @@ def test_backtest(default_conf) -> None:
assert not results.empty
def test_backtest_1min_ticker_interval(default_conf) -> None:
def test_backtest_1min_ticker_interval(init_backtesting, default_conf) -> None:
"""
Test Backtesting.backtest() method with 1 min ticker
"""
@@ -465,7 +489,7 @@ def test_backtest_1min_ticker_interval(default_conf) -> None:
assert not results.empty
def test_processed() -> None:
def test_processed(init_backtesting) -> None:
"""
Test Backtesting.backtest() method with offline data
"""
@@ -481,14 +505,15 @@ def test_processed() -> None:
assert col in cols
def test_backtest_pricecontours(default_conf) -> None:
def test_backtest_pricecontours(init_backtesting, default_conf, fee, mocker) -> None:
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
tests = [['raise', 17], ['lower', 0], ['sine', 17]]
for [contour, numres] in tests:
simple_backtest(default_conf, contour, numres)
# Test backtest using offline data (testdata directory)
def test_backtest_ticks(default_conf):
def test_backtest_ticks(init_backtesting, default_conf):
ticks = [1, 5]
fun = _BACKTESTING.populate_buy_trend
for tick in ticks:
@@ -497,7 +522,7 @@ def test_backtest_ticks(default_conf):
assert not results.empty
def test_backtest_clash_buy_sell(default_conf):
def test_backtest_clash_buy_sell(init_backtesting, default_conf):
# Override the default buy trend function in our default_strategy
def fun(dataframe=None):
buy_value = 1
@@ -509,7 +534,7 @@ def test_backtest_clash_buy_sell(default_conf):
assert results.empty
def test_backtest_only_sell(default_conf):
def test_backtest_only_sell(init_backtesting, default_conf):
# Override the default buy trend function in our default_strategy
def fun(dataframe=None):
buy_value = 0
@@ -521,15 +546,17 @@ def test_backtest_only_sell(default_conf):
assert results.empty
def test_backtest_alternate_buy_sell(default_conf):
def test_backtest_alternate_buy_sell(init_backtesting, default_conf, fee, mocker):
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
backtest_conf = _make_backtest_conf(conf=default_conf, pair='UNITTEST/BTC')
results = _run_backtest_1(_trend_alternate, backtest_conf)
assert len(results) == 3
def test_backtest_record(default_conf, mocker):
def test_backtest_record(init_backtesting, default_conf, fee, mocker):
names = []
records = []
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
mocker.patch(
'freqtrade.optimize.backtesting.file_dump_json',
new=lambda n, r: (names.append(n), records.append(r))
@@ -562,14 +589,16 @@ def test_backtest_record(default_conf, mocker):
assert dur > 0
def test_backtest_start_live(default_conf, mocker, caplog):
default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
def test_backtest_start_live(init_backtesting, default_conf, mocker, caplog):
conf = deepcopy(default_conf)
conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
mocker.patch('freqtrade.exchange.get_ticker_history',
new=lambda n, i: _load_pair_as_ticks(n, i))
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', MagicMock())
mocker.patch('freqtrade.optimize.backtesting.Backtesting._generate_text_table', MagicMock())
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
read_data=json.dumps(default_conf)
read_data=json.dumps(conf)
))
args = MagicMock()

View File

@@ -1,20 +1,34 @@
# pragma pylint: disable=missing-docstring,W0212,C0103
import json
import os
import signal
from copy import deepcopy
from unittest.mock import MagicMock
import pytest
import pandas as pd
from freqtrade.optimize.__init__ import load_tickerdata_file
from freqtrade.optimize.hyperopt import Hyperopt, start
from freqtrade.strategy.strategy import Strategy
from freqtrade.tests.conftest import default_conf, log_has
from freqtrade.tests.conftest import log_has
from freqtrade.tests.optimize.test_backtesting import get_args
# Avoid to reinit the same object again and again
_HYPEROPT = Hyperopt(default_conf())
_HYPEROPT_INITIALIZED = False
_HYPEROPT = None
@pytest.fixture(scope='function')
def init_hyperopt(default_conf, mocker):
global _HYPEROPT_INITIALIZED, _HYPEROPT
if not _HYPEROPT_INITIALIZED:
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf',
MagicMock(return_value=default_conf))
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
_HYPEROPT = Hyperopt(default_conf)
_HYPEROPT_INITIALIZED = True
# Functions for recurrent object patching
@@ -52,9 +66,10 @@ def test_start(mocker, default_conf, caplog) -> None:
start_mock = MagicMock()
mocker.patch('freqtrade.logger.Logger.set_format', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock)
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
read_data=json.dumps(default_conf)
))
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf',
MagicMock(return_value=default_conf))
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
args = [
'--config', 'config.json',
'--strategy', 'default_strategy',
@@ -75,7 +90,7 @@ def test_start(mocker, default_conf, caplog) -> None:
assert start_mock.call_count == 1
def test_loss_calculation_prefer_correct_trade_count() -> None:
def test_loss_calculation_prefer_correct_trade_count(init_hyperopt) -> None:
"""
Test Hyperopt.calculate_loss()
"""
@@ -89,7 +104,7 @@ def test_loss_calculation_prefer_correct_trade_count() -> None:
assert under > correct
def test_loss_calculation_prefer_shorter_trades() -> None:
def test_loss_calculation_prefer_shorter_trades(init_hyperopt) -> None:
"""
Test Hyperopt.calculate_loss()
"""
@@ -100,7 +115,7 @@ def test_loss_calculation_prefer_shorter_trades() -> None:
assert shorter < longer
def test_loss_calculation_has_limited_profit() -> None:
def test_loss_calculation_has_limited_profit(init_hyperopt) -> None:
hyperopt = _HYPEROPT
correct = hyperopt.calculate_loss(hyperopt.expected_max_profit, hyperopt.target_trades, 20)
@@ -110,7 +125,7 @@ def test_loss_calculation_has_limited_profit() -> None:
assert under > correct
def test_log_results_if_loss_improves(caplog) -> None:
def test_log_results_if_loss_improves(init_hyperopt, caplog) -> None:
hyperopt = _HYPEROPT
hyperopt.current_best_loss = 2
hyperopt.log_results(
@@ -124,7 +139,7 @@ def test_log_results_if_loss_improves(caplog) -> None:
assert log_has(' 1/2: foo. Loss 1.00000', caplog.record_tuples)
def test_no_log_if_loss_does_not_improve(caplog) -> None:
def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None:
hyperopt = _HYPEROPT
hyperopt.current_best_loss = 2
hyperopt.log_results(
@@ -135,7 +150,7 @@ def test_no_log_if_loss_does_not_improve(caplog) -> None:
assert caplog.record_tuples == []
def test_fmin_best_results(mocker, default_conf, caplog) -> None:
def test_fmin_best_results(mocker, init_hyperopt, default_conf, caplog) -> None:
fmin_result = {
"macd_below_zero": 0,
"adx": 1,
@@ -170,6 +185,7 @@ def test_fmin_best_results(mocker, default_conf, caplog) -> None:
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value=fmin_result)
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.logger.Logger.set_format', MagicMock())
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
Strategy({'strategy': 'default_strategy'})
hyperopt = Hyperopt(conf)
@@ -204,7 +220,7 @@ def test_fmin_best_results(mocker, default_conf, caplog) -> None:
assert line in caplog.text
def test_fmin_throw_value_error(mocker, default_conf, caplog) -> None:
def test_fmin_throw_value_error(mocker, init_hyperopt, default_conf, caplog) -> None:
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.fmin', side_effect=ValueError())
@@ -215,6 +231,8 @@ def test_fmin_throw_value_error(mocker, default_conf, caplog) -> None:
conf.update({'spaces': 'all'})
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.logger.Logger.set_format', MagicMock())
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
Strategy({'strategy': 'default_strategy'})
hyperopt = Hyperopt(conf)
hyperopt.trials = create_trials(mocker)
@@ -232,7 +250,7 @@ def test_fmin_throw_value_error(mocker, default_conf, caplog) -> None:
assert line in caplog.text
def test_resuming_previous_hyperopt_results_succeeds(mocker, default_conf) -> None:
def test_resuming_previous_hyperopt_results_succeeds(mocker, init_hyperopt, default_conf) -> None:
trials = create_trials(mocker)
conf = deepcopy(default_conf)
@@ -257,6 +275,7 @@ def test_resuming_previous_hyperopt_results_succeeds(mocker, default_conf) -> No
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.logger.Logger.set_format', MagicMock())
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
Strategy({'strategy': 'default_strategy'})
hyperopt = Hyperopt(conf)
@@ -275,7 +294,7 @@ def test_resuming_previous_hyperopt_results_succeeds(mocker, default_conf) -> No
assert total_tries == (current_tries + len(trials.results))
def test_save_trials_saves_trials(mocker, caplog) -> None:
def test_save_trials_saves_trials(mocker, init_hyperopt, caplog) -> None:
create_trials(mocker)
mock_dump = mocker.patch('freqtrade.optimize.hyperopt.pickle.dump', return_value=None)
@@ -284,22 +303,24 @@ def test_save_trials_saves_trials(mocker, caplog) -> None:
hyperopt.save_trials()
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
assert log_has(
'Saving Trials to \'freqtrade/tests/optimize/ut_trials.pickle\'',
'Saving Trials to \'{}\''.format(trials_file),
caplog.record_tuples
)
mock_dump.assert_called_once()
def test_read_trials_returns_trials_file(mocker, caplog) -> None:
def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None:
trials = create_trials(mocker)
mock_load = mocker.patch('freqtrade.optimize.hyperopt.pickle.load', return_value=trials)
mock_open = mocker.patch('freqtrade.optimize.hyperopt.open', return_value=mock_load)
hyperopt = _HYPEROPT
hyperopt_trial = hyperopt.read_trials()
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
assert log_has(
'Reading Trials from \'freqtrade/tests/optimize/ut_trials.pickle\'',
'Reading Trials from \'{}\''.format(trials_file),
caplog.record_tuples
)
assert hyperopt_trial == trials
@@ -307,7 +328,7 @@ def test_read_trials_returns_trials_file(mocker, caplog) -> None:
mock_load.assert_called_once()
def test_roi_table_generation() -> None:
def test_roi_table_generation(init_hyperopt) -> None:
params = {
'roi_t1': 5,
'roi_t2': 10,
@@ -321,10 +342,11 @@ def test_roi_table_generation() -> None:
assert hyperopt.generate_roi_table(params) == {0: 6, 15: 3, 25: 1, 30: 0}
def test_start_calls_fmin(mocker, default_conf) -> None:
def test_start_calls_fmin(mocker, init_hyperopt, default_conf) -> None:
trials = create_trials(mocker)
mocker.patch('freqtrade.optimize.hyperopt.sorted', return_value=trials.results)
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
mock_fmin = mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
conf = deepcopy(default_conf)
@@ -342,7 +364,7 @@ def test_start_calls_fmin(mocker, default_conf) -> None:
mock_fmin.assert_called_once()
def test_start_uses_mongotrials(mocker, default_conf) -> None:
def test_start_uses_mongotrials(mocker, init_hyperopt, default_conf) -> None:
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mock_fmin = mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
mock_mongotrials = mocker.patch(
@@ -357,6 +379,7 @@ def test_start_uses_mongotrials(mocker, default_conf) -> None:
conf.update({'timerange': None})
conf.update({'spaces': 'all'})
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
hyperopt = Hyperopt(conf)
hyperopt.tickerdata_to_dataframe = MagicMock()
@@ -385,7 +408,7 @@ def test_format_results():
assert x.find(' 66.67%')
def test_signal_handler(mocker):
def test_signal_handler(mocker, init_hyperopt):
"""
Test Hyperopt.signal_handler()
"""
@@ -395,11 +418,11 @@ def test_signal_handler(mocker):
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.log_trials_result', m)
hyperopt = _HYPEROPT
hyperopt.signal_handler(9, None)
hyperopt.signal_handler(signal.SIGTERM, None)
assert m.call_count == 3
def test_has_space():
def test_has_space(init_hyperopt):
"""
Test Hyperopt.has_space() method
"""
@@ -412,7 +435,7 @@ def test_has_space():
assert _HYPEROPT.has_space('buy')
def test_populate_indicators() -> None:
def test_populate_indicators(init_hyperopt) -> None:
"""
Test Hyperopt.populate_indicators()
"""
@@ -427,7 +450,7 @@ def test_populate_indicators() -> None:
assert 'cci' in dataframe
def test_buy_strategy_generator() -> None:
def test_buy_strategy_generator(init_hyperopt) -> None:
"""
Test Hyperopt.buy_strategy_generator()
"""
@@ -484,7 +507,7 @@ def test_buy_strategy_generator() -> None:
assert 1 in result['buy']
def test_generate_optimizer(mocker, default_conf) -> None:
def test_generate_optimizer(mocker, init_hyperopt, default_conf) -> None:
"""
Test Hyperopt.generate_optimizer() function
"""
@@ -503,6 +526,7 @@ def test_generate_optimizer(mocker, default_conf) -> None:
'freqtrade.optimize.hyperopt.Hyperopt.backtest',
MagicMock(return_value=backtest_result)
)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
optimizer_param = {
'adx': {'enabled': False},

View File

@@ -52,11 +52,11 @@ def test_load_data_30min_ticker(ticker_history, mocker, caplog) -> None:
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
file = 'freqtrade/tests/testdata/UNITTEST_BTC-30m.json'
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-30m.json')
_backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['UNITTEST/BTC'], ticker_interval='30m')
assert os.path.isfile(file) is True
assert not log_has('Download the pair: "ETH/BTC", Interval: 30 min', caplog.record_tuples)
assert not log_has('Download the pair: "UNITTEST/BTC", Interval: 30m', caplog.record_tuples)
_clean_test_file(file)
@@ -66,11 +66,11 @@ def test_load_data_5min_ticker(ticker_history, mocker, caplog) -> None:
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
file = 'freqtrade/tests/testdata/ETH_BTC-5m.json'
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-5m.json')
_backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['ETH/BTC'], ticker_interval='5m')
optimize.load_data(None, pairs=['UNITTEST/BTC'], ticker_interval='5m')
assert os.path.isfile(file) is True
assert not log_has('Download the pair: "ETH/BTC", Interval: 5 min', caplog.record_tuples)
assert not log_has('Download the pair: "UNITTEST/BTC", Interval: 5m', caplog.record_tuples)
_clean_test_file(file)
@@ -80,11 +80,11 @@ def test_load_data_1min_ticker(ticker_history, mocker, caplog) -> None:
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
file = 'freqtrade/tests/testdata/ETH_BTC-1m.json'
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-1m.json')
_backup_file(file, copy_file=True)
optimize.load_data(None, ticker_interval='1m', pairs=['ETH/BTC'])
optimize.load_data(None, ticker_interval='1m', pairs=['UNITTEST/BTC'])
assert os.path.isfile(file) is True
assert not log_has('Download the pair: "ETH/BTC", Interval: 1 min', caplog.record_tuples)
assert not log_has('Download the pair: "UNITTEST/BTC", Interval: 1m', caplog.record_tuples)
_clean_test_file(file)
@@ -94,11 +94,12 @@ def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog) -> None:
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
file = 'freqtrade/tests/testdata/MEME_BTC-1m.json'
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
_backup_file(file)
optimize.load_data(None, ticker_interval='1m', pairs=['MEME/BTC'])
assert os.path.isfile(file) is True
assert log_has('Download the pair: "MEME/BTC", Interval: 1 min', caplog.record_tuples)
assert log_has('Download the pair: "MEME/BTC", Interval: 1m', caplog.record_tuples)
_clean_test_file(file)
@@ -109,10 +110,10 @@ def test_testdata_path() -> None:
def test_download_pairs(ticker_history, mocker) -> None:
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history)
file1_1 = 'freqtrade/tests/testdata/MEME_BTC-1m.json'
file1_5 = 'freqtrade/tests/testdata/MEME_BTC-5m.json'
file2_1 = 'freqtrade/tests/testdata/CFI_BTC-1m.json'
file2_5 = 'freqtrade/tests/testdata/CFI_BTC-5m.json'
file1_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
file1_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-5m.json')
file2_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'CFI_BTC-1m.json')
file2_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'CFI_BTC-5m.json')
_backup_file(file1_1)
_backup_file(file1_5)
@@ -149,8 +150,8 @@ def test_download_pairs_exception(ticker_history, mocker, caplog) -> None:
mocker.patch('freqtrade.optimize.__init__.download_backtesting_testdata',
side_effect=BaseException('File Error'))
file1_1 = 'freqtrade/tests/testdata/MEME_BTC-1m.json'
file1_5 = 'freqtrade/tests/testdata/MEME_BTC-5m.json'
file1_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
file1_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-5m.json')
_backup_file(file1_1)
_backup_file(file1_5)
@@ -158,21 +159,21 @@ def test_download_pairs_exception(ticker_history, mocker, caplog) -> None:
# clean files freshly downloaded
_clean_test_file(file1_1)
_clean_test_file(file1_5)
assert log_has('Failed to download the pair: "MEME/BTC", Interval: 1 min', caplog.record_tuples)
assert log_has('Failed to download the pair: "MEME/BTC", Interval: 1m', caplog.record_tuples)
def test_download_backtesting_testdata(ticker_history, mocker) -> None:
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history)
# Download a 1 min ticker file
file1 = 'freqtrade/tests/testdata/XEL_BTC-1m.json'
file1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'XEL_BTC-1m.json')
_backup_file(file1)
download_backtesting_testdata(None, pair="XEL/BTC", interval='1m')
assert os.path.isfile(file1) is True
_clean_test_file(file1)
# Download a 5 min ticker file
file2 = 'freqtrade/tests/testdata/STORJ_BTC-5m.json'
file2 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'STORJ_BTC-5m.json')
_backup_file(file2)
download_backtesting_testdata(None, pair="STORJ/BTC", interval='5m')
@@ -181,7 +182,10 @@ def test_download_backtesting_testdata(ticker_history, mocker) -> None:
def test_download_backtesting_testdata2(mocker) -> None:
tick = [{'T': 'bar'}, {'T': 'foo'}]
tick = [
[1509836520000, 0.00162008, 0.00162008, 0.00162008, 0.00162008, 108.14853839],
[1509836580000, 0.00161, 0.00161, 0.00161, 0.00161, 82.390199]
]
mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick)
assert download_backtesting_testdata(None, pair="UNITTEST/BTC", interval='1m')
@@ -211,7 +215,8 @@ def test_init(default_conf, mocker) -> None:
def test_trim_tickerlist() -> None:
with open('freqtrade/tests/testdata/ETH_BTC-1m.json') as data_file:
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-1m.json')
with open(file) as data_file:
ticker_list = json.load(data_file)
ticker_list_len = len(ticker_list)
@@ -260,7 +265,8 @@ def test_file_dump_json() -> None:
Test file_dump_json()
:return: None
"""
file = 'freqtrade/tests/testdata/test_{id}.json'.format(id=str(uuid.uuid4()))
file = os.path.join(os.path.dirname(__file__), '..', 'testdata',
'test_{id}.json'.format(id=str(uuid.uuid4())))
data = {'bar': 'foo'}
# check the file we will create does not exist

View File

@@ -25,7 +25,7 @@ def prec_satoshi(a, b) -> float:
# Unit tests
def test_rpc_trade_status(default_conf, ticker, mocker) -> None:
def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
"""
Test rpc_trade_status() method
"""
@@ -35,7 +35,8 @@ def test_rpc_trade_status(default_conf, ticker, mocker) -> None:
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -67,13 +68,13 @@ def test_rpc_trade_status(default_conf, ticker, mocker) -> None:
'*Current Rate:* `0.00001098`\n'
'*Close Profit:* `None`\n'
'*Current Profit:* `-0.59%`\n'
'*Open Order:* `(LIMIT_BUY rem=0.00000000)`'
'*Open Order:* `(limit buy rem=0.00000000)`'
]
assert result == result_message
assert trade.find('[ETH/BTC]') >= 0
def test_rpc_status_table(default_conf, ticker, mocker) -> None:
def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
"""
Test rpc_status_table() method
"""
@@ -83,7 +84,8 @@ def test_rpc_status_table(default_conf, ticker, mocker) -> None:
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -106,8 +108,8 @@ def test_rpc_status_table(default_conf, ticker, mocker) -> None:
assert '-0.59%' in result['Profit'].all()
def test_rpc_daily_profit(default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker)\
-> None:
def test_rpc_daily_profit(default_conf, update, ticker, fee,
limit_buy_order, limit_sell_order, mocker) -> None:
"""
Test rpc_daily_profit() method
"""
@@ -117,7 +119,8 @@ def test_rpc_daily_profit(default_conf, update, ticker, limit_buy_order, limit_s
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -158,8 +161,8 @@ def test_rpc_daily_profit(default_conf, update, ticker, limit_buy_order, limit_s
assert days.find('must be an integer greater than 0') >= 0
def test_rpc_trade_statistics(
default_conf, ticker, ticker_sell_up, limit_buy_order, limit_sell_order, mocker) -> None:
def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
limit_buy_order, limit_sell_order, mocker) -> None:
"""
Test rpc_trade_statistics() method
"""
@@ -173,7 +176,8 @@ def test_rpc_trade_statistics(
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -220,8 +224,8 @@ def test_rpc_trade_statistics(
# Test that rpc_trade_statistics can handle trades that lacks
# trade.open_rate (it is set to None)
def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, ticker_sell_up, limit_buy_order,
limit_sell_order):
def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee,
ticker_sell_up, limit_buy_order, limit_sell_order):
"""
Test rpc_trade_statistics() method
"""
@@ -235,7 +239,8 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, ticker_sell_u
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -253,7 +258,8 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, ticker_sell_u
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up
get_ticker=ticker_sell_up,
get_fee=fee
)
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
@@ -401,8 +407,9 @@ def test_rpc_forcesell(default_conf, ticker, mocker) -> None:
cancel_order=cancel_order_mock,
get_order=MagicMock(
return_value={
'closed': True,
'type': 'LIMIT_BUY',
'status': 'closed',
'type': 'limit',
'side': 'buy'
}
)
)
@@ -448,8 +455,9 @@ def test_rpc_forcesell(default_conf, ticker, mocker) -> None:
mocker.patch(
'freqtrade.freqtradebot.exchange.get_order',
return_value={
'closed': None,
'type': 'LIMIT_BUY'
'status': 'open',
'type': 'limit',
'side': 'buy'
}
)
# check that the trade is called, which is done
@@ -464,8 +472,9 @@ def test_rpc_forcesell(default_conf, ticker, mocker) -> None:
mocker.patch(
'freqtrade.freqtradebot.exchange.get_order',
return_value={
'closed': None,
'type': 'LIMIT_SELL'
'status': 'open',
'type': 'limit',
'side': 'sell'
}
)
(error, res) = rpc.rpc_forcesell('2')
@@ -475,7 +484,7 @@ def test_rpc_forcesell(default_conf, ticker, mocker) -> None:
assert cancel_order_mock.call_count == 1
def test_performance_handle(default_conf, ticker, limit_buy_order,
def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
limit_sell_order, mocker) -> None:
"""
Test rpc_performance() method
@@ -487,7 +496,8 @@ def test_performance_handle(default_conf, ticker, limit_buy_order,
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_balances=MagicMock(return_value=ticker),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))

View File

@@ -333,7 +333,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_order_id')
buy=MagicMock(return_value={'id': 'mocked_order_id'})
)
msg_mock = MagicMock()
mocker.patch.multiple(
@@ -374,7 +374,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker) -> None:
assert msg_mock.call_count == 1
def test_daily_handle(default_conf, update, ticker, limit_buy_order,
def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
limit_sell_order, mocker) -> None:
"""
Test _daily() method
@@ -389,7 +389,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order,
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_pair_detail_url=MagicMock()
get_fee=fee
)
msg_mock = MagicMock()
mocker.patch.multiple(
@@ -486,7 +486,7 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
assert str('Daily Profit over the last 7 days') in msg_mock.call_args_list[0][0][0]
def test_profit_handle(default_conf, update, ticker, ticker_sell_up,
def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
limit_buy_order, limit_sell_order, mocker) -> None:
"""
Test _profit() method
@@ -497,7 +497,8 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up,
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
msg_mock = MagicMock()
mocker.patch.multiple(
@@ -749,7 +750,7 @@ def test_stop_handle_already_stopped(default_conf, update, mocker) -> None:
assert 'already stopped' in msg_mock.call_args_list[0][0][0]
def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker) -> None:
def test_forcesell_handle(default_conf, update, ticker, fee, ticker_sell_up, mocker) -> None:
"""
Test _forcesell() method
"""
@@ -761,7 +762,8 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker)
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -788,7 +790,7 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker)
assert '0.919 USD' in rpc_mock.call_args_list[-1][0][0]
def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, mocker) -> None:
def test_forcesell_down_handle(default_conf, update, ticker, fee, ticker_sell_down, mocker) -> None:
"""
Test _forcesell() method
"""
@@ -800,7 +802,8 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -831,7 +834,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
assert '-0.824 USD' in rpc_mock.call_args_list[-1][0][0]
def test_forcesell_all_handle(default_conf, update, ticker, mocker) -> None:
def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None:
"""
Test _forcesell() method
"""
@@ -844,7 +847,8 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker) -> None:
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -907,8 +911,8 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
assert 'Invalid argument.' in msg_mock.call_args_list[0][0][0]
def test_performance_handle(default_conf, update, ticker, limit_buy_order,
limit_sell_order, mocker) -> None:
def test_performance_handle(default_conf, update, ticker, fee,
limit_buy_order, limit_sell_order, mocker) -> None:
"""
Test _performance() method
"""
@@ -923,7 +927,8 @@ def test_performance_handle(default_conf, update, ticker, limit_buy_order,
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -987,7 +992,7 @@ def test_count_handle(default_conf, update, ticker, mocker) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_order_id')
buy=MagicMock(return_value={'id': 'mocked_order_id'})
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
telegram = Telegram(freqtradebot)

View File

@@ -1,18 +1,8 @@
import json
import pytest
from pandas import DataFrame
from freqtrade.analyze import Analyze
from freqtrade.strategy.default_strategy import DefaultStrategy, class_name
@pytest.fixture
def result():
with open('freqtrade/tests/testdata/ETH_BTC-1m.json') as data_file:
return Analyze.parse_ticker_dataframe(json.load(data_file))
def test_default_strategy_class_name():
assert class_name == DefaultStrategy.__name__

View File

@@ -1,6 +1,7 @@
# pragma pylint: disable=missing-docstring,C0103,protected-access
import freqtrade.tests.conftest as tt # test tools
from unittest.mock import MagicMock
# whitelist, blacklist, filtering, all of that will
# eventually become some rules to run on a generic ACL engine
@@ -26,81 +27,12 @@ def whitelist_conf():
return config
def get_market_summaries():
return {
'TKN/BTC': {
'symbol': 'TKN/BTC',
'info': {
'High': 0.00000919,
'Low': 0.00000820,
'Volume': 74339.61396015,
'Last': 0.00000820,
'BaseVolume': 1664,
'TimeStamp': '2014-07-09T07:19:30.15',
'Bid': 0.00000820,
'Ask': 0.00000831,
'OpenBuyOrders': 15,
'OpenSellOrders': 15,
'PrevDay': 0.00000821,
'Created': '2014-03-20T06:00:00',
'DisplayMarketName': ''
}
},
'ETH/BTC': {
'symbol': 'ETH/BTC',
'info': {
'High': 0.00000072,
'Low': 0.00000001,
'Volume': 166340678.42280999,
'Last': 0.00000005,
'BaseVolume': 42,
'TimeStamp': '2014-07-09T07:21:40.51',
'Bid': 0.00000004,
'Ask': 0.00000005,
'OpenBuyOrders': 18,
'OpenSellOrders': 18,
'PrevDay': 0.00000002,
'Created': '2014-05-30T07:57:49.637',
'DisplayMarketName': ''
}
},
'BLK/BTC': {
'symbol': 'BLK/BTC',
'info': {
'High': 0.00000072,
'Low': 0.00000001,
'Volume': 166340678.42280999,
'Last': 0.00000005,
'BaseVolume': 3,
'TimeStamp': '2014-07-09T07:21:40.51',
'Bid': 0.00000004,
'Ask': 0.00000005,
'OpenBuyOrders': 18,
'OpenSellOrders': 18,
'PrevDay': 0.00000002,
'Created': '2014-05-30T07:57:49.637',
'DisplayMarketName': ''
}}
}
def get_health():
return {
'ETH/BTC': {'base': 'ETH', 'active': True},
'TKN/BTC': {'base': 'TKN', 'active': True},
'BLK/BTC': {'base': 'BLK', 'active': True}}
def get_health_empty():
return {}
def test_refresh_market_pair_not_in_whitelist(mocker):
def test_refresh_market_pair_not_in_whitelist(mocker, markets):
conf = whitelist_conf()
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health)
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets)
refreshedwhitelist = freqtradebot._refresh_whitelist(
conf['exchange']['pair_whitelist'] + ['XXX/BTC']
)
@@ -110,11 +42,11 @@ def test_refresh_market_pair_not_in_whitelist(mocker):
assert whitelist == refreshedwhitelist
def test_refresh_whitelist(mocker):
def test_refresh_whitelist(mocker, markets):
conf = whitelist_conf()
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health)
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets)
refreshedwhitelist = freqtradebot._refresh_whitelist(conf['exchange']['pair_whitelist'])
# List ordered by BaseVolume
@@ -123,17 +55,18 @@ def test_refresh_whitelist(mocker):
assert whitelist == refreshedwhitelist
def test_refresh_whitelist_dynamic(mocker):
def test_refresh_whitelist_dynamic(mocker, markets, tickers):
conf = whitelist_conf()
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
get_wallet_health=get_health,
get_market_summaries=get_market_summaries
get_markets=markets,
get_tickers=tickers,
exchange_has=MagicMock(return_value=True)
)
# argument: use the whitelist dynamically by exchange-volume
whitelist = ['TKN/BTC', 'ETH/BTC']
whitelist = ['ETH/BTC', 'TKN/BTC']
refreshedwhitelist = freqtradebot._refresh_whitelist(
freqtradebot._gen_pair_whitelist(conf['stake_currency'])
@@ -142,10 +75,10 @@ def test_refresh_whitelist_dynamic(mocker):
assert whitelist == refreshedwhitelist
def test_refresh_whitelist_dynamic_empty(mocker):
def test_refresh_whitelist_dynamic_empty(mocker, markets_empty):
conf = whitelist_conf()
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health_empty)
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets_empty)
# argument: use the whitelist dynamically by exchange-volume
whitelist = []

View File

@@ -50,7 +50,7 @@ def test_dataframe_correct_length(result):
def test_dataframe_correct_columns(result):
assert result.columns.tolist() == \
['close', 'high', 'low', 'open', 'date', 'volume']
['date', 'open', 'high', 'low', 'close', 'volume']
def test_populates_buy_trend(result):
@@ -169,17 +169,13 @@ def test_get_signal_handles_exceptions(mocker):
assert _ANALYZE.get_signal('ETH/BTC', '5m') == (False, False)
def test_parse_ticker_dataframe(ticker_history, ticker_history_without_bv):
columns = ['close', 'high', 'low', 'open', 'date', 'volume']
def test_parse_ticker_dataframe(ticker_history):
columns = ['date', 'open', 'high', 'low', 'close', 'volume']
# Test file with BV data
dataframe = Analyze.parse_ticker_dataframe(ticker_history)
assert dataframe.columns.tolist() == columns
# Test file without BV data
dataframe = Analyze.parse_ticker_dataframe(ticker_history_without_bv)
assert dataframe.columns.tolist() == columns
def test_tickerdata_to_dataframe(default_conf) -> None:
"""

View File

@@ -201,29 +201,28 @@ def test_throttle_with_assets(mocker, default_conf) -> None:
assert result == -1
def test_gen_pair_whitelist(mocker, default_conf, get_market_summaries_data) -> None:
def test_gen_pair_whitelist(mocker, default_conf, tickers) -> None:
"""
Test _gen_pair_whitelist() method
"""
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch(
'freqtrade.freqtradebot.exchange.get_market_summaries',
return_value=get_market_summaries_data
)
mocker.patch('freqtrade.freqtradebot.exchange.get_tickers', tickers)
mocker.patch('freqtrade.freqtradebot.exchange.exchange_has', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
# Test to retrieved BTC sorted on BaseVolume
# Test to retrieved BTC sorted on quoteVolume (default)
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC')
assert whitelist == ['ZCL/BTC', 'ZEC/BTC', 'XZC/BTC', 'XWC/BTC']
assert whitelist == ['ETH/BTC', 'TKN/BTC', 'BLK/BTC', 'LTC/BTC']
# Test to retrieved BTC sorted on OpenBuyOrders
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC', key='OpenBuyOrders')
assert whitelist == ['XWC/BTC', 'ZCL/BTC', 'ZEC/BTC', 'XZC/BTC']
# Test to retrieve BTC sorted on bidVolume
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC', key='bidVolume')
assert whitelist == ['LTC/BTC', 'TKN/BTC', 'ETH/BTC', 'BLK/BTC']
# Test with USDT sorted on BaseVolume
# Test with USDT sorted on quoteVolume (default)
whitelist = freqtrade._gen_pair_whitelist(base_currency='USDT')
assert whitelist == ['XRP/USDT', 'XVG/USDT', 'XMR/USDT', 'ZEC/USDT']
assert whitelist == ['TKN/USDT', 'ETH/USDT', 'LTC/USDT', 'BLK/USDT']
# Test with ETH (our fixture does not have ETH, but Bittrex returns them)
# Test with ETH (our fixture does not have ETH, so result should be empty)
whitelist = freqtrade._gen_pair_whitelist(base_currency='ETH')
assert whitelist == []
@@ -247,7 +246,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
# Save state of current whitelist
@@ -271,14 +270,14 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker) -> None:
assert whitelist == default_conf['exchange']['pair_whitelist']
def test_create_trade_minimal_amount(default_conf, ticker, mocker) -> None:
def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order, mocker) -> None:
"""
Test create_trade() method
"""
patch_get_signal(mocker)
patch_RPCManager(mocker)
patch_coinmarketcap(mocker)
buy_mock = MagicMock(return_value='mocked_limit_buy')
buy_mock = MagicMock(return_value={'id': limit_buy_order['id']})
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
@@ -295,7 +294,7 @@ def test_create_trade_minimal_amount(default_conf, ticker, mocker) -> None:
assert rate * amount >= conf['stake_amount']
def test_create_trade_no_stake_amount(default_conf, ticker, mocker) -> None:
def test_create_trade_no_stake_amount(default_conf, ticker, limit_buy_order, mocker) -> None:
"""
Test create_trade() method
"""
@@ -306,7 +305,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, mocker) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'),
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5)
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -315,7 +314,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, mocker) -> None:
freqtrade.create_trade()
def test_create_trade_no_pairs(default_conf, ticker, mocker) -> None:
def test_create_trade_no_pairs(default_conf, ticker, limit_buy_order, mocker) -> None:
"""
Test create_trade() method
"""
@@ -326,7 +325,7 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
conf = deepcopy(default_conf)
@@ -340,7 +339,8 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker) -> None:
freqtrade.create_trade()
def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker) -> None:
def test_create_trade_no_pairs_after_blacklist(default_conf, ticker,
limit_buy_order, mocker) -> None:
"""
Test create_trade() method
"""
@@ -351,7 +351,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker) ->
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
conf = deepcopy(default_conf)
@@ -392,7 +392,7 @@ def test_create_trade_no_signal(default_conf, mocker) -> None:
def test_process_trade_creation(default_conf, ticker, limit_buy_order,
health, mocker, caplog) -> None:
markets, mocker, caplog) -> None:
"""
Test the trade creation in _process() method
"""
@@ -403,8 +403,8 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_wallet_health=health,
buy=MagicMock(return_value='mocked_limit_buy'),
get_markets=markets,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
get_order=MagicMock(return_value=limit_buy_order)
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -432,7 +432,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
)
def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None:
def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> None:
"""
Test _process() method when a RequestException happens
"""
@@ -443,7 +443,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_wallet_health=health,
get_markets=markets,
buy=MagicMock(side_effect=requests.exceptions.RequestException)
)
sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None)
@@ -454,7 +454,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None
assert sleep_mock.has_calls()
def test_process_operational_exception(default_conf, ticker, health, mocker) -> None:
def test_process_operational_exception(default_conf, ticker, markets, mocker) -> None:
"""
Test _process() method when an OperationalException happens
"""
@@ -465,7 +465,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker) ->
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_wallet_health=health,
get_markets=markets,
buy=MagicMock(side_effect=OperationalException)
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -477,7 +477,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker) ->
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]
def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, mocker) -> None:
def test_process_trade_handling(default_conf, ticker, limit_buy_order, markets, mocker) -> None:
"""
Test _process()
"""
@@ -488,8 +488,8 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_wallet_health=health,
buy=MagicMock(return_value='mocked_limit_buy'),
get_markets=markets,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
get_order=MagicMock(return_value=limit_buy_order)
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -577,7 +577,7 @@ def test_process_maybe_execute_sell(mocker, default_conf) -> None:
assert freqtrade.process_maybe_execute_sell(trade)
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker) -> None:
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, fee, mocker) -> None:
"""
Test check_handle() method
"""
@@ -591,8 +591,9 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker) -
'ask': 0.00001173,
'last': 0.00001172
}),
buy=MagicMock(return_value='mocked_limit_buy'),
sell=MagicMock(return_value='mocked_limit_sell')
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee
)
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
@@ -603,12 +604,13 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker) -
trade = Trade.query.first()
assert trade
time.sleep(0.01) # Race condition fix
trade.update(limit_buy_order)
assert trade.is_open is True
patch_get_signal(mocker, value=(False, True))
assert freqtrade.handle_trade(trade) is True
assert trade.open_order_id == 'mocked_limit_sell'
assert trade.open_order_id == limit_sell_order['id']
# Simulate fulfilled LIMIT_SELL order for trade
trade.update(limit_sell_order)
@@ -619,7 +621,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) -> None:
def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order, mocker) -> None:
"""
Test check_handle() method
"""
@@ -634,7 +636,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
@@ -676,7 +678,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker) -> None:
assert freqtrade.handle_trade(trades[0]) is True
def test_handle_trade_roi(default_conf, ticker, mocker, caplog) -> None:
def test_handle_trade_roi(default_conf, ticker, limit_buy_order, mocker, caplog) -> None:
"""
Test check_handle() method
"""
@@ -691,7 +693,7 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog) -> None:
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
mocker.patch('freqtrade.freqtradebot.Analyze.min_roi_reached', return_value=True)
@@ -711,7 +713,7 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog) -> None:
assert log_has('Required profit reached. Selling..', caplog.record_tuples)
def test_handle_trade_experimental(default_conf, ticker, mocker, caplog) -> None:
def test_handle_trade_experimental(default_conf, ticker, limit_buy_order, mocker, caplog) -> None:
"""
Test check_handle() method
"""
@@ -726,7 +728,7 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog) -> None
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
mocker.patch('freqtrade.freqtradebot.Analyze.min_roi_reached', return_value=False)
@@ -755,7 +757,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -773,7 +775,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
freqtrade.handle_trade(trade)
def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mocker) -> None:
def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, fee, mocker) -> None:
"""
Test check_handle_timedout() method
"""
@@ -785,14 +787,15 @@ def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mo
validate_pairs=MagicMock(),
get_ticker=ticker,
get_order=MagicMock(return_value=limit_buy_order_old),
cancel_order=cancel_order_mock
cancel_order=cancel_order_mock,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
trade_buy = Trade(
pair='ETH/BTC',
open_rate=0.00001099,
exchange='BITTREX',
exchange='bittrex',
open_order_id='123456789',
amount=90.99181073,
fee=0.0,
@@ -831,7 +834,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old,
trade_sell = Trade(
pair='ETH/BTC',
open_rate=0.00001099,
exchange='BITTREX',
exchange='bittrex',
open_order_id='123456789',
amount=90.99181073,
fee=0.0,
@@ -870,7 +873,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
trade_buy = Trade(
pair='ETH/BTC',
open_rate=0.00001099,
exchange='BITTREX',
exchange='bittrex',
open_order_id='123456789',
amount=90.99181073,
fee=0.0,
@@ -917,7 +920,7 @@ def test_check_handle_timedout_exception(default_conf, ticker, mocker, caplog) -
trade_buy = Trade(
pair='ETH/BTC',
open_rate=0.00001099,
exchange='BITTREX',
exchange='bittrex',
open_order_id='123456789',
amount=90.99181073,
fee=0.0,
@@ -989,7 +992,7 @@ def test_handle_timedout_limit_sell(mocker, default_conf) -> None:
assert cancel_order_mock.call_count == 1
def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker) -> None:
def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> None:
"""
Test execute_sell() method with a ticker going UP
"""
@@ -999,7 +1002,8 @@ def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker) -> None:
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -1029,7 +1033,7 @@ def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker) -> None:
assert '0.919 USD' in rpc_mock.call_args_list[-1][0][0]
def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker) -> None:
def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker) -> None:
"""
Test execute_sell() method with a ticker going DOWN
"""
@@ -1040,7 +1044,8 @@ def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker) -> No
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -1068,7 +1073,8 @@ def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker) -> No
assert '-0.824 USD' in rpc_mock.call_args_list[-1][0][0]
def test_execute_sell_without_conf_sell_up(default_conf, ticker, ticker_sell_up, mocker) -> None:
def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
ticker_sell_up, mocker) -> None:
"""
Test execute_sell() method with a ticker going DOWN and with a bot config empty
"""
@@ -1078,7 +1084,8 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, ticker_sell_up,
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -1107,7 +1114,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, ticker_sell_up,
assert 'USD' not in rpc_mock.call_args_list[-1][0][0]
def test_execute_sell_without_conf_sell_down(default_conf, ticker,
def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
ticker_sell_down, mocker) -> None:
"""
Test execute_sell() method with a ticker going DOWN and with a bot config empty
@@ -1118,7 +1125,8 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker,
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker
get_ticker=ticker,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
@@ -1161,7 +1169,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker) -
'ask': 0.00002173,
'last': 0.00002172
}),
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
conf = deepcopy(default_conf)
conf['experimental'] = {
@@ -1193,7 +1201,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker)
'ask': 0.00002173,
'last': 0.00002172
}),
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
conf = deepcopy(default_conf)
conf['experimental'] = {
@@ -1225,7 +1233,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker) ->
'ask': 0.00000173,
'last': 0.00000172
}),
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
conf = deepcopy(default_conf)
conf['experimental'] = {
@@ -1257,7 +1265,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker) ->
'ask': 0.00000173,
'last': 0.00000172
}),
buy=MagicMock(return_value='mocked_limit_buy')
buy=MagicMock(return_value={'id': limit_buy_order['id']})
)
conf = deepcopy(default_conf)

View File

@@ -89,7 +89,7 @@ def test_init_prod_db(default_conf, mocker):
os.rename(prod_db_swp, prod_db)
def test_update_with_bittrex(limit_buy_order, limit_sell_order):
def test_update_with_bittrex(limit_buy_order, limit_sell_order, fee):
"""
On this test we will buy and sell a crypto currency.
@@ -120,7 +120,7 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
assert trade.open_order_id is None
@@ -143,11 +143,11 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order):
assert trade.close_date is not None
def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order):
def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
@@ -165,11 +165,11 @@ def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order):
assert trade.calc_profit_percent() == 0.06201057
def test_calc_close_trade_price_exception(limit_buy_order):
def test_calc_close_trade_price_exception(limit_buy_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
@@ -191,7 +191,7 @@ def test_update_open_order(limit_buy_order):
assert trade.close_profit is None
assert trade.close_date is None
limit_buy_order['closed'] = False
limit_buy_order['status'] = 'open'
trade.update(limit_buy_order)
assert trade.open_order_id is None
@@ -212,11 +212,11 @@ def test_update_invalid_order(limit_buy_order):
trade.update(limit_buy_order)
def test_calc_open_trade_price(limit_buy_order):
def test_calc_open_trade_price(limit_buy_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
trade.open_order_id = 'open_trade'
@@ -229,11 +229,11 @@ def test_calc_open_trade_price(limit_buy_order):
assert trade.calc_open_trade_price(fee=0.003) == 0.001003000
def test_calc_close_trade_price(limit_buy_order, limit_sell_order):
def test_calc_close_trade_price(limit_buy_order, limit_sell_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
trade.open_order_id = 'close_trade'
@@ -250,11 +250,11 @@ def test_calc_close_trade_price(limit_buy_order, limit_sell_order):
assert trade.calc_close_trade_price(fee=0.005) == 0.0010619972
def test_calc_profit(limit_buy_order, limit_sell_order):
def test_calc_profit(limit_buy_order, limit_sell_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
trade.open_order_id = 'profit_percent'
@@ -280,11 +280,11 @@ def test_calc_profit(limit_buy_order, limit_sell_order):
assert trade.calc_profit(fee=0.003) == 0.00006163
def test_calc_profit_percent(limit_buy_order, limit_sell_order):
def test_calc_profit_percent(limit_buy_order, limit_sell_order, fee):
trade = Trade(
pair='ETH/BTC',
stake_amount=0.001,
fee=0.0025,
fee=fee.return_value,
exchange='bittrex',
)
trade.open_order_id = 'profit_percent'
@@ -304,7 +304,7 @@ def test_calc_profit_percent(limit_buy_order, limit_sell_order):
assert trade.calc_profit_percent(fee=0.003) == 0.0614782
def test_clean_dry_run_db(default_conf):
def test_clean_dry_run_db(default_conf, fee):
init(default_conf, create_engine('sqlite://'))
# Simulate dry_run entries
@@ -312,7 +312,7 @@ def test_clean_dry_run_db(default_conf):
pair='ETH/BTC',
stake_amount=0.001,
amount=123.0,
fee=0.0025,
fee=fee.return_value,
open_rate=0.123,
exchange='bittrex',
open_order_id='dry_run_buy_12345'
@@ -323,7 +323,7 @@ def test_clean_dry_run_db(default_conf):
pair='ETC/BTC',
stake_amount=0.001,
amount=123.0,
fee=0.0025,
fee=fee.return_value,
open_rate=0.123,
exchange='bittrex',
open_order_id='dry_run_sell_12345'
@@ -335,7 +335,7 @@ def test_clean_dry_run_db(default_conf):
pair='ETC/BTC',
stake_amount=0.001,
amount=123.0,
fee=0.0025,
fee=fee.return_value,
open_rate=0.123,
exchange='bittrex',
open_order_id='prod_buy_12345'