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() 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/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) 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, diff --git a/requirements-common.txt b/requirements-common.txt index 409c979b5..3cf34ad61 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.860 -SQLAlchemy==1.3.5 +ccxt==1.18.965 +SQLAlchemy==1.3.6 python-telegram-bot==11.1.0 arrow==0.14.2 cachetools==3.1.1 @@ -29,4 +29,4 @@ python-rapidjson==0.7.2 sdnotify==0.3.2 # Api server -flask==1.0.3 +flask==1.1.1 diff --git a/requirements-dev.txt b/requirements-dev.txt index 83fec3b8a..946d63039 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,13 +2,13 @@ -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 +pytest==5.0.1 pytest-mock==1.10.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 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 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