From a213674a98bf9ae48ac4ef0c527e9f00340049d1 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:05 +0000 Subject: [PATCH 01/31] Update pandas from 0.24.2 to 0.25.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 52442fb19..fef8f06f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,5 @@ -r requirements-common.txt numpy==1.16.4 -pandas==0.24.2 +pandas==0.25.0 scipy==1.3.0 From d6b6e59ab8d92a8f388ea556831e829821893a47 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:06 +0000 Subject: [PATCH 02/31] Update ccxt from 1.18.860 to 1.18.965 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 409c979b5..5f549e245 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.18.860 +ccxt==1.18.965 SQLAlchemy==1.3.5 python-telegram-bot==11.1.0 arrow==0.14.2 From 7add015a758a69a0434c36589c99c18dbe17b14a Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:07 +0000 Subject: [PATCH 03/31] Update sqlalchemy from 1.3.5 to 1.3.6 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 5f549e245..4c8bab90d 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,7 +1,7 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs ccxt==1.18.965 -SQLAlchemy==1.3.5 +SQLAlchemy==1.3.6 python-telegram-bot==11.1.0 arrow==0.14.2 cachetools==3.1.1 From 6c41ca4b8cb00984c111d6a987072d5cf3f21219 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:08 +0000 Subject: [PATCH 04/31] Update flask from 1.0.3 to 1.1.1 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 4c8bab90d..3cf34ad61 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -29,4 +29,4 @@ python-rapidjson==0.7.2 sdnotify==0.3.2 # Api server -flask==1.0.3 +flask==1.1.1 From e0cd34c9e1d32e7017acb22fdac6bdfc763cb432 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:09 +0000 Subject: [PATCH 05/31] Update flake8 from 3.7.7 to 3.7.8 --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 83fec3b8a..28fd19ce4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ -r requirements.txt -r requirements-plot.txt -flake8==3.7.7 +flake8==3.7.8 flake8-type-annotations==0.1.0 flake8-tidy-imports==2.0.0 pytest==5.0.0 From bd0faaf70291b7f8e8b1fb4fe9d42197fd2102c3 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:11 +0000 Subject: [PATCH 06/31] Update pytest from 5.0.0 to 5.0.1 --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 28fd19ce4..e6f7bde1c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,7 @@ flake8==3.7.8 flake8-type-annotations==0.1.0 flake8-tidy-imports==2.0.0 -pytest==5.0.0 +pytest==5.0.1 pytest-mock==1.10.4 pytest-asyncio==0.10.0 pytest-cov==2.7.1 From 76b9d781ee9b028b12e78409444b6f34ab0f1a41 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:12 +0000 Subject: [PATCH 07/31] Update mypy from 0.711 to 0.720 --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e6f7bde1c..946d63039 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,4 +11,4 @@ pytest-asyncio==0.10.0 pytest-cov==2.7.1 pytest-random-order==1.0.4 coveralls==1.8.1 -mypy==0.711 +mypy==0.720 From 44b2261c347eb4757e3a6976e340e7e23f8c34dd Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 22 Jul 2019 15:23:13 +0000 Subject: [PATCH 08/31] Update plotly from 3.10.0 to 4.0.0 --- requirements-plot.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-plot.txt b/requirements-plot.txt index d4e4fc165..a6753fc3f 100644 --- a/requirements-plot.txt +++ b/requirements-plot.txt @@ -1,5 +1,5 @@ # Include all requirements to run the bot. -r requirements.txt -plotly==3.10.0 +plotly==4.0.0 From 482f5f7a26c95a2d215e0b98edb817b169317d96 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 22 Jul 2019 20:39:38 +0200 Subject: [PATCH 09/31] Update plotly dependencies (will break 3.x installations) --- freqtrade/plot/plotting.py | 36 ++++++++++++++++---------------- freqtrade/resolvers/iresolver.py | 2 +- freqtrade/tests/test_plotting.py | 6 +++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index dde6f78f0..5c9c6e457 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -15,9 +15,9 @@ logger = logging.getLogger(__name__) try: - from plotly import tools + from plotly.subplots import make_subplots from plotly.offline import plot - import plotly.graph_objs as go + import plotly.graph_objects as go except ImportError: logger.exception("Module plotly not found \n Please install using `pip install plotly`") exit(1) @@ -62,7 +62,7 @@ def init_plotscript(config): } -def add_indicators(fig, row, indicators: List[str], data: pd.DataFrame) -> tools.make_subplots: +def add_indicators(fig, row, indicators: List[str], data: pd.DataFrame) -> make_subplots: """ Generator all the indicator selected by the user for a specific row :param fig: Plot figure to append to @@ -79,7 +79,7 @@ def add_indicators(fig, row, indicators: List[str], data: pd.DataFrame) -> tools mode='lines', name=indicator ) - fig.append_trace(scattergl, row, 1) + fig.add_trace(scattergl, row, 1) else: logger.info( 'Indicator "%s" ignored. Reason: This indicator is not found ' @@ -90,7 +90,7 @@ def add_indicators(fig, row, indicators: List[str], data: pd.DataFrame) -> tools return fig -def add_profit(fig, row, data: pd.DataFrame, column: str, name: str) -> tools.make_subplots: +def add_profit(fig, row, data: pd.DataFrame, column: str, name: str) -> make_subplots: """ Add profit-plot :param fig: Plot figure to append to @@ -105,12 +105,12 @@ def add_profit(fig, row, data: pd.DataFrame, column: str, name: str) -> tools.ma y=data[column], name=name, ) - fig.append_trace(profit, row, 1) + fig.add_trace(profit, row, 1) return fig -def plot_trades(fig, trades: pd.DataFrame) -> tools.make_subplots: +def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: """ Add trades to "fig" """ @@ -145,8 +145,8 @@ def plot_trades(fig, trades: pd.DataFrame) -> tools.make_subplots: color='red' ) ) - fig.append_trace(trade_buys, 1, 1) - fig.append_trace(trade_sells, 1, 1) + fig.add_trace(trade_buys, 1, 1) + fig.add_trace(trade_sells, 1, 1) else: logger.warning("No trades found.") return fig @@ -167,7 +167,7 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra """ # Define the graph - fig = tools.make_subplots( + fig = make_subplots( rows=3, cols=1, shared_xaxes=True, @@ -189,7 +189,7 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra close=data.close, name='Price' ) - fig.append_trace(candles, 1, 1) + fig.add_trace(candles, 1, 1) if 'buy' in data.columns: df_buy = data[data['buy'] == 1] @@ -206,7 +206,7 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra color='green', ) ) - fig.append_trace(buys, 1, 1) + fig.add_trace(buys, 1, 1) else: logger.warning("No buy-signals found.") @@ -225,7 +225,7 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra color='red', ) ) - fig.append_trace(sells, 1, 1) + fig.add_trace(sells, 1, 1) else: logger.warning("No sell-signals found.") @@ -244,8 +244,8 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra fillcolor="rgba(0,176,246,0.2)", line={'color': 'rgba(255,255,255,0)'}, ) - fig.append_trace(bb_lower, 1, 1) - fig.append_trace(bb_upper, 1, 1) + fig.add_trace(bb_lower, 1, 1) + fig.add_trace(bb_upper, 1, 1) # Add indicators to main plot fig = add_indicators(fig=fig, row=1, indicators=indicators1, data=data) @@ -258,7 +258,7 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra y=data['volume'], name='Volume' ) - fig.append_trace(volume, 2, 1) + fig.add_trace(volume, 2, 1) # Add indicators to seperate row fig = add_indicators(fig=fig, row=3, indicators=indicators2, data=data) @@ -281,10 +281,10 @@ def generate_profit_graph(pairs: str, tickers: Dict[str, pd.DataFrame], name='Avg close price', ) - fig = tools.make_subplots(rows=3, cols=1, shared_xaxes=True, row_width=[1, 1, 1]) + fig = make_subplots(rows=3, cols=1, shared_xaxes=True, row_width=[1, 1, 1]) fig['layout'].update(title="Profit plot") - fig.append_trace(avgclose, 1, 1) + fig.add_trace(avgclose, 1, 1) fig = add_profit(fig, 2, df_comb, 'cum_profit', 'Profit') for pair in pairs: diff --git a/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index 9d0c97917..841c3cf43 100644 --- a/freqtrade/resolvers/iresolver.py +++ b/freqtrade/resolvers/iresolver.py @@ -84,6 +84,6 @@ class IResolver(object): f"from '{module_path}'...") return module except FileNotFoundError: - logger.warning('Path "%s" does not exist.', _path.relative_to(Path.cwd())) + logger.warning('Path "%s" does not exist.', _path.resolve()) return None diff --git a/freqtrade/tests/test_plotting.py b/freqtrade/tests/test_plotting.py index 0ebadf720..509bf7880 100644 --- a/freqtrade/tests/test_plotting.py +++ b/freqtrade/tests/test_plotting.py @@ -2,8 +2,8 @@ from copy import deepcopy from unittest.mock import MagicMock -import plotly.graph_objs as go -from plotly import tools +import plotly.graph_objects as go +from plotly.subplots import make_subplots from freqtrade.configuration import Arguments, TimeRange from freqtrade.data import history @@ -28,7 +28,7 @@ def find_trace_in_fig_data(data, search_string: str): def generage_empty_figure(): - return tools.make_subplots( + return make_subplots( rows=3, cols=1, shared_xaxes=True, From 60cf56e23582fd7a0e06db0ce080640670cef836 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 22 Jul 2019 20:57:40 +0200 Subject: [PATCH 10/31] Adapt tests to always provide message for ccxt exceptions Changes introduced in https://github.com/ccxt/ccxt/pull/5470 --- freqtrade/tests/exchange/test_exchange.py | 54 +++++++++++------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index a4f1bca18..a5cdf0a82 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -33,13 +33,13 @@ def get_mock_coro(return_value): def ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name, fun, mock_ccxt_fun, **kwargs): with pytest.raises(TemporaryError): - api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError) + api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError("DeaDBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) getattr(exchange, fun)(**kwargs) assert api_mock.__dict__[mock_ccxt_fun].call_count == API_RETRY_COUNT + 1 with pytest.raises(OperationalException): - api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.BaseError) + api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) getattr(exchange, fun)(**kwargs) assert api_mock.__dict__[mock_ccxt_fun].call_count == 1 @@ -47,13 +47,13 @@ def ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name, async def async_ccxt_exception(mocker, default_conf, api_mock, fun, mock_ccxt_fun, **kwargs): with pytest.raises(TemporaryError): - api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError) + api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock) await getattr(exchange, fun)(**kwargs) assert api_mock.__dict__[mock_ccxt_fun].call_count == API_RETRY_COUNT + 1 with pytest.raises(OperationalException): - api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.BaseError) + api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock) await getattr(exchange, fun)(**kwargs) assert api_mock.__dict__[mock_ccxt_fun].call_count == 1 @@ -256,13 +256,13 @@ def test__load_async_markets(default_conf, mocker, caplog): def test__load_markets(default_conf, mocker, caplog): caplog.set_level(logging.INFO) api_mock = MagicMock() - api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError()) + api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError("SomeError")) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock()) 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: ', caplog.record_tuples) + assert log_has('Unable to initialize markets. Reason: SomeError', caplog.record_tuples) expected_return = {'ETH/BTC': 'available'} api_mock = MagicMock() @@ -305,7 +305,7 @@ def test__reload_markets_exception(default_conf, mocker, caplog): caplog.set_level(logging.DEBUG) api_mock = MagicMock() - api_mock.load_markets = MagicMock(side_effect=ccxt.NetworkError) + api_mock.load_markets = MagicMock(side_effect=ccxt.NetworkError("LoadError")) default_conf['exchange']['markets_refresh_interval'] = 10 exchange = get_patched_exchange(mocker, default_conf, api_mock, id="binance") @@ -634,25 +634,25 @@ def test_buy_prod(default_conf, mocker, exchange_name): # test exception handling with pytest.raises(DependencyException): - api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds) + api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("Not enough funds")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.buy(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(DependencyException): - api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder) + api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.buy(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(TemporaryError): - api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError) + api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("Network disconnect")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.buy(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(OperationalException): - api_mock.create_order = MagicMock(side_effect=ccxt.BaseError) + api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("Unknown error")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.buy(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200, time_in_force=time_in_force) @@ -758,22 +758,22 @@ def test_sell_prod(default_conf, mocker, exchange_name): # test exception handling with pytest.raises(DependencyException): - api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds) + api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) with pytest.raises(DependencyException): - api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder) + api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) with pytest.raises(TemporaryError): - api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError) + api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No Connection")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) with pytest.raises(OperationalException): - api_mock.create_order = MagicMock(side_effect=ccxt.BaseError) + api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) @@ -846,7 +846,7 @@ def test_get_balance_prod(default_conf, mocker, exchange_name): assert exchange.get_balance(currency='BTC') == 123.4 with pytest.raises(OperationalException): - api_mock.fetch_balance = MagicMock(side_effect=ccxt.BaseError) + api_mock.fetch_balance = MagicMock(side_effect=ccxt.BaseError("Unknown error")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_balance(currency='BTC') @@ -919,7 +919,7 @@ def test_get_tickers(default_conf, mocker, exchange_name): "get_tickers", "fetch_tickers") with pytest.raises(OperationalException): - api_mock.fetch_tickers = MagicMock(side_effect=ccxt.NotSupported) + api_mock.fetch_tickers = MagicMock(side_effect=ccxt.NotSupported("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_tickers() @@ -1101,7 +1101,7 @@ async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_ api_mock = MagicMock() with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'): - api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError) + api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError("Unknown error")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) await exchange._async_get_candle_history(pair, "5m", (arrow.utcnow().timestamp - 2000) * 1000) @@ -1173,15 +1173,15 @@ def test_get_order_book(default_conf, mocker, order_book_l2, exchange_name): def test_get_order_book_exception(default_conf, mocker, exchange_name): api_mock = MagicMock() with pytest.raises(OperationalException): - api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.NotSupported) + api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.NotSupported("Not supported")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_order_book(pair='ETH/BTC', limit=50) with pytest.raises(TemporaryError): - api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.NetworkError) + api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.NetworkError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_order_book(pair='ETH/BTC', limit=50) with pytest.raises(OperationalException): - api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.BaseError) + api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_order_book(pair='ETH/BTC', limit=50) @@ -1294,7 +1294,7 @@ def test_cancel_order(default_conf, mocker, exchange_name): assert exchange.cancel_order(order_id='_', pair='TKN/BTC') == 123 with pytest.raises(InvalidOrderException): - api_mock.cancel_order = MagicMock(side_effect=ccxt.InvalidOrder) + api_mock.cancel_order = MagicMock(side_effect=ccxt.InvalidOrder("Did not find order")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.cancel_order(order_id='_', pair='TKN/BTC') assert api_mock.cancel_order.call_count == 1 @@ -1321,7 +1321,7 @@ def test_get_order(default_conf, mocker, exchange_name): assert exchange.get_order('X', 'TKN/BTC') == 456 with pytest.raises(InvalidOrderException): - api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder) + api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_order(order_id='_', pair='TKN/BTC') assert api_mock.fetch_order.call_count == 1 @@ -1437,22 +1437,22 @@ def test_stoploss_limit_order(default_conf, mocker): # test exception handling with pytest.raises(DependencyException): - api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds) + api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance")) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(DependencyException): - api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder) + api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(TemporaryError): - api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError) + api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection")) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(OperationalException): - api_mock.create_order = MagicMock(side_effect=ccxt.BaseError) + api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) From a0cecc6c522700e0884474d1f456fa03a3a22e01 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Jul 2019 06:29:50 +0200 Subject: [PATCH 11/31] Fix test after pandas 0.25.0 update --- freqtrade/data/btanalysis.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index dcd544d00..f2356c34b 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -67,7 +67,6 @@ def evaluate_result_multi(results: pd.DataFrame, freq: str, max_open_trades: int dates = pd.Series(pd.concat(dates).values, name='date') df2 = pd.DataFrame(np.repeat(results.values, deltas, axis=0), columns=results.columns) - df2 = df2.astype(dtype={"open_time": "datetime64", "close_time": "datetime64"}) df2 = pd.concat([dates, df2], axis=1) df2 = df2.set_index('date') df_final = df2.resample(freq)[['pair']].count() From b691fb7f2dc04b9def11a56e6746381622d144aa Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 28 Jul 2019 15:19:17 +0200 Subject: [PATCH 12/31] Fix some hyperopt tests --- freqtrade/tests/optimize/test_hyperopt.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index fad89e877..065b4c41b 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -8,7 +8,7 @@ import pytest from arrow import Arrow from filelock import Timeout -from freqtrade import DependencyException +from freqtrade import DependencyException, OperationalException from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.history import load_tickerdata_file from freqtrade.optimize import setup_configuration, start_hyperopt @@ -186,6 +186,13 @@ def test_hyperoptresolver(mocker, default_conf, caplog) -> None: assert hasattr(x, "ticker_interval") +def test_hyperoptresolver_wrongname(mocker, default_conf, caplog) -> None: + default_conf.update({'hyperopt': "NonExistingHyperoptClass"}) + + with pytest.raises(OperationalException, match=r'Impossible to load Hyperopt.*'): + HyperOptResolver(default_conf, ).hyperopt + + def test_hyperoptlossresolver(mocker, default_conf, caplog) -> None: hl = DefaultHyperOptLoss @@ -193,9 +200,15 @@ def test_hyperoptlossresolver(mocker, default_conf, caplog) -> None: 'freqtrade.resolvers.hyperopt_resolver.HyperOptLossResolver._load_hyperoptloss', MagicMock(return_value=hl) ) - x = HyperOptResolver(default_conf, ).hyperopt - assert hasattr(x, "populate_indicators") - assert hasattr(x, "ticker_interval") + x = HyperOptLossResolver(default_conf, ).hyperoptloss + assert hasattr(x, "hyperopt_loss_function") + + +def test_hyperoptlossresolver_wrongname(mocker, default_conf, caplog) -> None: + default_conf.update({'hyperopt_loss': "NonExistingLossClass"}) + + with pytest.raises(OperationalException, match=r'Impossible to load HyperoptLoss.*'): + HyperOptLossResolver(default_conf, ).hyperopt def test_start(mocker, default_conf, caplog) -> None: From 02bfe2dad3d9ad8c3f1aeba2023c703a20f2e9e2 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:06 +0000 Subject: [PATCH 13/31] Update numpy from 1.16.4 to 1.17.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 52442fb19..be1495d08 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Load common requirements -r requirements-common.txt -numpy==1.16.4 +numpy==1.17.0 pandas==0.24.2 scipy==1.3.0 From 5a6e20a6aaa3174623db908a6ab8007143f554a5 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:07 +0000 Subject: [PATCH 14/31] Update pandas from 0.24.2 to 0.25.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index be1495d08..6420c7879 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,5 @@ -r requirements-common.txt numpy==1.17.0 -pandas==0.24.2 +pandas==0.25.0 scipy==1.3.0 From fe088dc8c32bfe2f1378b5a361e198bcd8fbd042 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:08 +0000 Subject: [PATCH 15/31] Update ccxt from 1.18.860 to 1.18.992 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 409c979b5..0d6c3f217 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.18.860 +ccxt==1.18.992 SQLAlchemy==1.3.5 python-telegram-bot==11.1.0 arrow==0.14.2 From 0fd91e4450e97acb05635aac63e62fe6311dc926 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:09 +0000 Subject: [PATCH 16/31] Update sqlalchemy from 1.3.5 to 1.3.6 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 0d6c3f217..a1cdbc6c0 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,7 +1,7 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs ccxt==1.18.992 -SQLAlchemy==1.3.5 +SQLAlchemy==1.3.6 python-telegram-bot==11.1.0 arrow==0.14.2 cachetools==3.1.1 From 9f70ebecf16fd7afaa51ddfec57796d706cc7e82 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:10 +0000 Subject: [PATCH 17/31] Update arrow from 0.14.2 to 0.14.3 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index a1cdbc6c0..b79c700c8 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -3,7 +3,7 @@ ccxt==1.18.992 SQLAlchemy==1.3.6 python-telegram-bot==11.1.0 -arrow==0.14.2 +arrow==0.14.3 cachetools==3.1.1 requests==2.22.0 urllib3==1.24.2 # pyup: ignore From a3620c60adbbed1de171bbbaf03174cf973d7cc4 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:11 +0000 Subject: [PATCH 18/31] Update flask from 1.0.3 to 1.1.1 --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index b79c700c8..2e52b84ad 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -29,4 +29,4 @@ python-rapidjson==0.7.2 sdnotify==0.3.2 # Api server -flask==1.0.3 +flask==1.1.1 From ebca1e435745c2c7c72805c25d6629fe0cc0df92 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:12 +0000 Subject: [PATCH 19/31] Update flake8 from 3.7.7 to 3.7.8 --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 83fec3b8a..28fd19ce4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ -r requirements.txt -r requirements-plot.txt -flake8==3.7.7 +flake8==3.7.8 flake8-type-annotations==0.1.0 flake8-tidy-imports==2.0.0 pytest==5.0.0 From 0f632201e07c06f2f95cd48661857b79a00b488f Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:14 +0000 Subject: [PATCH 20/31] Update pytest from 5.0.0 to 5.0.1 --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 28fd19ce4..e6f7bde1c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,7 @@ flake8==3.7.8 flake8-type-annotations==0.1.0 flake8-tidy-imports==2.0.0 -pytest==5.0.0 +pytest==5.0.1 pytest-mock==1.10.4 pytest-asyncio==0.10.0 pytest-cov==2.7.1 From 3e95b7d8a51c2a12d074223eecc9ab90ecd2f913 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:15 +0000 Subject: [PATCH 21/31] Update mypy from 0.711 to 0.720 --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e6f7bde1c..946d63039 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,4 +11,4 @@ pytest-asyncio==0.10.0 pytest-cov==2.7.1 pytest-random-order==1.0.4 coveralls==1.8.1 -mypy==0.711 +mypy==0.720 From 5ba0aa8082b1c801f7cd99dca8356e32f25ff23d Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 29 Jul 2019 15:25:16 +0000 Subject: [PATCH 22/31] Update plotly from 3.10.0 to 4.0.0 --- requirements-plot.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-plot.txt b/requirements-plot.txt index d4e4fc165..a6753fc3f 100644 --- a/requirements-plot.txt +++ b/requirements-plot.txt @@ -1,5 +1,5 @@ # Include all requirements to run the bot. -r requirements.txt -plotly==3.10.0 +plotly==4.0.0 From e64509f1b42d95c4a86a6b6663dbf15c27bae6ec Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:27:50 +0200 Subject: [PATCH 23/31] Version bump to 2019.7 --- freqtrade/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/__init__.py b/freqtrade/__init__.py index 2fdcccea5..10900bee9 100644 --- a/freqtrade/__init__.py +++ b/freqtrade/__init__.py @@ -1,5 +1,5 @@ """ FreqTrade bot """ -__version__ = '2019.6-dev' +__version__ = '2019.7' class DependencyException(Exception): From 7a97995d81d25f6f9928c82a31d8de57c36e6a8e Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:30:14 +0200 Subject: [PATCH 24/31] 2017.7-dev version bump --- freqtrade/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/__init__.py b/freqtrade/__init__.py index 10900bee9..14f0bb819 100644 --- a/freqtrade/__init__.py +++ b/freqtrade/__init__.py @@ -1,5 +1,5 @@ """ FreqTrade bot """ -__version__ = '2019.7' +__version__ = '2019.7-dev' class DependencyException(Exception): From e14dd4974f0ebfeb07a302064cc2fc5cd615019d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:32:28 +0200 Subject: [PATCH 25/31] Improve release documentation --- docs/developer.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/developer.md b/docs/developer.md index f58e0597d..f50625111 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -156,6 +156,8 @@ git log --oneline --no-decorate --no-merges master..develop ### Create github release / tag +Once the PR against master is merged (best right after merging): + * Use the button "Draft a new release" in the Github UI (subsection releases) * Use the version-number specified as tag. * Use "master" as reference (this step comes after the above PR is merged). From 8dd8addd3aeadfd652f65a3a141491e263dcd79b Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:52:38 +0200 Subject: [PATCH 26/31] Sort requirements-dev file --- requirements-dev.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 946d63039..f54b38a57 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,13 +2,13 @@ -r requirements.txt -r requirements-plot.txt +coveralls==1.8.1 flake8==3.7.8 flake8-type-annotations==0.1.0 flake8-tidy-imports==2.0.0 +mypy==0.720 pytest==5.0.1 -pytest-mock==1.10.4 pytest-asyncio==0.10.0 pytest-cov==2.7.1 +pytest-mock==1.10.4 pytest-random-order==1.0.4 -coveralls==1.8.1 -mypy==0.720 From 7bea0007c7b6ef253a5e7903728ac556f5c2e0e1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:53:26 +0200 Subject: [PATCH 27/31] Allow installing via submodules freqtrade can be installed using `pip install -e .[all]` to include all dependencies --- setup.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index ca2f81d1f..1ae395295 100644 --- a/setup.py +++ b/setup.py @@ -8,6 +8,24 @@ if version_info.major == 3 and version_info.minor < 6 or \ from freqtrade import __version__ +# Requirements used for submodules +api = ['flask'] +plot = ['plotly>=4.0'] + +develop = [ + 'coveralls', + 'flake8', + 'flake8-type-annotations', + 'flake8-tidy-imports', + 'mypy', + 'pytest', + 'pytest-asyncio', + 'pytest-cov', + 'pytest-mock', + 'pytest-random-order', +] + +all_extra = api + plot + develop setup(name='freqtrade', version=__version__, @@ -20,26 +38,37 @@ setup(name='freqtrade', setup_requires=['pytest-runner', 'numpy'], tests_require=['pytest', 'pytest-mock', 'pytest-cov'], install_requires=[ - 'ccxt', + # from requirements-common.txt + 'ccxt>=1.18', 'SQLAlchemy', 'python-telegram-bot', 'arrow', + 'cachetools', 'requests', 'urllib3', 'wrapt', - 'pandas', 'scikit-learn', - 'scipy', 'joblib', 'jsonschema', 'TA-Lib', 'tabulate', - 'cachetools', 'coinmarketcap', 'scikit-optimize', + 'filelock', + 'py_find_1st', 'python-rapidjson', - 'py_find_1st' + 'sdnotify', + # from requirements.txt + 'numpy', + 'pandas', + 'scipy', ], + extras_require={ + 'api': api, + 'dev': develop, + 'plot': plot, + 'all': all_extra, + }, include_package_data=True, zip_safe=False, entry_points={ From f825e81d0eba06b58adc721715d7bbc545413ee4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:54:35 +0200 Subject: [PATCH 28/31] developers need all dependencies! --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1ae395295..202e3fd0d 100644 --- a/setup.py +++ b/setup.py @@ -65,7 +65,7 @@ setup(name='freqtrade', ], extras_require={ 'api': api, - 'dev': develop, + 'dev': all_extra, 'plot': plot, 'all': all_extra, }, From 59caff8fb1d49bf26b29cb3855354d0eed7d2aa9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Jul 2019 20:57:57 +0200 Subject: [PATCH 29/31] UPdate developer docs --- docs/developer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer.md b/docs/developer.md index f58e0597d..2895db7e8 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -12,8 +12,8 @@ Special fields for the documentation (like Note boxes, ...) can be found [here]( ## Developer setup -To configure a development environment, use best use the `setup.sh` script and answer "y" when asked "Do you want to install dependencies for dev [y/N]? ". -Alternatively (if your system is not supported by the setup.sh script), follow the manual installation process and run `pip3 install -r requirements-dev.txt`. +To configure a development environment, best use the `setup.sh` script and answer "y" when asked "Do you want to install dependencies for dev [y/N]? ". +Alternatively (if your system is not supported by the setup.sh script), follow the manual installation process and run `pip3 install -e .[all]`. This will install all required tools for development, including `pytest`, `flake8`, `mypy`, and `coveralls`. From 8f1f416a52b2381d6c2958a905eb4716dae1d037 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 30 Jul 2019 11:47:28 +0300 Subject: [PATCH 30/31] hyperopt cleanup and output improvements --- freqtrade/optimize/hyperopt.py | 65 ++++++++++++++++------------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 759ceffbe..842a111ca 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -51,7 +51,7 @@ class Hyperopt(Backtesting): self.custom_hyperoptloss = HyperOptLossResolver(self.config).hyperoptloss self.calculate_loss = self.custom_hyperoptloss.hyperopt_loss_function - self.total_tries = config.get('epochs', 0) + self.total_epochs = config.get('epochs', 0) self.current_best_loss = 100 if not self.config.get('hyperopt_continue'): @@ -124,13 +124,12 @@ class Hyperopt(Backtesting): """ results = sorted(self.trials, key=itemgetter('loss')) best_result = results[0] - logger.info( - 'Best result:\n%s\nwith values:\n', - best_result['result'] - ) + + log_str = self.format_results_logstring(best_result) + print(f"\nBest result:\n{log_str}\nwith values:") pprint(best_result['params'], indent=4) if 'roi_t1' in best_result['params']: - logger.info('ROI table:') + print("ROI table:") pprint(self.custom_hyperopt.generate_roi_table(best_result['params']), indent=4) def log_results(self, results) -> None: @@ -139,22 +138,26 @@ class Hyperopt(Backtesting): """ print_all = self.config.get('print_all', False) if print_all or results['loss'] < self.current_best_loss: - # Output human-friendly index here (starting from 1) - current = results['current_tries'] + 1 - total = results['total_tries'] - res = results['result'] - loss = results['loss'] - self.current_best_loss = results['loss'] - log_msg = f'{current:5d}/{total}: {res} Objective: {loss:.5f}' - log_msg = f'*{log_msg}' if results['initial_point'] else f' {log_msg}' + log_str = self.format_results_logstring(results) if print_all: - print(log_msg) + print(log_str) else: - print('\n' + log_msg) + print('\n' + log_str) else: print('.', end='') sys.stdout.flush() + def format_results_logstring(self, results) -> str: + # Output human-friendly index here (starting from 1) + current = results['current_epoch'] + 1 + total = self.total_epochs + res = results['results_explanation'] + loss = results['loss'] + self.current_best_loss = results['loss'] + log_str = f'{current:5d}/{total}: {res} Objective: {loss:.5f}' + log_str = f'*{log_str}' if results['is_initial_point'] else f' {log_str}' + return log_str + def has_space(self, space: str) -> bool: """ Tell if a space value is contained in the configuration @@ -214,7 +217,7 @@ class Hyperopt(Backtesting): 'end_date': max_date, } ) - result_explanation = self.format_results(results) + results_explanation = self.format_results(results) trade_count = len(results.index) @@ -226,7 +229,7 @@ class Hyperopt(Backtesting): return { 'loss': MAX_LOSS, 'params': params, - 'result': result_explanation, + 'results_explanation': results_explanation, } loss = self.calculate_loss(results=results, trade_count=trade_count, @@ -235,12 +238,12 @@ class Hyperopt(Backtesting): return { 'loss': loss, 'params': params, - 'result': result_explanation, + 'results_explanation': results_explanation, } def format_results(self, results: DataFrame) -> str: """ - Return the format result in a string + Return the formatted results explanation in a string """ trades = len(results.index) avg_profit = results.profit_percent.mean() * 100.0 @@ -323,25 +326,19 @@ class Hyperopt(Backtesting): with Parallel(n_jobs=config_jobs) as parallel: jobs = parallel._effective_n_jobs() logger.info(f'Effective number of parallel workers used: {jobs}') - EVALS = max(self.total_tries // jobs, 1) + EVALS = max(self.total_epochs // jobs, 1) for i in range(EVALS): asked = opt.ask(n_points=jobs) f_val = self.run_optimizer_parallel(parallel, asked) - opt.tell(asked, [i['loss'] for i in f_val]) - - self.trials += f_val + opt.tell(asked, [v['loss'] for v in f_val]) for j in range(jobs): current = i * jobs + j - self.log_results({ - 'loss': f_val[j]['loss'], - 'current_tries': current, - 'initial_point': current < INITIAL_POINTS, - 'total_tries': self.total_tries, - 'result': f_val[j]['result'], - }) - logger.debug(f"Optimizer params: {f_val[j]['params']}") - for j in range(jobs): - logger.debug(f"Optimizer state: Xi: {opt.Xi[-j-1]}, yi: {opt.yi[-j-1]}") + val = f_val[j] + val['current_epoch'] = current + val['is_initial_point'] = current < INITIAL_POINTS + self.log_results(val) + self.trials.append(val) + logger.debug(f"Optimizer epoch evaluated: {val}") except KeyboardInterrupt: print('User interrupted..') From b976f24672fd8f0118d94a5890925fc404998abc Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Tue, 30 Jul 2019 11:47:46 +0300 Subject: [PATCH 31/31] tests adjusted --- freqtrade/tests/optimize/test_hyperopt.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 065b4c41b..5d6128e7c 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -370,13 +370,13 @@ def test_onlyprofit_loss_prefers_higher_profits(default_conf, hyperopt_results) def test_log_results_if_loss_improves(hyperopt, capsys) -> None: hyperopt.current_best_loss = 2 + hyperopt.total_epochs = 2 hyperopt.log_results( { 'loss': 1, - 'current_tries': 1, - 'total_tries': 2, - 'result': 'foo.', - 'initial_point': False + 'current_epoch': 1, + 'results_explanation': 'foo.', + 'is_initial_point': False } ) out, err = capsys.readouterr() @@ -433,7 +433,7 @@ def test_roi_table_generation(hyperopt) -> None: assert hyperopt.custom_hyperopt.generate_roi_table(params) == {0: 6, 15: 3, 25: 1, 30: 0} -def test_start_calls_optimizer(mocker, default_conf, caplog) -> None: +def test_start_calls_optimizer(mocker, default_conf, caplog, capsys) -> None: dumper = mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock()) mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock()) mocker.patch( @@ -443,7 +443,7 @@ def test_start_calls_optimizer(mocker, default_conf, caplog) -> None: parallel = mocker.patch( 'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel', - MagicMock(return_value=[{'loss': 1, 'result': 'foo result', 'params': {}}]) + MagicMock(return_value=[{'loss': 1, 'results_explanation': 'foo result', 'params': {}}]) ) patch_exchange(mocker) @@ -457,8 +457,11 @@ def test_start_calls_optimizer(mocker, default_conf, caplog) -> None: hyperopt.strategy.tickerdata_to_dataframe = MagicMock() hyperopt.start() + parallel.assert_called_once() - assert log_has('Best result:\nfoo result\nwith values:\n', caplog.record_tuples) + + out, err = capsys.readouterr() + assert 'Best result:\n* 1/1: foo result Objective: 1.00000\nwith values:\n' in out assert dumper.called # Should be called twice, once for tickerdata, once to save evaluations assert dumper.call_count == 2 @@ -598,8 +601,8 @@ def test_generate_optimizer(mocker, default_conf) -> None: } response_expected = { 'loss': 1.9840569076926293, - 'result': ' 1 trades. Avg profit 2.31%. Total profit 0.00023300 BTC ' - '( 2.31Σ%). Avg duration 100.0 mins.', + 'results_explanation': ' 1 trades. Avg profit 2.31%. Total profit 0.00023300 BTC ' + '( 2.31Σ%). Avg duration 100.0 mins.', 'params': optimizer_param }