Log exchange responses if configured
This commit is contained in:
parent
e40d481d09
commit
39b876e37a
@ -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.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_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.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.
|
| `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
|
| `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
|
| `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)
|
amount=amount, price=rate, params=params)
|
||||||
logger.info('stoploss limit order added for %s. '
|
logger.info('stoploss limit order added for %s. '
|
||||||
'stop price: %s. limit: %s', pair, stop_price, rate)
|
'stop price: %s. limit: %s', pair, stop_price, rate)
|
||||||
|
self._log_exchange_response('create_stoploss_order', order)
|
||||||
return order
|
return order
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise InsufficientFundsError(
|
raise InsufficientFundsError(
|
||||||
|
@ -104,6 +104,7 @@ class Exchange:
|
|||||||
logger.info('Instance is running with dry_run enabled')
|
logger.info('Instance is running with dry_run enabled')
|
||||||
logger.info(f"Using CCXT {ccxt.__version__}")
|
logger.info(f"Using CCXT {ccxt.__version__}")
|
||||||
exchange_config = config['exchange']
|
exchange_config = config['exchange']
|
||||||
|
self.log_responses = exchange_config.get('log_responses', False)
|
||||||
|
|
||||||
# Deep merge ft_has with default ft_has options
|
# Deep merge ft_has with default ft_has options
|
||||||
self._ft_has = deep_merge_dicts(self._ft_has, deepcopy(self._ft_has_default))
|
self._ft_has = deep_merge_dicts(self._ft_has, deepcopy(self._ft_has_default))
|
||||||
@ -226,6 +227,11 @@ class Exchange:
|
|||||||
"""exchange ccxt precisionMode"""
|
"""exchange ccxt precisionMode"""
|
||||||
return self._api.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:
|
def ohlcv_candle_limit(self, timeframe: str) -> int:
|
||||||
"""
|
"""
|
||||||
Exchange ohlcv candle limit
|
Exchange ohlcv candle limit
|
||||||
@ -622,8 +628,10 @@ class Exchange:
|
|||||||
or self._api.options.get("createMarketBuyOrderRequiresPrice", False))
|
or self._api.options.get("createMarketBuyOrderRequiresPrice", False))
|
||||||
rate_for_order = self.price_to_precision(pair, rate) if needs_price else None
|
rate_for_order = self.price_to_precision(pair, rate) if needs_price else None
|
||||||
|
|
||||||
return self._api.create_order(pair, ordertype, side,
|
order = self._api.create_order(pair, ordertype, side,
|
||||||
amount, rate_for_order, params)
|
amount, rate_for_order, params)
|
||||||
|
self._log_exchange_response('create_order', order)
|
||||||
|
return order
|
||||||
|
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise InsufficientFundsError(
|
raise InsufficientFundsError(
|
||||||
@ -694,7 +702,9 @@ class Exchange:
|
|||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
return self.fetch_dry_run_order(order_id)
|
return self.fetch_dry_run_order(order_id)
|
||||||
try:
|
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:
|
except ccxt.OrderNotFound as e:
|
||||||
raise RetryableOrderError(
|
raise RetryableOrderError(
|
||||||
f'Order not found (pair: {pair} id: {order_id}). Message: {e}') from e
|
f'Order not found (pair: {pair} id: {order_id}). Message: {e}') from e
|
||||||
@ -744,7 +754,9 @@ class Exchange:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
try:
|
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:
|
except ccxt.InvalidOrder as e:
|
||||||
raise InvalidOrderException(
|
raise InvalidOrderException(
|
||||||
f'Could not cancel order. Message: {e}') from e
|
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))
|
pair, int((since.replace(tzinfo=timezone.utc).timestamp() - 5) * 1000))
|
||||||
matched_trades = [trade for trade in my_trades if trade['order'] == order_id]
|
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
|
return matched_trades
|
||||||
except ccxt.DDoSProtection as e:
|
except ccxt.DDoSProtection as e:
|
||||||
raise DDosProtection(e) from e
|
raise DDosProtection(e) from e
|
||||||
|
@ -69,6 +69,7 @@ class Ftx(Exchange):
|
|||||||
|
|
||||||
order = self._api.create_order(symbol=pair, type=ordertype, side='sell',
|
order = self._api.create_order(symbol=pair, type=ordertype, side='sell',
|
||||||
amount=amount, params=params)
|
amount=amount, params=params)
|
||||||
|
self._log_exchange_response('create_stoploss_order', order)
|
||||||
logger.info('stoploss order added for %s. '
|
logger.info('stoploss order added for %s. '
|
||||||
'stop price: %s.', pair, stop_price)
|
'stop price: %s.', pair, stop_price)
|
||||||
return order
|
return order
|
||||||
@ -99,12 +100,14 @@ class Ftx(Exchange):
|
|||||||
orders = self._api.fetch_orders(pair, None, params={'type': 'stop'})
|
orders = self._api.fetch_orders(pair, None, params={'type': 'stop'})
|
||||||
|
|
||||||
order = [order for order in orders if order['id'] == order_id]
|
order = [order for order in orders if order['id'] == order_id]
|
||||||
|
self._log_exchange_response('fetch_stoploss_order', order)
|
||||||
if len(order) == 1:
|
if len(order) == 1:
|
||||||
if order[0].get('status') == 'closed':
|
if order[0].get('status') == 'closed':
|
||||||
# Trigger order was triggered ...
|
# Trigger order was triggered ...
|
||||||
real_order_id = order[0].get('info', {}).get('orderId')
|
real_order_id = order[0].get('info', {}).get('orderId')
|
||||||
|
|
||||||
order1 = self._api.fetch_order(real_order_id, pair)
|
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.
|
# Fake type to stop - as this was really a stop order.
|
||||||
order1['id_stop'] = order1['id']
|
order1['id_stop'] = order1['id']
|
||||||
order1['id'] = order_id
|
order1['id'] = order_id
|
||||||
@ -131,7 +134,9 @@ class Ftx(Exchange):
|
|||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
return {}
|
return {}
|
||||||
try:
|
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:
|
except ccxt.InvalidOrder as e:
|
||||||
raise InvalidOrderException(
|
raise InvalidOrderException(
|
||||||
f'Could not cancel order. Message: {e}') from e
|
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',
|
order = self._api.create_order(symbol=pair, type=ordertype, side='sell',
|
||||||
amount=amount, price=stop_price, params=params)
|
amount=amount, price=stop_price, params=params)
|
||||||
|
self._log_exchange_response('create_stoploss_order', order)
|
||||||
logger.info('stoploss order added for %s. '
|
logger.info('stoploss order added for %s. '
|
||||||
'stop price: %s.', pair, stop_price)
|
'stop price: %s.', pair, stop_price)
|
||||||
return order
|
return order
|
||||||
|
@ -2271,8 +2271,9 @@ def test_cancel_stoploss_order_with_result(default_conf, mocker, exchange_name):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
@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['dry_run'] = True
|
||||||
|
default_conf['exchange']['log_responses'] = True
|
||||||
order = MagicMock()
|
order = MagicMock()
|
||||||
order.myid = 123
|
order.myid = 123
|
||||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
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)
|
api_mock.fetch_order = MagicMock(return_value=456)
|
||||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||||
assert exchange.fetch_order('X', 'TKN/BTC') == 456
|
assert exchange.fetch_order('X', 'TKN/BTC') == 456
|
||||||
|
assert log_has("API fetch_order: 456", caplog)
|
||||||
|
|
||||||
with pytest.raises(InvalidOrderException):
|
with pytest.raises(InvalidOrderException):
|
||||||
api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
||||||
|
Loading…
Reference in New Issue
Block a user