Log exchange responses if configured
This commit is contained in:
		| @@ -102,6 +102,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | ||||
| | `exchange.markets_refresh_interval` | The interval in minutes in which markets are reloaded. <br>*Defaults to `60` minutes.* <br> **Datatype:** Positive Integer | ||||
| | `exchange.skip_pair_validation` | Skip pairlist validation on startup.<br>*Defaults to `false`<br> **Datatype:** Boolean | ||||
| | `exchange.skip_open_order_update` | Skips open order updates on startup should the exchange cause problems. Only relevant in live conditions.<br>*Defaults to `false`<br> **Datatype:** Boolean | ||||
| | `exchange.log_responses` | Log relevant exchange responses. For debug mode only - use with care.<br>*Defaults to `false`<br> **Datatype:** Boolean | ||||
| | `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation. | ||||
| | `experimental.block_bad_exchanges` | Block exchanges known to not work with freqtrade. Leave on default unless you want to test if that exchange works now. <br>*Defaults to `true`.* <br> **Datatype:** Boolean | ||||
| | `pairlists` | Define one or more pairlists to be used. [More information](plugins.md#pairlists-and-pairlist-handlers). <br>*Defaults to `StaticPairList`.*  <br> **Datatype:** List of Dicts | ||||
|   | ||||
| @@ -68,6 +68,7 @@ class Binance(Exchange): | ||||
|                                            amount=amount, price=rate, params=params) | ||||
|             logger.info('stoploss limit order added for %s. ' | ||||
|                         'stop price: %s. limit: %s', pair, stop_price, rate) | ||||
|             self._log_exchange_response('create_stoploss_order', order) | ||||
|             return order | ||||
|         except ccxt.InsufficientFunds as e: | ||||
|             raise InsufficientFundsError( | ||||
|   | ||||
| @@ -104,6 +104,7 @@ class Exchange: | ||||
|             logger.info('Instance is running with dry_run enabled') | ||||
|         logger.info(f"Using CCXT {ccxt.__version__}") | ||||
|         exchange_config = config['exchange'] | ||||
|         self.log_responses = exchange_config.get('log_responses', False) | ||||
|  | ||||
|         # Deep merge ft_has with default ft_has options | ||||
|         self._ft_has = deep_merge_dicts(self._ft_has, deepcopy(self._ft_has_default)) | ||||
| @@ -226,6 +227,11 @@ class Exchange: | ||||
|         """exchange ccxt precisionMode""" | ||||
|         return self._api.precisionMode | ||||
|  | ||||
|     def _log_exchange_response(self, endpoint, response) -> None: | ||||
|         """ Log exchange responses """ | ||||
|         if self.log_responses: | ||||
|             logger.info(f"API {endpoint}: {response}") | ||||
|  | ||||
|     def ohlcv_candle_limit(self, timeframe: str) -> int: | ||||
|         """ | ||||
|         Exchange ohlcv candle limit | ||||
| @@ -622,8 +628,10 @@ class Exchange: | ||||
|                            or self._api.options.get("createMarketBuyOrderRequiresPrice", False)) | ||||
|             rate_for_order = self.price_to_precision(pair, rate) if needs_price else None | ||||
|  | ||||
|             return self._api.create_order(pair, ordertype, side, | ||||
|                                           amount, rate_for_order, params) | ||||
|             order = self._api.create_order(pair, ordertype, side, | ||||
|                                            amount, rate_for_order, params) | ||||
|             self._log_exchange_response('create_order', order) | ||||
|             return order | ||||
|  | ||||
|         except ccxt.InsufficientFunds as e: | ||||
|             raise InsufficientFundsError( | ||||
| @@ -694,7 +702,9 @@ class Exchange: | ||||
|         if self._config['dry_run']: | ||||
|             return self.fetch_dry_run_order(order_id) | ||||
|         try: | ||||
|             return self._api.fetch_order(order_id, pair) | ||||
|             order = self._api.fetch_order(order_id, pair) | ||||
|             self._log_exchange_response('fetch_order', order) | ||||
|             return order | ||||
|         except ccxt.OrderNotFound as e: | ||||
|             raise RetryableOrderError( | ||||
|                 f'Order not found (pair: {pair} id: {order_id}). Message: {e}') from e | ||||
| @@ -744,7 +754,9 @@ class Exchange: | ||||
|                 return {} | ||||
|  | ||||
|         try: | ||||
|             return self._api.cancel_order(order_id, pair) | ||||
|             order = self._api.cancel_order(order_id, pair) | ||||
|             self._log_exchange_response('cancel_order', order) | ||||
|             return order | ||||
|         except ccxt.InvalidOrder as e: | ||||
|             raise InvalidOrderException( | ||||
|                 f'Could not cancel order. Message: {e}') from e | ||||
| @@ -1042,6 +1054,7 @@ class Exchange: | ||||
|                 pair, int((since.replace(tzinfo=timezone.utc).timestamp() - 5) * 1000)) | ||||
|             matched_trades = [trade for trade in my_trades if trade['order'] == order_id] | ||||
|  | ||||
|             self._log_exchange_response('get_trades_for_order', matched_trades) | ||||
|             return matched_trades | ||||
|         except ccxt.DDoSProtection as e: | ||||
|             raise DDosProtection(e) from e | ||||
|   | ||||
| @@ -69,6 +69,7 @@ class Ftx(Exchange): | ||||
|  | ||||
|             order = self._api.create_order(symbol=pair, type=ordertype, side='sell', | ||||
|                                            amount=amount, params=params) | ||||
|             self._log_exchange_response('create_stoploss_order', order) | ||||
|             logger.info('stoploss order added for %s. ' | ||||
|                         'stop price: %s.', pair, stop_price) | ||||
|             return order | ||||
| @@ -99,12 +100,14 @@ class Ftx(Exchange): | ||||
|             orders = self._api.fetch_orders(pair, None, params={'type': 'stop'}) | ||||
|  | ||||
|             order = [order for order in orders if order['id'] == order_id] | ||||
|             self._log_exchange_response('fetch_stoploss_order', order) | ||||
|             if len(order) == 1: | ||||
|                 if order[0].get('status') == 'closed': | ||||
|                     # Trigger order was triggered ... | ||||
|                     real_order_id = order[0].get('info', {}).get('orderId') | ||||
|  | ||||
|                     order1 = self._api.fetch_order(real_order_id, pair) | ||||
|                     self._log_exchange_response('fetch_stoploss_order1', order1) | ||||
|                     # Fake type to stop - as this was really a stop order. | ||||
|                     order1['id_stop'] = order1['id'] | ||||
|                     order1['id'] = order_id | ||||
| @@ -131,7 +134,9 @@ class Ftx(Exchange): | ||||
|         if self._config['dry_run']: | ||||
|             return {} | ||||
|         try: | ||||
|             return self._api.cancel_order(order_id, pair, params={'type': 'stop'}) | ||||
|             order = self._api.cancel_order(order_id, pair, params={'type': 'stop'}) | ||||
|             self._log_exchange_response('cancel_stoploss_order', order) | ||||
|             return order | ||||
|         except ccxt.InvalidOrder as e: | ||||
|             raise InvalidOrderException( | ||||
|                 f'Could not cancel order. Message: {e}') from e | ||||
|   | ||||
| @@ -103,6 +103,7 @@ class Kraken(Exchange): | ||||
|  | ||||
|             order = self._api.create_order(symbol=pair, type=ordertype, side='sell', | ||||
|                                            amount=amount, price=stop_price, params=params) | ||||
|             self._log_exchange_response('create_stoploss_order', order) | ||||
|             logger.info('stoploss order added for %s. ' | ||||
|                         'stop price: %s.', pair, stop_price) | ||||
|             return order | ||||
|   | ||||
| @@ -2271,8 +2271,9 @@ def test_cancel_stoploss_order_with_result(default_conf, mocker, exchange_name): | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("exchange_name", EXCHANGES) | ||||
| def test_fetch_order(default_conf, mocker, exchange_name): | ||||
| def test_fetch_order(default_conf, mocker, exchange_name, caplog): | ||||
|     default_conf['dry_run'] = True | ||||
|     default_conf['exchange']['log_responses'] = True | ||||
|     order = MagicMock() | ||||
|     order.myid = 123 | ||||
|     exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) | ||||
| @@ -2287,6 +2288,7 @@ def test_fetch_order(default_conf, mocker, exchange_name): | ||||
|     api_mock.fetch_order = MagicMock(return_value=456) | ||||
|     exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) | ||||
|     assert exchange.fetch_order('X', 'TKN/BTC') == 456 | ||||
|     assert log_has("API fetch_order: 456", caplog) | ||||
|  | ||||
|     with pytest.raises(InvalidOrderException): | ||||
|         api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user