Merge branch 'develop' into align_userdata

This commit is contained in:
Matthias
2019-08-18 15:00:12 +02:00
63 changed files with 1517 additions and 941 deletions

View File

@@ -0,0 +1,133 @@
{
/* Single-line C-style comment */
"max_open_trades": 3,
/*
* Multi-line C-style comment
*/
"stake_currency": "BTC",
"stake_amount": 0.05,
"fiat_display_currency": "USD", // C++-style comment
"amount_reserve_percent" : 0.05, // And more, tabs before this comment
"dry_run": false,
"ticker_interval": "5m",
"trailing_stop": false,
"trailing_stop_positive": 0.005,
"trailing_stop_positive_offset": 0.0051,
"trailing_only_offset_is_reached": false,
"minimal_roi": {
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
},
"stoploss": -0.10,
"unfilledtimeout": {
"buy": 10,
"sell": 30, // Trailing comma should also be accepted now
},
"bid_strategy": {
"use_order_book": false,
"ask_last_balance": 0.0,
"order_book_top": 1,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"ask_strategy":{
"use_order_book": false,
"order_book_min": 1,
"order_book_max": 9
},
"order_types": {
"buy": "limit",
"sell": "limit",
"stoploss": "market",
"stoploss_on_exchange": false,
"stoploss_on_exchange_interval": 60
},
"order_time_in_force": {
"buy": "gtc",
"sell": "gtc"
},
"pairlist": {
"method": "VolumePairList",
"config": {
"number_assets": 20,
"sort_key": "quoteVolume",
"precision_filter": false
}
},
"exchange": {
"name": "bittrex",
"sandbox": false,
"key": "your_exchange_key",
"secret": "your_exchange_secret",
"password": "",
"ccxt_config": {"enableRateLimit": true},
"ccxt_async_config": {
"enableRateLimit": false,
"rateLimit": 500,
"aiohttp_trust_env": false
},
"pair_whitelist": [
"ETH/BTC",
"LTC/BTC",
"ETC/BTC",
"DASH/BTC",
"ZEC/BTC",
"XLM/BTC",
"NXT/BTC",
"POWR/BTC",
"ADA/BTC",
"XMR/BTC"
],
"pair_blacklist": [
"DOGE/BTC"
],
"outdated_offset": 5,
"markets_refresh_interval": 60
},
"edge": {
"enabled": false,
"process_throttle_secs": 3600,
"calculate_since_number_of_days": 7,
"capital_available_percentage": 0.5,
"allowed_risk": 0.01,
"stoploss_range_min": -0.01,
"stoploss_range_max": -0.1,
"stoploss_range_step": -0.01,
"minimum_winrate": 0.60,
"minimum_expectancy": 0.20,
"min_trade_number": 10,
"max_trade_duration_minute": 1440,
"remove_pumps": false
},
"experimental": {
"use_sell_signal": false,
"sell_profit_only": false,
"ignore_roi_if_buy_signal": false
},
"telegram": {
// We can now comment out some settings
// "enabled": true,
"enabled": false,
"token": "your_telegram_token",
"chat_id": "your_telegram_chat_id"
},
"api_server": {
"enabled": false,
"listen_ip_address": "127.0.0.1",
"listen_port": 8080,
"username": "freqtrader",
"password": "SuperSecurePassword"
},
"db_url": "sqlite:///tradesv3.sqlite",
"initial_state": "running",
"forcebuy_enable": false,
"internals": {
"process_throttle_secs": 5
},
"strategy": "DefaultStrategy",
"strategy_path": "user_data/strategies/"
}

View File

@@ -10,6 +10,7 @@ from unittest.mock import MagicMock, PropertyMock
import arrow
import pytest
import numpy as np
from telegram import Chat, Message, Update
from freqtrade import constants, persistence
@@ -25,17 +26,21 @@ from freqtrade.worker import Worker
logging.getLogger('').setLevel(logging.INFO)
# Do not mask numpy errors as warnings that no one read, raise the exсeption
np.seterr(all='raise')
def log_has(line, logs):
# caplog mocker returns log as a tuple: ('freqtrade.something', 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),
filter(lambda x: x[2] == line, logs.record_tuples),
False)
def log_has_re(line, logs):
return reduce(lambda a, b: a or b,
filter(lambda x: re.match(line, x[2]), logs),
filter(lambda x: re.match(line, x[2]), logs.record_tuples),
False)

View File

@@ -4,7 +4,7 @@ import pytest
from arrow import Arrow
from pandas import DataFrame, to_datetime
from freqtrade.configuration import Arguments, TimeRange
from freqtrade.configuration import TimeRange
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS,
combine_tickers_with_mean,
create_cum_profit,
@@ -121,7 +121,7 @@ def test_combine_tickers_with_mean():
def test_create_cum_profit():
filename = make_testdata_path(None) / "backtest-result_test.json"
bt_data = load_backtest_data(filename)
timerange = Arguments.parse_timerange("20180110-20180112")
timerange = TimeRange.parse_timerange("20180110-20180112")
df = load_pair_history(pair="POWR/BTC", ticker_interval='5m',
datadir=None, timerange=timerange)

View File

@@ -18,7 +18,7 @@ def test_parse_ticker_dataframe(ticker_history_list, caplog):
dataframe = parse_ticker_dataframe(ticker_history_list, '5m',
pair="UNITTEST/BTC", fill_missing=True)
assert dataframe.columns.tolist() == columns
assert log_has('Parsing tickerlist to dataframe', caplog.record_tuples)
assert log_has('Parsing tickerlist to dataframe', caplog)
def test_ohlcv_fill_up_missing_data(caplog):
@@ -34,8 +34,7 @@ def test_ohlcv_fill_up_missing_data(caplog):
assert (data.columns == data2.columns).all()
assert log_has(f"Missing data fillup for UNITTEST/BTC: before: "
f"{len(data)} - after: {len(data2)}",
caplog.record_tuples)
f"{len(data)} - after: {len(data2)}", caplog)
# Test fillup actually fixes invalid backtest data
min_date, max_date = get_timeframe({'UNITTEST/BTC': data})
@@ -97,8 +96,7 @@ def test_ohlcv_fill_up_missing_data2(caplog):
assert (data.columns == data2.columns).all()
assert log_has(f"Missing data fillup for UNITTEST/BTC: before: "
f"{len(data)} - after: {len(data2)}",
caplog.record_tuples)
f"{len(data)} - after: {len(data2)}", caplog)
def test_ohlcv_drop_incomplete(caplog):
@@ -140,11 +138,11 @@ def test_ohlcv_drop_incomplete(caplog):
data = parse_ticker_dataframe(ticks, ticker_interval, pair="UNITTEST/BTC",
fill_missing=False, drop_incomplete=False)
assert len(data) == 4
assert not log_has("Dropping last candle", caplog.record_tuples)
assert not log_has("Dropping last candle", caplog)
# Drop last candle
data = parse_ticker_dataframe(ticks, ticker_interval, pair="UNITTEST/BTC",
fill_missing=False, drop_incomplete=True)
assert len(data) == 3
assert log_has("Dropping last candle", caplog.record_tuples)
assert log_has("Dropping last candle", caplog)

View File

@@ -13,6 +13,7 @@ def test_ohlcv(mocker, default_conf, ticker_history):
exchange = get_patched_exchange(mocker, default_conf)
exchange._klines[("XRP/BTC", ticker_interval)] = ticker_history
exchange._klines[("UNITTEST/BTC", ticker_interval)] = ticker_history
dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.DRY_RUN
assert ticker_history.equals(dp.ohlcv("UNITTEST/BTC", ticker_interval))
@@ -37,11 +38,9 @@ def test_ohlcv(mocker, default_conf, ticker_history):
def test_historic_ohlcv(mocker, default_conf, ticker_history):
historymock = MagicMock(return_value=ticker_history)
mocker.patch("freqtrade.data.dataprovider.load_pair_history", historymock)
# exchange = get_patched_exchange(mocker, default_conf)
dp = DataProvider(default_conf, None)
data = dp.historic_ohlcv("UNITTEST/BTC", "5m")
assert isinstance(data, DataFrame)
@@ -51,14 +50,47 @@ def test_historic_ohlcv(mocker, default_conf, ticker_history):
assert historymock.call_args_list[0][1]["ticker_interval"] == "5m"
def test_get_pair_dataframe(mocker, default_conf, ticker_history):
default_conf["runmode"] = RunMode.DRY_RUN
ticker_interval = default_conf["ticker_interval"]
exchange = get_patched_exchange(mocker, default_conf)
exchange._klines[("XRP/BTC", ticker_interval)] = ticker_history
exchange._klines[("UNITTEST/BTC", ticker_interval)] = ticker_history
dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.DRY_RUN
assert ticker_history.equals(dp.get_pair_dataframe("UNITTEST/BTC", ticker_interval))
assert isinstance(dp.get_pair_dataframe("UNITTEST/BTC", ticker_interval), DataFrame)
assert dp.get_pair_dataframe("UNITTEST/BTC", ticker_interval) is not ticker_history
assert not dp.get_pair_dataframe("UNITTEST/BTC", ticker_interval).empty
assert dp.get_pair_dataframe("NONESENSE/AAA", ticker_interval).empty
# Test with and without parameter
assert dp.get_pair_dataframe("UNITTEST/BTC",
ticker_interval).equals(dp.get_pair_dataframe("UNITTEST/BTC"))
default_conf["runmode"] = RunMode.LIVE
dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.LIVE
assert isinstance(dp.get_pair_dataframe("UNITTEST/BTC", ticker_interval), DataFrame)
assert dp.get_pair_dataframe("NONESENSE/AAA", ticker_interval).empty
historymock = MagicMock(return_value=ticker_history)
mocker.patch("freqtrade.data.dataprovider.load_pair_history", historymock)
default_conf["runmode"] = RunMode.BACKTEST
dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.BACKTEST
assert isinstance(dp.get_pair_dataframe("UNITTEST/BTC", ticker_interval), DataFrame)
# assert dp.get_pair_dataframe("NONESENSE/AAA", ticker_interval).empty
def test_available_pairs(mocker, default_conf, ticker_history):
exchange = get_patched_exchange(mocker, default_conf)
ticker_interval = default_conf["ticker_interval"]
exchange._klines[("XRP/BTC", ticker_interval)] = ticker_history
exchange._klines[("UNITTEST/BTC", ticker_interval)] = ticker_history
dp = DataProvider(default_conf, exchange)
dp = DataProvider(default_conf, exchange)
assert len(dp.available_pairs) == 2
assert dp.available_pairs == [
("XRP/BTC", ticker_interval),

View File

@@ -64,8 +64,7 @@ def test_load_data_30min_ticker(mocker, caplog, default_conf) -> None:
assert isinstance(ld, DataFrame)
assert not log_has(
'Download history data for pair: "UNITTEST/BTC", interval: 30m '
'and store in None.',
caplog.record_tuples
'and store in None.', caplog
)
@@ -76,21 +75,19 @@ def test_load_data_7min_ticker(mocker, caplog, default_conf) -> None:
assert log_has(
'No history data for pair: "UNITTEST/BTC", interval: 7m. '
'Use --refresh-pairs-cached option or download_backtest_data.py '
'script to download the data',
caplog.record_tuples
'script to download the data', caplog
)
def test_load_data_1min_ticker(ticker_history, mocker, caplog) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ticker_history)
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-1m.json')
_backup_file(file, copy_file=True)
history.load_data(datadir=None, ticker_interval='1m', pairs=['UNITTEST/BTC'])
assert os.path.isfile(file) is True
assert not log_has(
'Download history data for pair: "UNITTEST/BTC", interval: 1m '
'and store in None.',
caplog.record_tuples
'and store in None.', caplog
)
_clean_test_file(file)
@@ -99,7 +96,7 @@ def test_load_data_with_new_pair_1min(ticker_history_list, mocker, caplog, defau
"""
Test load_pair_history() with 1 min ticker
"""
mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history_list)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ticker_history_list)
exchange = get_patched_exchange(mocker, default_conf)
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
@@ -113,8 +110,7 @@ def test_load_data_with_new_pair_1min(ticker_history_list, mocker, caplog, defau
assert log_has(
'No history data for pair: "MEME/BTC", interval: 1m. '
'Use --refresh-pairs-cached option or download_backtest_data.py '
'script to download the data',
caplog.record_tuples
'script to download the data', caplog
)
# download a new pair if refresh_pairs is set
@@ -126,8 +122,7 @@ def test_load_data_with_new_pair_1min(ticker_history_list, mocker, caplog, defau
assert os.path.isfile(file) is True
assert log_has(
'Download history data for pair: "MEME/BTC", interval: 1m '
'and store in None.',
caplog.record_tuples
'and store in None.', caplog
)
with pytest.raises(OperationalException, match=r'Exchange needs to be initialized when.*'):
history.load_pair_history(datadir=None,
@@ -149,7 +144,7 @@ def test_load_data_live(default_conf, mocker, caplog) -> None:
exchange=exchange)
assert refresh_mock.call_count == 1
assert len(refresh_mock.call_args_list[0][0][0]) == 2
assert log_has('Live: Downloading data for all defined pairs ...', caplog.record_tuples)
assert log_has('Live: Downloading data for all defined pairs ...', caplog)
def test_load_data_live_noexchange(default_conf, mocker, caplog) -> None:
@@ -271,7 +266,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
def test_download_pair_history(ticker_history_list, mocker, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history_list)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ticker_history_list)
exchange = get_patched_exchange(mocker, default_conf)
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')
@@ -324,7 +319,7 @@ def test_download_pair_history2(mocker, default_conf) -> None:
[1509836580000, 0.00161, 0.00161, 0.00161, 0.00161, 82.390199]
]
json_dump_mock = mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=tick)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=tick)
exchange = get_patched_exchange(mocker, default_conf)
download_pair_history(None, exchange, pair="UNITTEST/BTC", ticker_interval='1m')
download_pair_history(None, exchange, pair="UNITTEST/BTC", ticker_interval='3m')
@@ -332,7 +327,7 @@ def test_download_pair_history2(mocker, default_conf) -> None:
def test_download_backtesting_data_exception(ticker_history, mocker, caplog, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_history',
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv',
side_effect=Exception('File Error'))
exchange = get_patched_exchange(mocker, default_conf)
@@ -350,8 +345,7 @@ def test_download_backtesting_data_exception(ticker_history, mocker, caplog, def
_clean_test_file(file1_5)
assert log_has(
'Failed to download history data for pair: "MEME/BTC", interval: 1m. '
'Error: File Error',
caplog.record_tuples
'Error: File Error', caplog
)
@@ -380,7 +374,7 @@ def test_load_partial_missing(caplog) -> None:
start_real = tickerdata['UNITTEST/BTC'].iloc[0, 0]
assert log_has(f'Missing data at start for pair '
f'UNITTEST/BTC, data starts at {start_real.strftime("%Y-%m-%d %H:%M:%S")}',
caplog.record_tuples)
caplog)
# Make sure we start fresh - test missing data at end
caplog.clear()
start = arrow.get('2018-01-10T00:00:00')
@@ -396,7 +390,7 @@ def test_load_partial_missing(caplog) -> None:
end_real = arrow.get(tickerdata['UNITTEST/BTC'].iloc[-1, 0]).shift(minutes=5)
assert log_has(f'Missing data at end for pair '
f'UNITTEST/BTC, data ends at {end_real.strftime("%Y-%m-%d %H:%M:%S")}',
caplog.record_tuples)
caplog)
def test_init(default_conf, mocker) -> None:
@@ -560,7 +554,7 @@ def test_validate_backtest_data_warn(default_conf, mocker, caplog) -> None:
assert len(caplog.record_tuples) == 1
assert log_has(
"UNITTEST/BTC has missing frames: expected 14396, got 13680, that's 716 missing values",
caplog.record_tuples)
caplog)
def test_validate_backtest_data(default_conf, mocker, caplog) -> None:

View File

@@ -311,7 +311,7 @@ def test_edge_process_no_data(mocker, edge_conf, caplog):
assert not edge.calculate()
assert len(edge._cached_pairs) == 0
assert log_has("No data found. Edge is stopped ...", caplog.record_tuples)
assert log_has("No data found. Edge is stopped ...", caplog)
assert edge._last_updated == 0
@@ -326,7 +326,7 @@ def test_edge_process_no_trades(mocker, edge_conf, caplog):
assert not edge.calculate()
assert len(edge._cached_pairs) == 0
assert log_has("No trades found.", caplog.record_tuples)
assert log_has("No trades found.", caplog)
def test_edge_init_error(mocker, edge_conf,):

View File

@@ -14,7 +14,11 @@ from pandas import DataFrame
from freqtrade import (DependencyException, InvalidOrderException,
OperationalException, TemporaryError)
from freqtrade.exchange import Binance, Exchange, Kraken
from freqtrade.exchange.exchange import API_RETRY_COUNT
from freqtrade.exchange.exchange import (API_RETRY_COUNT, timeframe_to_minutes,
timeframe_to_msecs,
timeframe_to_next_date,
timeframe_to_prev_date,
timeframe_to_seconds)
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
from freqtrade.tests.conftest import get_patched_exchange, log_has, log_has_re
@@ -62,7 +66,7 @@ async def async_ccxt_exception(mocker, default_conf, api_mock, fun, mock_ccxt_fu
def test_init(default_conf, mocker, caplog):
caplog.set_level(logging.INFO)
get_patched_exchange(mocker, default_conf)
assert log_has('Instance is running with dry_run enabled', caplog.record_tuples)
assert log_has('Instance is running with dry_run enabled', caplog)
def test_init_ccxt_kwargs(default_conf, mocker, caplog):
@@ -71,8 +75,7 @@ def test_init_ccxt_kwargs(default_conf, mocker, caplog):
conf = copy.deepcopy(default_conf)
conf['exchange']['ccxt_async_config'] = {'aiohttp_trust_env': True}
ex = Exchange(conf)
assert log_has("Applying additional ccxt config: {'aiohttp_trust_env': True}",
caplog.record_tuples)
assert log_has("Applying additional ccxt config: {'aiohttp_trust_env': True}", caplog)
assert ex._api_async.aiohttp_trust_env
assert not ex._api.aiohttp_trust_env
@@ -81,20 +84,18 @@ def test_init_ccxt_kwargs(default_conf, mocker, caplog):
conf = copy.deepcopy(default_conf)
conf['exchange']['ccxt_config'] = {'TestKWARG': 11}
ex = Exchange(conf)
assert not log_has("Applying additional ccxt config: {'aiohttp_trust_env': True}",
caplog.record_tuples)
assert not log_has("Applying additional ccxt config: {'aiohttp_trust_env': True}", caplog)
assert not ex._api_async.aiohttp_trust_env
assert hasattr(ex._api, 'TestKWARG')
assert ex._api.TestKWARG == 11
assert not hasattr(ex._api_async, 'TestKWARG')
assert log_has("Applying additional ccxt config: {'TestKWARG': 11}",
caplog.record_tuples)
assert log_has("Applying additional ccxt config: {'TestKWARG': 11}", caplog)
def test_destroy(default_conf, mocker, caplog):
caplog.set_level(logging.DEBUG)
get_patched_exchange(mocker, default_conf)
assert log_has('Exchange object destroyed, closing async loop', caplog.record_tuples)
assert log_has('Exchange object destroyed, closing async loop', caplog)
def test_init_exception(default_conf, mocker):
@@ -120,8 +121,7 @@ def test_exchange_resolver(default_conf, mocker, caplog):
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
exchange = ExchangeResolver('Bittrex', default_conf).exchange
assert isinstance(exchange, Exchange)
assert log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples)
assert log_has_re(r"No .* specific subclass found. Using the generic class instead.", caplog)
caplog.clear()
exchange = ExchangeResolver('kraken', default_conf).exchange
@@ -129,7 +129,7 @@ def test_exchange_resolver(default_conf, mocker, caplog):
assert isinstance(exchange, Kraken)
assert not isinstance(exchange, Binance)
assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples)
caplog)
exchange = ExchangeResolver('binance', default_conf).exchange
assert isinstance(exchange, Exchange)
@@ -137,7 +137,7 @@ def test_exchange_resolver(default_conf, mocker, caplog):
assert not isinstance(exchange, Kraken)
assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples)
caplog)
def test_validate_order_time_in_force(default_conf, mocker, caplog):
@@ -249,8 +249,7 @@ def test__load_async_markets(default_conf, mocker, caplog):
exchange._api_async.load_markets = Mock(side_effect=ccxt.BaseError("deadbeef"))
exchange._load_async_markets()
assert log_has('Could not load async markets. Reason: deadbeef',
caplog.record_tuples)
assert log_has('Could not load async markets. Reason: deadbeef', caplog)
def test__load_markets(default_conf, mocker, caplog):
@@ -262,7 +261,7 @@ def test__load_markets(default_conf, mocker, caplog):
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())
Exchange(default_conf)
assert log_has('Unable to initialize markets. Reason: SomeError', caplog.record_tuples)
assert log_has('Unable to initialize markets. Reason: SomeError', caplog)
expected_return = {'ETH/BTC': 'available'}
api_mock = MagicMock()
@@ -298,7 +297,7 @@ def test__reload_markets(default_conf, mocker, caplog):
exchange._last_markets_refresh = arrow.utcnow().timestamp - 15 * 60
exchange._reload_markets()
assert exchange.markets == updated_markets
assert log_has('Performing scheduled market reload..', caplog.record_tuples)
assert log_has('Performing scheduled market reload..', caplog)
def test__reload_markets_exception(default_conf, mocker, caplog):
@@ -312,7 +311,7 @@ def test__reload_markets_exception(default_conf, mocker, caplog):
# less than 10 minutes have passed, no reload
exchange._reload_markets()
assert exchange._last_markets_refresh == 0
assert log_has_re(r"Could not reload markets.*", caplog.record_tuples)
assert log_has_re(r"Could not reload markets.*", caplog)
def test_validate_pairs(default_conf, mocker): # test exchange.validate_pairs directly
@@ -357,8 +356,7 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value={}))
Exchange(default_conf)
assert log_has('Unable to validate pairs (assuming they are correct).',
caplog.record_tuples)
assert log_has('Unable to validate pairs (assuming they are correct).', caplog)
def test_validate_pairs_restricted(default_conf, mocker, caplog):
@@ -374,8 +372,7 @@ def test_validate_pairs_restricted(default_conf, mocker, caplog):
Exchange(default_conf)
assert log_has(f"Pair XRP/BTC is restricted for some users on this exchange."
f"Please check if you are impacted by this restriction "
f"on the exchange and eventually remove XRP/BTC from your whitelist.",
caplog.record_tuples)
f"on the exchange and eventually remove XRP/BTC from your whitelist.", caplog)
def test_validate_timeframes(default_conf, mocker):
@@ -1003,7 +1000,7 @@ def test_get_ticker(default_conf, mocker, exchange_name):
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_get_history(default_conf, mocker, caplog, exchange_name):
def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name):
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
tick = [
[
@@ -1024,7 +1021,7 @@ def test_get_history(default_conf, mocker, caplog, exchange_name):
# one_call calculation * 1.8 should do 2 calls
since = 5 * 60 * 500 * 1.8
print(f"since = {since}")
ret = exchange.get_history(pair, "5m", int((arrow.utcnow().timestamp - since) * 1000))
ret = exchange.get_historic_ohlcv(pair, "5m", int((arrow.utcnow().timestamp - since) * 1000))
assert exchange._async_get_candle_history.call_count == 2
# Returns twice the above tick
@@ -1060,7 +1057,7 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
assert not exchange._klines
exchange.refresh_latest_ohlcv(pairs)
assert log_has(f'Refreshing ohlcv data for {len(pairs)} pairs', caplog.record_tuples)
assert log_has(f'Refreshing ohlcv data for {len(pairs)} pairs', caplog)
assert exchange._klines
assert exchange._api_async.fetch_ohlcv.call_count == 2
for pair in pairs:
@@ -1079,7 +1076,7 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
assert exchange._api_async.fetch_ohlcv.call_count == 2
assert log_has(f"Using cached ohlcv data for pair {pairs[0][0]}, interval {pairs[0][1]} ...",
caplog.record_tuples)
caplog)
@pytest.mark.asyncio
@@ -1109,7 +1106,7 @@ async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_
assert res[1] == "5m"
assert res[2] == tick
assert exchange._api_async.fetch_ohlcv.call_count == 1
assert not log_has(f"Using cached ohlcv data for {pair} ...", caplog.record_tuples)
assert not log_has(f"Using cached ohlcv data for {pair} ...", caplog)
# exchange = Exchange(default_conf)
await async_ccxt_exception(mocker, default_conf, MagicMock(),
@@ -1168,8 +1165,8 @@ def test_refresh_latest_ohlcv_inv_result(default_conf, mocker, caplog):
# Test that each is in list at least once as order is not guaranteed
assert type(res[0]) is tuple or type(res[1]) is tuple
assert type(res[0]) is TypeError or type(res[1]) is TypeError
assert log_has("Error loading ETH/BTC. Result was [[]].", caplog.record_tuples)
assert log_has("Async code raised an exception: TypeError", caplog.record_tuples)
assert log_has("Error loading ETH/BTC. Result was [[]].", caplog)
assert log_has("Async code raised an exception: TypeError", caplog)
@pytest.mark.parametrize("exchange_name", EXCHANGES)
@@ -1547,3 +1544,74 @@ def test_get_valid_pair_combination(default_conf, mocker, markets):
assert ex.get_valid_pair_combination("BTC", "ETH") == "ETH/BTC"
with pytest.raises(DependencyException, match=r"Could not combine.* to get a valid pair."):
ex.get_valid_pair_combination("NOPAIR", "ETH")
def test_timeframe_to_minutes():
assert timeframe_to_minutes("5m") == 5
assert timeframe_to_minutes("10m") == 10
assert timeframe_to_minutes("1h") == 60
assert timeframe_to_minutes("1d") == 1440
def test_timeframe_to_seconds():
assert timeframe_to_seconds("5m") == 300
assert timeframe_to_seconds("10m") == 600
assert timeframe_to_seconds("1h") == 3600
assert timeframe_to_seconds("1d") == 86400
def test_timeframe_to_msecs():
assert timeframe_to_msecs("5m") == 300000
assert timeframe_to_msecs("10m") == 600000
assert timeframe_to_msecs("1h") == 3600000
assert timeframe_to_msecs("1d") == 86400000
def test_timeframe_to_prev_date():
# 2019-08-12 13:22:08
date = datetime.fromtimestamp(1565616128, tz=timezone.utc)
tf_list = [
# 5m -> 2019-08-12 13:20:00
("5m", datetime(2019, 8, 12, 13, 20, 0, tzinfo=timezone.utc)),
# 10m -> 2019-08-12 13:20:00
("10m", datetime(2019, 8, 12, 13, 20, 0, tzinfo=timezone.utc)),
# 1h -> 2019-08-12 13:00:00
("1h", datetime(2019, 8, 12, 13, 00, 0, tzinfo=timezone.utc)),
# 2h -> 2019-08-12 12:00:00
("2h", datetime(2019, 8, 12, 12, 00, 0, tzinfo=timezone.utc)),
# 4h -> 2019-08-12 12:00:00
("4h", datetime(2019, 8, 12, 12, 00, 0, tzinfo=timezone.utc)),
# 1d -> 2019-08-12 00:00:00
("1d", datetime(2019, 8, 12, 00, 00, 0, tzinfo=timezone.utc)),
]
for interval, result in tf_list:
assert timeframe_to_prev_date(interval, date) == result
date = datetime.now(tz=timezone.utc)
assert timeframe_to_prev_date("5m", date) < date
def test_timeframe_to_next_date():
# 2019-08-12 13:22:08
date = datetime.fromtimestamp(1565616128, tz=timezone.utc)
tf_list = [
# 5m -> 2019-08-12 13:25:00
("5m", datetime(2019, 8, 12, 13, 25, 0, tzinfo=timezone.utc)),
# 10m -> 2019-08-12 13:30:00
("10m", datetime(2019, 8, 12, 13, 30, 0, tzinfo=timezone.utc)),
# 1h -> 2019-08-12 14:00:00
("1h", datetime(2019, 8, 12, 14, 00, 0, tzinfo=timezone.utc)),
# 2h -> 2019-08-12 14:00:00
("2h", datetime(2019, 8, 12, 14, 00, 0, tzinfo=timezone.utc)),
# 4h -> 2019-08-12 14:00:00
("4h", datetime(2019, 8, 12, 16, 00, 0, tzinfo=timezone.utc)),
# 1d -> 2019-08-13 00:00:00
("1d", datetime(2019, 8, 13, 0, 0, 0, tzinfo=timezone.utc)),
]
for interval, result in tf_list:
assert timeframe_to_next_date(interval, date) == result
date = datetime.now(tz=timezone.utc)
assert timeframe_to_next_date("5m", date) > date

View File

@@ -181,21 +181,18 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
assert 'exchange' in config
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog.record_tuples)
assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog)
assert 'live' not in config
assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert not log_has('Parameter -l/--live detected ...', caplog)
assert 'position_stacking' not in config
assert not log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert not log_has('Parameter --enable-position-stacking detected ...', caplog)
assert 'refresh_pairs' not in config
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' not in config
assert 'export' not in config
@@ -235,43 +232,31 @@ def test_setup_bt_configuration_with_arguments(mocker, default_conf, caplog) ->
assert 'datadir' in config
assert config['runmode'] == RunMode.BACKTEST
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...',
caplog.record_tuples)
caplog)
assert 'live' in config
assert log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert log_has('Parameter -l/--live detected ...', caplog)
assert 'position_stacking' in config
assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert log_has('Parameter --enable-position-stacking detected ...', caplog)
assert 'use_max_market_positions' in config
assert log_has('Parameter --disable-max-market-positions detected ...', caplog.record_tuples)
assert log_has('max_open_trades set to unlimited ...', caplog.record_tuples)
assert log_has('Parameter --disable-max-market-positions detected ...', caplog)
assert log_has('max_open_trades set to unlimited ...', caplog)
assert 'refresh_pairs' in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' in config
assert log_has(
'Parameter --timerange detected: {} ...'.format(config['timerange']),
caplog.record_tuples
)
assert log_has('Parameter --timerange detected: {} ...'.format(config['timerange']), caplog)
assert 'export' in config
assert log_has(
'Parameter --export detected: {} ...'.format(config['export']),
caplog.record_tuples
)
assert log_has('Parameter --export detected: {} ...'.format(config['export']), caplog)
assert 'exportfilename' in config
assert log_has(
'Storing backtest results to {} ...'.format(config['exportfilename']),
caplog.record_tuples
)
assert log_has('Storing backtest results to {} ...'.format(config['exportfilename']), caplog)
def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog) -> None:
@@ -303,10 +288,7 @@ def test_start(mocker, fee, default_conf, caplog) -> None:
]
args = get_args(args)
start_backtesting(args)
assert log_has(
'Starting freqtrade in Backtesting mode',
caplog.record_tuples
)
assert log_has('Starting freqtrade in Backtesting mode', caplog)
assert start_mock.call_count == 1
@@ -360,7 +342,7 @@ def test_backtesting_init_no_ticker_interval(mocker, default_conf, caplog) -> No
with pytest.raises(OperationalException):
Backtesting(default_conf)
log_has("Ticker-interval needs to be set in either configuration "
"or as cli argument `--ticker-interval 5m`", caplog.record_tuples)
"or as cli argument `--ticker-interval 5m`", caplog)
def test_tickerdata_to_dataframe_bt(default_conf, mocker) -> None:
@@ -511,7 +493,7 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
'up to 2017-11-14T22:59:00+00:00 (0 days)..'
]
for line in exists:
assert log_has(line, caplog.record_tuples)
assert log_has(line, caplog)
def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
@@ -539,7 +521,7 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
backtesting.start()
# check the logs, that will contain the backtest result
assert log_has('No data found. Terminating.', caplog.record_tuples)
assert log_has('No data found. Terminating.', caplog)
def test_backtest(default_conf, fee, mocker) -> None:
@@ -876,7 +858,7 @@ def test_backtest_start_live(default_conf, mocker, caplog):
]
for line in exists:
assert log_has(line, caplog.record_tuples)
assert log_has(line, caplog)
@pytest.mark.filterwarnings("ignore:DEPRECATED")
@@ -936,4 +918,4 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog):
]
for line in exists:
assert log_has(line, caplog.record_tuples)
assert log_has(line, caplog)

View File

@@ -29,15 +29,12 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
assert 'exchange' in config
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog.record_tuples)
assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog)
assert 'refresh_pairs' not in config
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' not in config
assert 'stoploss_range' not in config
@@ -69,21 +66,15 @@ def test_setup_edge_configuration_with_arguments(mocker, edge_conf, caplog) -> N
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert config['runmode'] == RunMode.EDGE
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...',
caplog.record_tuples)
caplog)
assert 'refresh_pairs' in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' in config
assert log_has(
'Parameter --timerange detected: {} ...'.format(config['timerange']),
caplog.record_tuples
)
assert log_has('Parameter --timerange detected: {} ...'.format(config['timerange']), caplog)
def test_start(mocker, fee, edge_conf, caplog) -> None:
@@ -100,10 +91,7 @@ def test_start(mocker, fee, edge_conf, caplog) -> None:
]
args = get_args(args)
start_edge(args)
assert log_has(
'Starting freqtrade in Edge mode',
caplog.record_tuples
)
assert log_has('Starting freqtrade in Edge mode', caplog)
assert start_mock.call_count == 1

View File

@@ -82,21 +82,18 @@ def test_setup_hyperopt_configuration_without_arguments(mocker, default_conf, ca
assert 'exchange' in config
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog.record_tuples)
assert not log_has_re('Parameter -i/--ticker-interval detected .*', caplog)
assert 'live' not in config
assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert not log_has('Parameter -l/--live detected ...', caplog)
assert 'position_stacking' not in config
assert not log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert not log_has('Parameter --enable-position-stacking detected ...', caplog)
assert 'refresh_pairs' not in config
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' not in config
assert 'runmode' in config
@@ -133,41 +130,32 @@ def test_setup_hyperopt_configuration_with_arguments(mocker, default_conf, caplo
assert 'datadir' in config
assert config['runmode'] == RunMode.HYPEROPT
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...',
caplog.record_tuples)
caplog)
assert 'position_stacking' in config
assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert log_has('Parameter --enable-position-stacking detected ...', caplog)
assert 'use_max_market_positions' in config
assert log_has('Parameter --disable-max-market-positions detected ...', caplog.record_tuples)
assert log_has('max_open_trades set to unlimited ...', caplog.record_tuples)
assert log_has('Parameter --disable-max-market-positions detected ...', caplog)
assert log_has('max_open_trades set to unlimited ...', caplog)
assert 'refresh_pairs' in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' in config
assert log_has(
'Parameter --timerange detected: {} ...'.format(config['timerange']),
caplog.record_tuples
)
assert log_has('Parameter --timerange detected: {} ...'.format(config['timerange']), caplog)
assert 'epochs' in config
assert log_has('Parameter --epochs detected ... Will run Hyperopt with for 1000 epochs ...',
caplog.record_tuples)
caplog)
assert 'spaces' in config
assert log_has(
'Parameter -s/--spaces detected: {}'.format(config['spaces']),
caplog.record_tuples
)
assert log_has('Parameter -s/--spaces detected: {}'.format(config['spaces']), caplog)
assert 'print_all' in config
assert log_has('Parameter --print-all detected ...', caplog.record_tuples)
assert log_has('Parameter --print-all detected ...', caplog)
def test_hyperoptresolver(mocker, default_conf, caplog) -> None:
@@ -184,9 +172,9 @@ def test_hyperoptresolver(mocker, default_conf, caplog) -> None:
assert not hasattr(x, 'populate_buy_trend')
assert not hasattr(x, 'populate_sell_trend')
assert log_has("Custom Hyperopt does not provide populate_sell_trend. "
"Using populate_sell_trend from DefaultStrategy.", caplog.record_tuples)
"Using populate_sell_trend from DefaultStrategy.", caplog)
assert log_has("Custom Hyperopt does not provide populate_buy_trend. "
"Using populate_buy_trend from DefaultStrategy.", caplog.record_tuples)
"Using populate_buy_trend from DefaultStrategy.", caplog)
assert hasattr(x, "ticker_interval")
@@ -232,10 +220,7 @@ def test_start(mocker, default_conf, caplog) -> None:
import pprint
pprint.pprint(caplog.record_tuples)
assert log_has(
'Starting freqtrade in Hyperopt mode',
caplog.record_tuples
)
assert log_has('Starting freqtrade in Hyperopt mode', caplog)
assert start_mock.call_count == 1
@@ -260,7 +245,7 @@ def test_start_no_data(mocker, default_conf, caplog) -> None:
import pprint
pprint.pprint(caplog.record_tuples)
assert log_has('No data found. Terminating.', caplog.record_tuples)
assert log_has('No data found. Terminating.', caplog)
def test_start_failure(mocker, default_conf, caplog) -> None:
@@ -278,10 +263,7 @@ def test_start_failure(mocker, default_conf, caplog) -> None:
args = get_args(args)
with pytest.raises(DependencyException):
start_hyperopt(args)
assert log_has(
"Please don't use --strategy for hyperopt.",
caplog.record_tuples
)
assert log_has("Please don't use --strategy for hyperopt.", caplog)
def test_start_filelock(mocker, default_conf, caplog) -> None:
@@ -297,10 +279,7 @@ def test_start_filelock(mocker, default_conf, caplog) -> None:
]
args = get_args(args)
start_hyperopt(args)
assert log_has(
"Another running instance of freqtrade Hyperopt detected.",
caplog.record_tuples
)
assert log_has("Another running instance of freqtrade Hyperopt detected.", caplog)
def test_loss_calculation_prefer_correct_trade_count(default_conf, hyperopt_results) -> None:
@@ -404,10 +383,7 @@ def test_save_trials_saves_trials(mocker, hyperopt, caplog) -> None:
hyperopt.save_trials()
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
assert log_has(
'Saving 1 evaluations to \'{}\''.format(trials_file),
caplog.record_tuples
)
assert log_has('Saving 1 evaluations to \'{}\''.format(trials_file), caplog)
mock_dump.assert_called_once()
@@ -416,10 +392,7 @@ def test_read_trials_returns_trials_file(mocker, hyperopt, caplog) -> None:
mock_load = mocker.patch('freqtrade.optimize.hyperopt.load', return_value=trials)
hyperopt_trial = hyperopt.read_trials()
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
assert log_has(
'Reading Trials from \'{}\''.format(trials_file),
caplog.record_tuples
)
assert log_has('Reading Trials from \'{}\''.format(trials_file), caplog)
assert hyperopt_trial == trials
mock_load.assert_called_once()
@@ -608,7 +581,8 @@ def test_generate_optimizer(mocker, default_conf) -> None:
'loss': 1.9840569076926293,
'results_explanation': ' 1 trades. Avg profit 2.31%. Total profit 0.00023300 BTC '
'( 2.31Σ%). Avg duration 100.0 mins.',
'params': optimizer_param
'params': optimizer_param,
'total_profit': 0.00023300
}
hyperopt = Hyperopt(default_conf)
@@ -629,7 +603,7 @@ def test_clean_hyperopt(mocker, default_conf, caplog):
h = Hyperopt(default_conf)
assert unlinkmock.call_count == 2
assert log_has(f"Removing `{h.tickerdata_pickle}`.", caplog.record_tuples)
assert log_has(f"Removing `{h.tickerdata_pickle}`.", caplog)
def test_continue_hyperopt(mocker, default_conf, caplog):
@@ -646,4 +620,78 @@ def test_continue_hyperopt(mocker, default_conf, caplog):
Hyperopt(default_conf)
assert unlinkmock.call_count == 0
assert log_has(f"Continuing on previous hyperopt results.", caplog.record_tuples)
assert log_has(f"Continuing on previous hyperopt results.", caplog)
def test_print_json_spaces_all(mocker, default_conf, caplog, capsys) -> None:
dumper = mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch(
'freqtrade.optimize.hyperopt.get_timeframe',
MagicMock(return_value=(datetime(2017, 12, 10), datetime(2017, 12, 13)))
)
parallel = mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel',
MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}}])
)
patch_exchange(mocker)
default_conf.update({'config': 'config.json.example',
'epochs': 1,
'timerange': None,
'spaces': 'all',
'hyperopt_jobs': 1,
'print_json': True,
})
hyperopt = Hyperopt(default_conf)
hyperopt.strategy.tickerdata_to_dataframe = MagicMock()
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
hyperopt.start()
parallel.assert_called_once()
out, err = capsys.readouterr()
assert '{"params":{"mfi-value":null,"fastd-value":null,"adx-value":null,"rsi-value":null,"mfi-enabled":null,"fastd-enabled":null,"adx-enabled":null,"rsi-enabled":null,"trigger":null,"sell-mfi-value":null,"sell-fastd-value":null,"sell-adx-value":null,"sell-rsi-value":null,"sell-mfi-enabled":null,"sell-fastd-enabled":null,"sell-adx-enabled":null,"sell-rsi-enabled":null,"sell-trigger":null},"minimal_roi":{},"stoploss":null}' in out # noqa: E501
assert dumper.called
# Should be called twice, once for tickerdata, once to save evaluations
assert dumper.call_count == 2
def test_print_json_spaces_roi_stoploss(mocker, default_conf, caplog, capsys) -> None:
dumper = mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch(
'freqtrade.optimize.hyperopt.get_timeframe',
MagicMock(return_value=(datetime(2017, 12, 10), datetime(2017, 12, 13)))
)
parallel = mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel',
MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}}])
)
patch_exchange(mocker)
default_conf.update({'config': 'config.json.example',
'epochs': 1,
'timerange': None,
'spaces': 'roi stoploss',
'hyperopt_jobs': 1,
'print_json': True,
})
hyperopt = Hyperopt(default_conf)
hyperopt.strategy.tickerdata_to_dataframe = MagicMock()
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
hyperopt.start()
parallel.assert_called_once()
out, err = capsys.readouterr()
assert '{"minimal_roi":{},"stoploss":null}' in out
assert dumper.called
# Should be called twice, once for tickerdata, once to save evaluations
assert dumper.call_count == 2

View File

@@ -91,7 +91,7 @@ def test_fiat_convert_unsupported_crypto(mocker, caplog):
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._cryptomap', return_value=[])
fiat_convert = CryptoToFiatConverter()
assert fiat_convert._find_price(crypto_symbol='CRYPTO_123', fiat_symbol='EUR') == 0.0
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog.record_tuples)
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog)
def test_fiat_convert_get_price(mocker):
@@ -190,7 +190,7 @@ def test_fiat_invalid_response(mocker, caplog):
length_cryptomap = len(fiat_convert._cryptomap)
assert length_cryptomap == 0
assert log_has('Could not load FIAT Cryptocurrency map for the following problem: TypeError',
caplog.record_tuples)
caplog)
def test_convert_amount(mocker):

View File

@@ -44,7 +44,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
with pytest.raises(RPCException, match=r'.*no active trade*'):
rpc._rpc_trade_status()
freqtradebot.create_trade()
freqtradebot.create_trades()
results = rpc._rpc_trade_status()
assert {
'trade_id': 1,
@@ -116,7 +116,7 @@ def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
with pytest.raises(RPCException, match=r'.*no active order*'):
rpc._rpc_status_table()
freqtradebot.create_trade()
freqtradebot.create_trades()
result = rpc._rpc_status_table()
assert 'instantly' in result['Since'].all()
assert 'ETH/BTC' in result['Pair'].all()
@@ -151,7 +151,7 @@ def test_rpc_daily_profit(default_conf, update, ticker, fee,
rpc = RPC(freqtradebot)
rpc._fiat_converter = CryptoToFiatConverter()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -208,7 +208,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
@@ -222,7 +222,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
trade.close_date = datetime.utcnow()
trade.is_open = False
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
@@ -292,7 +292,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
rpc = RPC(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
@@ -536,7 +536,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
msg = rpc._rpc_forcesell('all')
assert msg == {'result': 'Created sell orders for all open trades.'}
freqtradebot.create_trade()
freqtradebot.create_trades()
msg = rpc._rpc_forcesell('all')
assert msg == {'result': 'Created sell orders for all open trades.'}
@@ -570,7 +570,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
assert cancel_order_mock.call_count == 1
assert trade.amount == filled_amount
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.filter(Trade.id == '2').first()
amount = trade.amount
# make an limit-buy open trade, if there is no 'filled', don't sell it
@@ -589,7 +589,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
assert cancel_order_mock.call_count == 2
assert trade.amount == amount
freqtradebot.create_trade()
freqtradebot.create_trades()
# make an limit-sell open trade
mocker.patch(
'freqtrade.exchange.Exchange.get_order',
@@ -622,7 +622,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
rpc = RPC(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -660,7 +660,7 @@ def test_rpc_count(mocker, default_conf, ticker, fee, markets) -> None:
assert counts["current"] == 0
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
counts = rpc._rpc_count()
assert counts["current"] == 1

View File

@@ -148,8 +148,8 @@ def test_api_run(default_conf, mocker, caplog):
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
assert hasattr(apiserver, "srv")
assert log_has("Starting HTTP Server at 127.0.0.1:8080", caplog.record_tuples)
assert log_has("Starting Local Rest Server.", caplog.record_tuples)
assert log_has("Starting HTTP Server at 127.0.0.1:8080", caplog)
assert log_has("Starting Local Rest Server.", caplog)
# Test binding to public
caplog.clear()
@@ -165,22 +165,20 @@ def test_api_run(default_conf, mocker, caplog):
assert server_mock.call_args_list[0][0][0] == "0.0.0.0"
assert server_mock.call_args_list[0][0][1] == "8089"
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
assert log_has("Starting HTTP Server at 0.0.0.0:8089", caplog.record_tuples)
assert log_has("Starting Local Rest Server.", caplog.record_tuples)
assert log_has("Starting HTTP Server at 0.0.0.0:8089", caplog)
assert log_has("Starting Local Rest Server.", caplog)
assert log_has("SECURITY WARNING - Local Rest Server listening to external connections",
caplog.record_tuples)
caplog)
assert log_has("SECURITY WARNING - This is insecure please set to your loopback,"
"e.g 127.0.0.1 in config.json",
caplog.record_tuples)
"e.g 127.0.0.1 in config.json", caplog)
assert log_has("SECURITY WARNING - No password for local REST Server defined. "
"Please make sure that this is intentional!",
caplog.record_tuples)
"Please make sure that this is intentional!", caplog)
# Test crashing flask
caplog.clear()
mocker.patch('freqtrade.rpc.api_server.make_server', MagicMock(side_effect=Exception))
apiserver.run()
assert log_has("Api server failed to start.", caplog.record_tuples)
assert log_has("Api server failed to start.", caplog)
def test_api_cleanup(default_conf, mocker, caplog):
@@ -199,7 +197,7 @@ def test_api_cleanup(default_conf, mocker, caplog):
apiserver.cleanup()
assert stop_mock.shutdown.call_count == 1
assert log_has("Stopping API Server", caplog.record_tuples)
assert log_has("Stopping API Server", caplog)
def test_api_reloadconf(botclient):
@@ -277,7 +275,7 @@ def test_api_count(botclient, mocker, ticker, fee, markets):
assert rc.json["max"] == 1.0
# Create some test data
ftbot.create_trade()
ftbot.create_trades()
rc = client_get(client, f"{BASE_URI}/count")
assert_response(rc)
assert rc.json["current"] == 1.0
@@ -331,7 +329,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, limit_buy_order, li
assert len(rc.json) == 1
assert rc.json == {"error": "Error querying _profit: no closed trade"}
ftbot.create_trade()
ftbot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
@@ -420,7 +418,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
assert_response(rc, 502)
assert rc.json == {'error': 'Error querying _status: no active trade'}
ftbot.create_trade()
ftbot.create_trades()
rc = client_get(client, f"{BASE_URI}/status")
assert_response(rc)
assert len(rc.json) == 1
@@ -550,7 +548,7 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets):
assert_response(rc, 502)
assert rc.json == {"error": "Error querying _forcesell: invalid argument"}
ftbot.create_trade()
ftbot.create_trades()
rc = client_post(client, f"{BASE_URI}/forcesell",
data='{"tradeid": "1"}')

View File

@@ -19,7 +19,7 @@ def test_init_telegram_disabled(mocker, default_conf, caplog) -> None:
default_conf['telegram']['enabled'] = False
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
assert not log_has('Enabling rpc.telegram ...', caplog.record_tuples)
assert not log_has('Enabling rpc.telegram ...', caplog)
assert rpc_manager.registered_modules == []
@@ -28,7 +28,7 @@ def test_init_telegram_enabled(mocker, default_conf, caplog) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
assert log_has('Enabling rpc.telegram ...', caplog.record_tuples)
assert log_has('Enabling rpc.telegram ...', caplog)
len_modules = len(rpc_manager.registered_modules)
assert len_modules == 1
assert 'telegram' in [mod.name for mod in rpc_manager.registered_modules]
@@ -43,7 +43,7 @@ def test_cleanup_telegram_disabled(mocker, default_conf, caplog) -> None:
rpc_manager = RPCManager(freqtradebot)
rpc_manager.cleanup()
assert not log_has('Cleaning up rpc.telegram ...', caplog.record_tuples)
assert not log_has('Cleaning up rpc.telegram ...', caplog)
assert telegram_mock.call_count == 0
@@ -59,7 +59,7 @@ def test_cleanup_telegram_enabled(mocker, default_conf, caplog) -> None:
assert 'telegram' in [mod.name for mod in rpc_manager.registered_modules]
rpc_manager.cleanup()
assert log_has('Cleaning up rpc.telegram ...', caplog.record_tuples)
assert log_has('Cleaning up rpc.telegram ...', caplog)
assert 'telegram' not in [mod.name for mod in rpc_manager.registered_modules]
assert telegram_mock.call_count == 1
@@ -75,7 +75,7 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
'status': 'test'
})
assert log_has("Sending rpc message: {'type': status, 'status': 'test'}", caplog.record_tuples)
assert log_has("Sending rpc message: {'type': status, 'status': 'test'}", caplog)
assert telegram_mock.call_count == 0
@@ -90,7 +90,7 @@ def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None:
'status': 'test'
})
assert log_has("Sending rpc message: {'type': status, 'status': 'test'}", caplog.record_tuples)
assert log_has("Sending rpc message: {'type': status, 'status': 'test'}", caplog)
assert telegram_mock.call_count == 1
@@ -100,7 +100,7 @@ def test_init_webhook_disabled(mocker, default_conf, caplog) -> None:
default_conf['webhook'] = {'enabled': False}
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
assert not log_has('Enabling rpc.webhook ...', caplog.record_tuples)
assert not log_has('Enabling rpc.webhook ...', caplog)
assert rpc_manager.registered_modules == []
@@ -110,7 +110,7 @@ def test_init_webhook_enabled(mocker, default_conf, caplog) -> None:
default_conf['webhook'] = {'enabled': True, 'url': "https://DEADBEEF.com"}
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
assert log_has('Enabling rpc.webhook ...', caplog.record_tuples)
assert log_has('Enabling rpc.webhook ...', caplog)
assert len(rpc_manager.registered_modules) == 1
assert 'webhook' in [mod.name for mod in rpc_manager.registered_modules]
@@ -144,7 +144,7 @@ def test_init_apiserver_disabled(mocker, default_conf, caplog) -> None:
default_conf['telegram']['enabled'] = False
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
assert not log_has('Enabling rpc.api_server', caplog.record_tuples)
assert not log_has('Enabling rpc.api_server', caplog)
assert rpc_manager.registered_modules == []
assert run_mock.call_count == 0
@@ -160,7 +160,7 @@ def test_init_apiserver_enabled(mocker, default_conf, caplog) -> None:
"listen_port": "8080"}
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
assert log_has('Enabling rpc.api_server', caplog.record_tuples)
assert log_has('Enabling rpc.api_server', caplog)
assert len(rpc_manager.registered_modules) == 1
assert 'apiserver' in [mod.name for mod in rpc_manager.registered_modules]
assert run_mock.call_count == 1

View File

@@ -76,7 +76,7 @@ def test_init(default_conf, mocker, caplog) -> None:
"['performance'], ['daily'], ['count'], ['reload_conf'], " \
"['stopbuy'], ['whitelist'], ['blacklist'], ['edge'], ['help'], ['version']]"
assert log_has(message_str, caplog.record_tuples)
assert log_has(message_str, caplog)
def test_cleanup(default_conf, mocker) -> None:
@@ -102,18 +102,9 @@ def test_authorized_only(default_conf, mocker, caplog) -> None:
dummy = DummyCls(bot)
dummy.dummy_handler(bot=MagicMock(), update=update)
assert dummy.state['called'] is True
assert log_has(
'Executing handler: dummy_handler for chat_id: 0',
caplog.record_tuples
)
assert not log_has(
'Rejected unauthorized message from: 0',
caplog.record_tuples
)
assert not log_has(
'Exception occurred within Telegram module',
caplog.record_tuples
)
assert log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
assert not log_has('Rejected unauthorized message from: 0', caplog)
assert not log_has('Exception occurred within Telegram module', caplog)
def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
@@ -128,18 +119,9 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
dummy = DummyCls(bot)
dummy.dummy_handler(bot=MagicMock(), update=update)
assert dummy.state['called'] is False
assert not log_has(
'Executing handler: dummy_handler for chat_id: 3735928559',
caplog.record_tuples
)
assert log_has(
'Rejected unauthorized message from: 3735928559',
caplog.record_tuples
)
assert not log_has(
'Exception occurred within Telegram module',
caplog.record_tuples
)
assert not log_has('Executing handler: dummy_handler for chat_id: 3735928559', caplog)
assert log_has('Rejected unauthorized message from: 3735928559', caplog)
assert not log_has('Exception occurred within Telegram module', caplog)
def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
@@ -156,18 +138,9 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
dummy.dummy_exception(bot=MagicMock(), update=update)
assert dummy.state['called'] is False
assert not log_has(
'Executing handler: dummy_handler for chat_id: 0',
caplog.record_tuples
)
assert not log_has(
'Rejected unauthorized message from: 0',
caplog.record_tuples
)
assert log_has(
'Exception occurred within Telegram module',
caplog.record_tuples
)
assert not log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
assert not log_has('Rejected unauthorized message from: 0', caplog)
assert log_has('Exception occurred within Telegram module', caplog)
def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
@@ -219,7 +192,7 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
# Create some test data
for _ in range(3):
freqtradebot.create_trade()
freqtradebot.create_trades()
telegram._status(bot=MagicMock(), update=update)
assert msg_mock.call_count == 1
@@ -267,7 +240,7 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No
msg_mock.reset_mock()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
# Trigger status while we have a fulfilled order for the open trade
telegram._status(bot=MagicMock(), update=update)
@@ -319,7 +292,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
msg_mock.reset_mock()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
telegram._status_table(bot=MagicMock(), update=update)
@@ -335,6 +308,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
limit_sell_order, markets, mocker) -> None:
patch_exchange(mocker)
default_conf['max_open_trades'] = 1
mocker.patch(
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
return_value=15000.0
@@ -358,7 +332,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -384,9 +358,9 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
# Reset msg_mock
msg_mock.reset_mock()
freqtradebot.config['max_open_trades'] = 2
# Add two other trades
freqtradebot.create_trade()
freqtradebot.create_trade()
freqtradebot.create_trades()
trades = Trade.query.all()
for trade in trades:
@@ -465,7 +439,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
msg_mock.reset_mock()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
@@ -760,7 +734,7 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -811,7 +785,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
# Decrease the price and sell it
mocker.patch.multiple(
@@ -859,14 +833,13 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker
markets=PropertyMock(return_value=markets),
validate_pairs=MagicMock(return_value={})
)
default_conf['max_open_trades'] = 4
freqtradebot = FreqtradeBot(default_conf)
patch_get_signal(freqtradebot, (True, False))
telegram = Telegram(freqtradebot)
# Create some test data
for _ in range(4):
freqtradebot.create_trade()
freqtradebot.create_trades()
rpc_mock.reset_mock()
update.message.text = '/forcesell all'
@@ -1010,7 +983,7 @@ def test_performance_handle(default_conf, update, ticker, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -1055,7 +1028,7 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non
freqtradebot.state = State.RUNNING
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
msg_mock.reset_mock()
telegram._count(bot=MagicMock(), update=update)
@@ -1440,7 +1413,4 @@ def test__send_msg_network_error(default_conf, mocker, caplog) -> None:
# Bot should've tried to send it twice
assert len(bot.method_calls) == 2
assert log_has(
'Telegram NetworkError: Oh snap! Trying one more time.',
caplog.record_tuples
)
assert log_has('Telegram NetworkError: Oh snap! Trying one more time.', caplog)

View File

@@ -115,7 +115,7 @@ def test_exception_send_msg(default_conf, mocker, caplog):
webhook = Webhook(get_patched_freqtradebot(mocker, default_conf))
webhook.send_msg({'type': RPCMessageType.BUY_NOTIFICATION})
assert log_has(f"Message type {RPCMessageType.BUY_NOTIFICATION} not configured for webhooks",
caplog.record_tuples)
caplog)
default_conf["webhook"] = get_webhook_dict()
default_conf["webhook"]["webhookbuy"]["value1"] = "{DEADBEEF:8f}"
@@ -135,7 +135,7 @@ def test_exception_send_msg(default_conf, mocker, caplog):
}
webhook.send_msg(msg)
assert log_has("Problem calling Webhook. Please check your webhook configuration. "
"Exception: 'DEADBEEF'", caplog.record_tuples)
"Exception: 'DEADBEEF'", caplog)
msg_mock = MagicMock()
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
@@ -164,4 +164,4 @@ def test__send_msg(default_conf, mocker, caplog):
post = MagicMock(side_effect=RequestException)
mocker.patch("freqtrade.rpc.webhook.post", post)
webhook._send_msg(msg)
assert log_has('Could not call webhook url. Exception: ', caplog.record_tuples)
assert log_has('Could not call webhook url. Exception: ', caplog)

View File

@@ -49,12 +49,12 @@ def test_returns_latest_sell_signal(mocker, default_conf, ticker_history):
def test_get_signal_empty(default_conf, mocker, caplog):
assert (False, False) == _STRATEGY.get_signal('foo', default_conf['ticker_interval'],
DataFrame())
assert log_has('Empty ticker history for pair foo', caplog.record_tuples)
assert log_has('Empty ticker history for pair foo', caplog)
caplog.clear()
assert (False, False) == _STRATEGY.get_signal('bar', default_conf['ticker_interval'],
[])
assert log_has('Empty ticker history for pair bar', caplog.record_tuples)
assert log_has('Empty ticker history for pair bar', caplog)
def test_get_signal_exception_valueerror(default_conf, mocker, caplog, ticker_history):
@@ -65,7 +65,7 @@ def test_get_signal_exception_valueerror(default_conf, mocker, caplog, ticker_hi
)
assert (False, False) == _STRATEGY.get_signal('foo', default_conf['ticker_interval'],
ticker_history)
assert log_has('Unable to analyze ticker for pair foo: xyz', caplog.record_tuples)
assert log_has('Unable to analyze ticker for pair foo: xyz', caplog)
def test_get_signal_empty_dataframe(default_conf, mocker, caplog, ticker_history):
@@ -76,7 +76,7 @@ def test_get_signal_empty_dataframe(default_conf, mocker, caplog, ticker_history
)
assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['ticker_interval'],
ticker_history)
assert log_has('Empty dataframe for pair xyz', caplog.record_tuples)
assert log_has('Empty dataframe for pair xyz', caplog)
def test_get_signal_old_dataframe(default_conf, mocker, caplog, ticker_history):
@@ -91,10 +91,7 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ticker_history):
)
assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['ticker_interval'],
ticker_history)
assert log_has(
'Outdated history for pair xyz. Last tick is 16 minutes old',
caplog.record_tuples
)
assert log_has('Outdated history for pair xyz. Last tick is 16 minutes old', caplog)
def test_get_signal_handles_exceptions(mocker, default_conf):
@@ -237,9 +234,8 @@ def test_analyze_ticker_default(ticker_history, mocker, caplog) -> None:
assert buy_mock.call_count == 1
assert buy_mock.call_count == 1
assert log_has('TA Analysis Launched', caplog.record_tuples)
assert not log_has('Skipping TA Analysis for already analyzed candle',
caplog.record_tuples)
assert log_has('TA Analysis Launched', caplog)
assert not log_has('Skipping TA Analysis for already analyzed candle', caplog)
caplog.clear()
strategy.analyze_ticker(ticker_history, {'pair': 'ETH/BTC'})
@@ -247,9 +243,8 @@ def test_analyze_ticker_default(ticker_history, mocker, caplog) -> None:
assert ind_mock.call_count == 2
assert buy_mock.call_count == 2
assert buy_mock.call_count == 2
assert log_has('TA Analysis Launched', caplog.record_tuples)
assert not log_has('Skipping TA Analysis for already analyzed candle',
caplog.record_tuples)
assert log_has('TA Analysis Launched', caplog)
assert not log_has('Skipping TA Analysis for already analyzed candle', caplog)
def test__analyze_ticker_internal_skip_analyze(ticker_history, mocker, caplog) -> None:
@@ -275,9 +270,8 @@ def test__analyze_ticker_internal_skip_analyze(ticker_history, mocker, caplog) -
assert ind_mock.call_count == 1
assert buy_mock.call_count == 1
assert buy_mock.call_count == 1
assert log_has('TA Analysis Launched', caplog.record_tuples)
assert not log_has('Skipping TA Analysis for already analyzed candle',
caplog.record_tuples)
assert log_has('TA Analysis Launched', caplog)
assert not log_has('Skipping TA Analysis for already analyzed candle', caplog)
caplog.clear()
ret = strategy._analyze_ticker_internal(ticker_history, {'pair': 'ETH/BTC'})
@@ -290,6 +284,21 @@ def test__analyze_ticker_internal_skip_analyze(ticker_history, mocker, caplog) -
assert 'sell' in ret.columns
assert ret['buy'].sum() == 0
assert ret['sell'].sum() == 0
assert not log_has('TA Analysis Launched', caplog.record_tuples)
assert log_has('Skipping TA Analysis for already analyzed candle',
caplog.record_tuples)
assert not log_has('TA Analysis Launched', caplog)
assert log_has('Skipping TA Analysis for already analyzed candle', caplog)
def test_is_pair_locked(default_conf):
strategy = DefaultStrategy(default_conf)
# dict should be empty
assert not strategy._pair_locked_until
pair = 'ETH/BTC'
assert not strategy.is_pair_locked(pair)
strategy.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime)
# ETH/BTC locked for 4 minutes
assert strategy.is_pair_locked(pair)
# XRP/BTC should not be locked now
pair = 'XRP/BTC'
assert not strategy.is_pair_locked(pair)

View File

@@ -15,7 +15,7 @@ from freqtrade.resolvers import StrategyResolver
from freqtrade.strategy import import_strategy
from freqtrade.strategy.default_strategy import DefaultStrategy
from freqtrade.strategy.interface import IStrategy
from freqtrade.tests.conftest import log_has_re
from freqtrade.tests.conftest import log_has, log_has_re
def test_import_strategy(caplog):
@@ -35,12 +35,8 @@ def test_import_strategy(caplog):
assert imported_strategy.__module__ == 'freqtrade.strategy'
assert imported_strategy.some_method() == 42
assert (
'freqtrade.strategy',
logging.DEBUG,
'Imported strategy freqtrade.strategy.default_strategy.DefaultStrategy '
'as freqtrade.strategy.DefaultStrategy',
) in caplog.record_tuples
assert log_has('Imported strategy freqtrade.strategy.default_strategy.DefaultStrategy '
'as freqtrade.strategy.DefaultStrategy', caplog)
def test_search_strategy():
@@ -79,8 +75,7 @@ def test_load_strategy_base64(result, caplog, default_conf):
assert 'adx' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
# Make sure strategy was loaded from base64 (using temp directory)!!
assert log_has_re(r"Using resolved strategy TestStrategy from '"
+ tempfile.gettempdir() + r"/.*/TestStrategy\.py'\.\.\.",
caplog.record_tuples)
+ tempfile.gettempdir() + r"/.*/TestStrategy\.py'\.\.\.", caplog)
def test_load_strategy_invalid_directory(result, caplog, default_conf):
@@ -88,7 +83,7 @@ def test_load_strategy_invalid_directory(result, caplog, default_conf):
extra_dir = Path.cwd() / 'some/path'
resolver._load_strategy('TestStrategy', config=default_conf, extra_dir=extra_dir)
assert log_has_re(r'Path .*' + r'some.*path.*' + r'.* does not exist', caplog.record_tuples)
assert log_has_re(r'Path .*' + r'some.*path.*' + r'.* does not exist', caplog)
assert 'adx' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
@@ -108,7 +103,7 @@ def test_load_staticmethod_importerror(mocker, caplog, default_conf):
match=r"Impossible to load Strategy 'DefaultStrategy'. "
r"This class does not exist or contains Python code errors."):
StrategyResolver(default_conf)
assert log_has_re(r".*Error: can't pickle staticmethod objects", caplog.record_tuples)
assert log_has_re(r".*Error: can't pickle staticmethod objects", caplog)
def test_strategy(result, default_conf):
@@ -146,10 +141,7 @@ def test_strategy_override_minimal_roi(caplog, default_conf):
resolver = StrategyResolver(default_conf)
assert resolver.strategy.minimal_roi[0] == 0.5
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'minimal_roi' with value in config file: {'0': 0.5}."
) in caplog.record_tuples
assert log_has("Override strategy 'minimal_roi' with value in config file: {'0': 0.5}.", caplog)
def test_strategy_override_stoploss(caplog, default_conf):
@@ -161,10 +153,7 @@ def test_strategy_override_stoploss(caplog, default_conf):
resolver = StrategyResolver(default_conf)
assert resolver.strategy.stoploss == -0.5
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'stoploss' with value in config file: -0.5."
) in caplog.record_tuples
assert log_has("Override strategy 'stoploss' with value in config file: -0.5.", caplog)
def test_strategy_override_trailing_stop(caplog, default_conf):
@@ -177,10 +166,7 @@ def test_strategy_override_trailing_stop(caplog, default_conf):
assert resolver.strategy.trailing_stop
assert isinstance(resolver.strategy.trailing_stop, bool)
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'trailing_stop' with value in config file: True."
) in caplog.record_tuples
assert log_has("Override strategy 'trailing_stop' with value in config file: True.", caplog)
def test_strategy_override_trailing_stop_positive(caplog, default_conf):
@@ -194,16 +180,12 @@ def test_strategy_override_trailing_stop_positive(caplog, default_conf):
resolver = StrategyResolver(default_conf)
assert resolver.strategy.trailing_stop_positive == -0.1
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'trailing_stop_positive' with value in config file: -0.1."
) in caplog.record_tuples
assert log_has("Override strategy 'trailing_stop_positive' with value in config file: -0.1.",
caplog)
assert resolver.strategy.trailing_stop_positive_offset == -0.2
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'trailing_stop_positive' with value in config file: -0.1."
) in caplog.record_tuples
assert log_has("Override strategy 'trailing_stop_positive' with value in config file: -0.1.",
caplog)
def test_strategy_override_ticker_interval(caplog, default_conf):
@@ -218,10 +200,8 @@ def test_strategy_override_ticker_interval(caplog, default_conf):
assert resolver.strategy.ticker_interval == 60
assert resolver.strategy.stake_currency == 'ETH'
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'ticker_interval' with value in config file: 60."
) in caplog.record_tuples
assert log_has("Override strategy 'ticker_interval' with value in config file: 60.",
caplog)
def test_strategy_override_process_only_new_candles(caplog, default_conf):
@@ -234,10 +214,8 @@ def test_strategy_override_process_only_new_candles(caplog, default_conf):
resolver = StrategyResolver(default_conf)
assert resolver.strategy.process_only_new_candles
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'process_only_new_candles' with value in config file: True."
) in caplog.record_tuples
assert log_has("Override strategy 'process_only_new_candles' with value in config file: True.",
caplog)
def test_strategy_override_order_types(caplog, default_conf):
@@ -259,12 +237,9 @@ def test_strategy_override_order_types(caplog, default_conf):
for method in ['buy', 'sell', 'stoploss', 'stoploss_on_exchange']:
assert resolver.strategy.order_types[method] == order_types[method]
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'order_types' with value in config file:"
" {'buy': 'market', 'sell': 'limit', 'stoploss': 'limit',"
" 'stoploss_on_exchange': True}."
) in caplog.record_tuples
assert log_has("Override strategy 'order_types' with value in config file:"
" {'buy': 'market', 'sell': 'limit', 'stoploss': 'limit',"
" 'stoploss_on_exchange': True}.", caplog)
default_conf.update({
'strategy': 'DefaultStrategy',
@@ -295,11 +270,8 @@ def test_strategy_override_order_tif(caplog, default_conf):
for method in ['buy', 'sell']:
assert resolver.strategy.order_time_in_force[method] == order_time_in_force[method]
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'order_time_in_force' with value in config file:"
" {'buy': 'fok', 'sell': 'gtc'}."
) in caplog.record_tuples
assert log_has("Override strategy 'order_time_in_force' with value in config file:"
" {'buy': 'fok', 'sell': 'gtc'}.", caplog)
default_conf.update({
'strategy': 'DefaultStrategy',
@@ -334,10 +306,7 @@ def test_strategy_override_use_sell_signal(caplog, default_conf):
assert resolver.strategy.use_sell_signal
assert isinstance(resolver.strategy.use_sell_signal, bool)
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'use_sell_signal' with value in config file: True."
) in caplog.record_tuples
assert log_has("Override strategy 'use_sell_signal' with value in config file: True.", caplog)
def test_strategy_override_use_sell_profit_only(caplog, default_conf):
@@ -362,10 +331,7 @@ def test_strategy_override_use_sell_profit_only(caplog, default_conf):
assert resolver.strategy.sell_profit_only
assert isinstance(resolver.strategy.sell_profit_only, bool)
assert ('freqtrade.resolvers.strategy_resolver',
logging.INFO,
"Override strategy 'sell_profit_only' with value in config file: True."
) in caplog.record_tuples
assert log_has("Override strategy 'sell_profit_only' with value in config file: True.", caplog)
@pytest.mark.filterwarnings("ignore:deprecated")

View File

@@ -3,7 +3,7 @@ import argparse
import pytest
from freqtrade.configuration import Arguments, TimeRange
from freqtrade.configuration import Arguments
from freqtrade.configuration.arguments import ARGS_DOWNLOADER, ARGS_PLOT_DATAFRAME
from freqtrade.configuration.cli_options import check_int_positive
@@ -86,30 +86,6 @@ def test_parse_args_strategy_path_invalid() -> None:
Arguments(['--strategy-path'], '').get_parsed_arg()
def test_parse_timerange_incorrect() -> None:
assert TimeRange(None, 'line', 0, -200) == Arguments.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == Arguments.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == Arguments.parse_timerange('200-500')
assert TimeRange('date', None, 1274486400, 0) == Arguments.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == Arguments.parse_timerange('-20100522')
timerange = Arguments.parse_timerange('20100522-20150730')
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == Arguments.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == Arguments.parse_timerange('-1233360000')
timerange = Arguments.parse_timerange('1231006505-1233360000')
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
# TODO: Find solution for the following case (passing timestamp in ms)
timerange = Arguments.parse_timerange('1231006505000-1233360000000')
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
Arguments.parse_timerange('-')
def test_parse_args_backtesting_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'):
Arguments(['backtesting --ticker-interval'], '').get_parsed_arg()

View File

@@ -73,7 +73,7 @@ def test__args_to_config(caplog):
# No warnings ...
configuration._args_to_config(config, argname="strategy_path", logstring="DeadBeef")
assert len(w) == 0
assert log_has("DeadBeef", caplog.record_tuples)
assert log_has("DeadBeef", caplog)
assert config['strategy_path'] == "TestTest"
configuration = Configuration(args)
@@ -85,7 +85,7 @@ def test__args_to_config(caplog):
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "DEPRECATED: Going away soon!" in str(w[-1].message)
assert log_has("DeadBeef", caplog.record_tuples)
assert log_has("DeadBeef", caplog)
assert config['strategy_path'] == "TestTest"
@@ -99,7 +99,7 @@ def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None:
assert validated_conf['max_open_trades'] == 0
assert 'internals' in validated_conf
assert log_has('Validating configuration ...', caplog.record_tuples)
assert log_has('Validating configuration ...', caplog)
def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None:
@@ -131,7 +131,36 @@ def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None:
assert validated_conf['exchange']['pair_whitelist'] == conf2['exchange']['pair_whitelist']
assert 'internals' in validated_conf
assert log_has('Validating configuration ...', caplog.record_tuples)
assert log_has('Validating configuration ...', caplog)
def test_from_config(default_conf, mocker, caplog) -> None:
conf1 = deepcopy(default_conf)
conf2 = deepcopy(default_conf)
del conf1['exchange']['key']
del conf1['exchange']['secret']
del conf2['exchange']['name']
conf2['exchange']['pair_whitelist'] += ['NANO/BTC']
conf2['fiat_display_currency'] = "EUR"
config_files = [conf1, conf2]
configsmock = MagicMock(side_effect=config_files)
mocker.patch(
'freqtrade.configuration.configuration.load_config_file',
configsmock
)
validated_conf = Configuration.from_files(['test_conf.json', 'test2_conf.json'])
exchange_conf = default_conf['exchange']
assert validated_conf['exchange']['name'] == exchange_conf['name']
assert validated_conf['exchange']['key'] == exchange_conf['key']
assert validated_conf['exchange']['secret'] == exchange_conf['secret']
assert validated_conf['exchange']['pair_whitelist'] != conf1['exchange']['pair_whitelist']
assert validated_conf['exchange']['pair_whitelist'] == conf2['exchange']['pair_whitelist']
assert validated_conf['fiat_display_currency'] == "EUR"
assert 'internals' in validated_conf
assert log_has('Validating configuration ...', caplog)
def test_load_config_max_open_trades_minus_one(default_conf, mocker, caplog) -> None:
@@ -144,7 +173,7 @@ def test_load_config_max_open_trades_minus_one(default_conf, mocker, caplog) ->
assert validated_conf['max_open_trades'] > 999999999
assert validated_conf['max_open_trades'] == float('inf')
assert log_has('Validating configuration ...', caplog.record_tuples)
assert log_has('Validating configuration ...', caplog)
assert "runmode" in validated_conf
assert validated_conf['runmode'] == RunMode.DRY_RUN
@@ -281,8 +310,8 @@ def test_show_info(default_conf, mocker, caplog) -> None:
configuration = Configuration(args)
configuration.get_config()
assert log_has('Using DB: "sqlite:///tmp/testdb"', caplog.record_tuples)
assert log_has('Dry run is enabled', caplog.record_tuples)
assert log_has('Using DB: "sqlite:///tmp/testdb"', caplog)
assert log_has('Dry run is enabled', caplog)
def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None:
@@ -305,21 +334,18 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert 'user_data_dir' in config
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples)
assert not log_has('Parameter -i/--ticker-interval detected ...', caplog)
assert 'live' not in config
assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert not log_has('Parameter -l/--live detected ...', caplog)
assert 'position_stacking' not in config
assert not log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert not log_has('Parameter --enable-position-stacking detected ...', caplog)
assert 'refresh_pairs' not in config
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' not in config
assert 'export' not in config
@@ -361,43 +387,31 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
assert 'exchange' in config
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert log_has(
'Using data directory: {} ...'.format("/foo/bar"),
caplog.record_tuples
)
assert log_has(
'Using user-data directory: {} ...'.format("/tmp/freqtrade"),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format("/foo/bar"), caplog)
assert log_has('Using user-data directory: {} ...'.format("/tmp/freqtrade"), caplog)
assert 'user_data_dir' in config
assert 'ticker_interval' in config
assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...',
caplog.record_tuples)
caplog)
assert 'live' in config
assert log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert log_has('Parameter -l/--live detected ...', caplog)
assert 'position_stacking'in config
assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert log_has('Parameter --enable-position-stacking detected ...', caplog)
assert 'use_max_market_positions' in config
assert log_has('Parameter --disable-max-market-positions detected ...', caplog.record_tuples)
assert log_has('max_open_trades set to unlimited ...', caplog.record_tuples)
assert log_has('Parameter --disable-max-market-positions detected ...', caplog)
assert log_has('max_open_trades set to unlimited ...', caplog)
assert 'refresh_pairs'in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog)
assert 'timerange' in config
assert log_has(
'Parameter --timerange detected: {} ...'.format(config['timerange']),
caplog.record_tuples
)
assert log_has('Parameter --timerange detected: {} ...'.format(config['timerange']), caplog)
assert 'export' in config
assert log_has(
'Parameter --export detected: {} ...'.format(config['export']),
caplog.record_tuples
)
assert log_has('Parameter --export detected: {} ...'.format(config['export']), caplog)
def test_setup_configuration_with_stratlist(mocker, default_conf, caplog) -> None:
@@ -427,16 +441,13 @@ def test_setup_configuration_with_stratlist(mocker, default_conf, caplog) -> Non
assert 'exchange' in config
assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config
assert log_has(
'Using data directory: {} ...'.format(config['datadir']),
caplog.record_tuples
)
assert log_has('Using data directory: {} ...'.format(config['datadir']), caplog)
assert 'ticker_interval' in config
assert log_has('Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...',
caplog.record_tuples)
caplog)
assert 'strategy_list' in config
assert log_has('Using strategy list of 2 Strategies', caplog.record_tuples)
assert log_has('Using strategy list of 2 Strategies', caplog)
assert 'position_stacking' not in config
@@ -445,10 +456,7 @@ def test_setup_configuration_with_stratlist(mocker, default_conf, caplog) -> Non
assert 'timerange' not in config
assert 'export' in config
assert log_has(
'Parameter --export detected: {} ...'.format(config['export']),
caplog.record_tuples
)
assert log_has('Parameter --export detected: {} ...'.format(config['export']), caplog)
def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None:
@@ -467,11 +475,11 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None:
assert 'epochs' in config
assert int(config['epochs']) == 10
assert log_has('Parameter --epochs detected ... Will run Hyperopt with for 10 epochs ...',
caplog.record_tuples)
caplog)
assert 'spaces' in config
assert config['spaces'] == ['all']
assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog.record_tuples)
assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog)
assert "runmode" in config
assert config['runmode'] == RunMode.HYPEROPT
@@ -481,38 +489,35 @@ def test_check_exchange(default_conf, caplog) -> None:
default_conf.get('exchange').update({'name': 'BITTREX'})
assert check_exchange(default_conf)
assert log_has_re(r"Exchange .* is officially supported by the Freqtrade development team\.",
caplog.record_tuples)
caplog)
caplog.clear()
# Test an officially supported by Freqtrade team exchange
default_conf.get('exchange').update({'name': 'binance'})
assert check_exchange(default_conf)
assert log_has_re(r"Exchange .* is officially supported by the Freqtrade development team\.",
caplog.record_tuples)
caplog)
caplog.clear()
# Test an available exchange, supported by ccxt
default_conf.get('exchange').update({'name': 'kraken'})
assert check_exchange(default_conf)
assert log_has_re(r"Exchange .* is supported by ccxt and .* not officially supported "
r"by the Freqtrade development team\. .*",
caplog.record_tuples)
r"by the Freqtrade development team\. .*", caplog)
caplog.clear()
# Test a 'bad' exchange, which known to have serious problems
default_conf.get('exchange').update({'name': 'bitmex'})
assert not check_exchange(default_conf)
assert log_has_re(r"Exchange .* is known to not work with the bot yet\. "
r"Use it only for development and testing purposes\.",
caplog.record_tuples)
with pytest.raises(OperationalException,
match=r"Exchange .* is known to not work with the bot yet.*"):
check_exchange(default_conf)
caplog.clear()
# Test a 'bad' exchange with check_for_bad=False
default_conf.get('exchange').update({'name': 'bitmex'})
assert check_exchange(default_conf, False)
assert log_has_re(r"Exchange .* is supported by ccxt and .* not officially supported "
r"by the Freqtrade development team\. .*",
caplog.record_tuples)
r"by the Freqtrade development team\. .*", caplog)
caplog.clear()
# Test an invalid exchange
@@ -538,7 +543,7 @@ def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
validated_conf = configuration.load_config()
assert validated_conf.get('verbosity') == 3
assert log_has('Verbosity set to 3', caplog.record_tuples)
assert log_has('Verbosity set to 3', caplog)
def test_set_loggers() -> None:
@@ -604,7 +609,7 @@ def test_load_config_warn_forcebuy(default_conf, mocker, caplog) -> None:
validated_conf = configuration.load_config()
assert validated_conf.get('forcebuy_enable')
assert log_has('`forcebuy` RPC message enabled.', caplog.record_tuples)
assert log_has('`forcebuy` RPC message enabled.', caplog)
def test_validate_default_conf(default_conf) -> None:
@@ -617,7 +622,7 @@ def test_create_datadir(mocker, default_conf, caplog) -> None:
create_datadir(default_conf, '/foo/bar')
assert md.call_args[1]['parents'] is True
assert log_has('Created data directory: /foo/bar', caplog.record_tuples)
assert log_has('Created data directory: /foo/bar', caplog)
def test_create_userdata_dir(mocker, default_conf, caplog) -> None:
@@ -675,6 +680,17 @@ def test_validate_tsl(default_conf):
configuration._validate_config_consistency(default_conf)
def test_load_config_test_comments() -> None:
"""
Load config with comments
"""
config_file = Path(__file__).parents[0] / "config_test_comments.json"
print(config_file)
conf = load_config_file(str(config_file))
assert conf
def test_load_config_default_exchange(all_conf) -> None:
"""
config['exchange'] subtree has required options in it

File diff suppressed because it is too large Load Diff

View File

@@ -60,8 +60,8 @@ def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('Fatal exception!', caplog.record_tuples)
assert log_has('Using config: config.json.example ...', caplog)
assert log_has('Fatal exception!', caplog)
def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None:
@@ -77,8 +77,8 @@ def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None:
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('SIGINT received, aborting ...', caplog.record_tuples)
assert log_has('Using config: config.json.example ...', caplog)
assert log_has('SIGINT received, aborting ...', caplog)
def test_main_operational_exception(mocker, default_conf, caplog) -> None:
@@ -97,8 +97,8 @@ def test_main_operational_exception(mocker, default_conf, caplog) -> None:
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('Oh snap!', caplog.record_tuples)
assert log_has('Using config: config.json.example ...', caplog)
assert log_has('Oh snap!', caplog)
def test_main_reload_conf(mocker, default_conf, caplog) -> None:
@@ -121,7 +121,7 @@ def test_main_reload_conf(mocker, default_conf, caplog) -> None:
with pytest.raises(SystemExit):
main(['-c', 'config.json.example'])
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('Using config: config.json.example ...', caplog)
assert worker_mock.call_count == 4
assert reconfigure_mock.call_count == 1
assert isinstance(worker.freqtrade, FreqtradeBot)

View File

@@ -151,7 +151,7 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order, fee, caplog):
assert trade.close_date is None
assert log_has("LIMIT_BUY has been fulfilled for Trade(id=2, "
"pair=ETH/BTC, amount=90.99181073, open_rate=0.00001099, open_since=closed).",
caplog.record_tuples)
caplog)
caplog.clear()
trade.open_order_id = 'something'
@@ -162,7 +162,7 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order, fee, caplog):
assert trade.close_date is not None
assert log_has("LIMIT_SELL has been fulfilled for Trade(id=2, "
"pair=ETH/BTC, amount=90.99181073, open_rate=0.00001099, open_since=closed).",
caplog.record_tuples)
caplog)
@pytest.mark.usefixtures("init_persistence")
@@ -184,7 +184,7 @@ def test_update_market_order(market_buy_order, market_sell_order, fee, caplog):
assert trade.close_date is None
assert log_has("MARKET_BUY has been fulfilled for Trade(id=1, "
"pair=ETH/BTC, amount=91.99181073, open_rate=0.00004099, open_since=closed).",
caplog.record_tuples)
caplog)
caplog.clear()
trade.open_order_id = 'something'
@@ -195,7 +195,7 @@ def test_update_market_order(market_buy_order, market_sell_order, fee, caplog):
assert trade.close_date is not None
assert log_has("MARKET_SELL has been fulfilled for Trade(id=1, "
"pair=ETH/BTC, amount=91.99181073, open_rate=0.00004099, open_since=closed).",
caplog.record_tuples)
caplog)
@pytest.mark.usefixtures("init_persistence")
@@ -558,10 +558,9 @@ def test_migrate_new(mocker, default_conf, fee, caplog):
assert trade.ticker_interval is None
assert trade.stoploss_order_id is None
assert trade.stoploss_last_update is None
assert log_has("trying trades_bak1", caplog.record_tuples)
assert log_has("trying trades_bak2", caplog.record_tuples)
assert log_has("Running database migration - backup available as trades_bak2",
caplog.record_tuples)
assert log_has("trying trades_bak1", caplog)
assert log_has("trying trades_bak2", caplog)
assert log_has("Running database migration - backup available as trades_bak2", caplog)
def test_migrate_mid_state(mocker, default_conf, fee, caplog):
@@ -621,9 +620,8 @@ def test_migrate_mid_state(mocker, default_conf, fee, caplog):
assert trade.max_rate == 0.0
assert trade.stop_loss == 0.0
assert trade.initial_stop_loss == 0.0
assert log_has("trying trades_bak0", caplog.record_tuples)
assert log_has("Running database migration - backup available as trades_bak0",
caplog.record_tuples)
assert log_has("trying trades_bak0", caplog)
assert log_has("Running database migration - backup available as trades_bak0", caplog)
def test_adjust_stop_loss(fee):

View File

@@ -6,7 +6,7 @@ from unittest.mock import MagicMock
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from freqtrade.configuration import Arguments, TimeRange
from freqtrade.configuration import TimeRange
from freqtrade.data import history
from freqtrade.data.btanalysis import create_cum_profit, load_backtest_data
from freqtrade.plot.plotting import (add_indicators, add_profit,
@@ -88,7 +88,7 @@ def test_add_indicators(default_conf, caplog):
# No indicator found
fig3 = add_indicators(fig=deepcopy(fig), row=3, indicators=['no_indicator'], data=data)
assert fig == fig3
assert log_has_re(r'Indicator "no_indicator" ignored\..*', caplog.record_tuples)
assert log_has_re(r'Indicator "no_indicator" ignored\..*', caplog)
def test_plot_trades(caplog):
@@ -96,7 +96,7 @@ def test_plot_trades(caplog):
# nothing happens when no trades are available
fig = plot_trades(fig1, None)
assert fig == fig1
assert log_has("No trades found.", caplog.record_tuples)
assert log_has("No trades found.", caplog)
pair = "ADA/BTC"
filename = history.make_testdata_path(None) / "backtest-result_test.json"
trades = load_backtest_data(filename)
@@ -151,8 +151,8 @@ def test_generate_candlestick_graph_no_signals_no_trades(default_conf, mocker, c
assert row_mock.call_count == 2
assert trades_mock.call_count == 1
assert log_has("No buy-signals found.", caplog.record_tuples)
assert log_has("No sell-signals found.", caplog.record_tuples)
assert log_has("No buy-signals found.", caplog)
assert log_has("No sell-signals found.", caplog)
def test_generate_candlestick_graph_no_trades(default_conf, mocker):
@@ -218,13 +218,13 @@ def test_generate_plot_file(mocker, caplog):
assert (plot_mock.call_args_list[0][1]['filename']
== "user_data/plots/freqtrade-plot-UNITTEST_BTC-5m.html")
assert log_has("Stored plot as user_data/plots/freqtrade-plot-UNITTEST_BTC-5m.html",
caplog.record_tuples)
caplog)
def test_add_profit():
filename = history.make_testdata_path(None) / "backtest-result_test.json"
bt_data = load_backtest_data(filename)
timerange = Arguments.parse_timerange("20180110-20180112")
timerange = TimeRange.parse_timerange("20180110-20180112")
df = history.load_pair_history(pair="POWR/BTC", ticker_interval='5m',
datadir=None, timerange=timerange)
@@ -244,7 +244,7 @@ def test_add_profit():
def test_generate_profit_graph():
filename = history.make_testdata_path(None) / "backtest-result_test.json"
trades = load_backtest_data(filename)
timerange = Arguments.parse_timerange("20180110-20180112")
timerange = TimeRange.parse_timerange("20180110-20180112")
pairs = ["POWR/BTC", "XLM/BTC"]
tickers = history.load_data(datadir=None,

View File

@@ -0,0 +1,28 @@
# pragma pylint: disable=missing-docstring, C0103
import pytest
from freqtrade.configuration import TimeRange
def test_parse_timerange_incorrect() -> None:
assert TimeRange(None, 'line', 0, -200) == TimeRange.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == TimeRange.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == TimeRange.parse_timerange('200-500')
assert TimeRange('date', None, 1274486400, 0) == TimeRange.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == TimeRange.parse_timerange('-20100522')
timerange = TimeRange.parse_timerange('20100522-20150730')
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == TimeRange.parse_timerange('-1233360000')
timerange = TimeRange.parse_timerange('1231006505-1233360000')
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
# TODO: Find solution for the following case (passing timestamp in ms)
timerange = TimeRange.parse_timerange('1231006505000-1233360000000')
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
TimeRange.parse_timerange('-')