Merge pull request #3676 from freqtrade/stoploss_remove_unused_argument

[minor] Cleanup and exception hierarchy documentation
This commit is contained in:
Matthias 2020-08-14 07:11:56 +02:00 committed by GitHub
commit 22f6e884ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 26 deletions

View File

@ -85,6 +85,35 @@ docker-compose exec freqtrade_develop /bin/bash
![image](https://user-images.githubusercontent.com/419355/65456522-ba671a80-de06-11e9-9598-df9ca0d8dcac.png) ![image](https://user-images.githubusercontent.com/419355/65456522-ba671a80-de06-11e9-9598-df9ca0d8dcac.png)
## ErrorHandling
Freqtrade Exceptions all inherit from `FreqtradeException`.
This general class of error should however not be used directly. Instead, multiple specialized sub-Exceptions exist.
Below is an outline of exception inheritance hierarchy:
```
+ FreqtradeException
|
+---+ OperationalException
|
+---+ DependencyException
| |
| +---+ PricingError
| |
| +---+ ExchangeError
| |
| +---+ TemporaryError
| |
| +---+ DDosProtection
| |
| +---+ InvalidOrderException
| |
| +---+ RetryableOrderError
|
+---+ StrategyError
```
## Modules ## Modules
### Dynamic Pairlist ### Dynamic Pairlist

View File

@ -29,7 +29,14 @@ class PricingError(DependencyException):
""" """
class InvalidOrderException(FreqtradeException): class ExchangeError(DependencyException):
"""
Error raised out of the exchange.
Has multiple Errors to determine the appropriate error.
"""
class InvalidOrderException(ExchangeError):
""" """
This is returned when the order is not valid. Example: This is returned when the order is not valid. Example:
If stoploss on exchange order is hit, then trying to cancel the order If stoploss on exchange order is hit, then trying to cancel the order
@ -44,13 +51,6 @@ class RetryableOrderError(InvalidOrderException):
""" """
class ExchangeError(DependencyException):
"""
Error raised out of the exchange.
Has multiple Errors to determine the appropriate error.
"""
class TemporaryError(ExchangeError): class TemporaryError(ExchangeError):
""" """
Temporary network or exchange related error. Temporary network or exchange related error.

View File

@ -975,7 +975,7 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
# Assign method to fetch_stoploss_order to allow easy overriding in other classes # Assign method to cancel_stoploss_order to allow easy overriding in other classes
cancel_stoploss_order = cancel_order cancel_stoploss_order = cancel_order
def is_cancel_order_result_suitable(self, corder) -> bool: def is_cancel_order_result_suitable(self, corder) -> bool:
@ -1041,10 +1041,10 @@ class Exchange:
@retrier @retrier
def fetch_l2_order_book(self, pair: str, limit: int = 100) -> dict: def fetch_l2_order_book(self, pair: str, limit: int = 100) -> dict:
""" """
get order book level 2 from exchange Get L2 order book from exchange.
Can be limited to a certain amount (if supported).
Notes: Returns a dict in the format
20180619: bittrex doesnt support limits -.- {'asks': [price, volume], 'bids': [price, volume]}
""" """
try: try:

View File

@ -770,7 +770,7 @@ class FreqtradeBot:
logger.debug('Found no sell signal for %s.', trade) logger.debug('Found no sell signal for %s.', trade)
return False return False
def create_stoploss_order(self, trade: Trade, stop_price: float, rate: float) -> bool: def create_stoploss_order(self, trade: Trade, stop_price: float) -> bool:
""" """
Abstracts creating stoploss orders from the logic. Abstracts creating stoploss orders from the logic.
Handles errors and updates the trade database object. Handles errors and updates the trade database object.
@ -833,14 +833,13 @@ class FreqtradeBot:
stoploss = self.edge.stoploss(pair=trade.pair) if self.edge else self.strategy.stoploss stoploss = self.edge.stoploss(pair=trade.pair) if self.edge else self.strategy.stoploss
stop_price = trade.open_rate * (1 + stoploss) stop_price = trade.open_rate * (1 + stoploss)
if self.create_stoploss_order(trade=trade, stop_price=stop_price, rate=stop_price): if self.create_stoploss_order(trade=trade, stop_price=stop_price):
trade.stoploss_last_update = datetime.now() trade.stoploss_last_update = datetime.now()
return False return False
# If stoploss order is canceled for some reason we add it # If stoploss order is canceled for some reason we add it
if stoploss_order and stoploss_order['status'] in ('canceled', 'cancelled'): if stoploss_order and stoploss_order['status'] in ('canceled', 'cancelled'):
if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss, if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss):
rate=trade.stop_loss):
return False return False
else: else:
trade.stoploss_order_id = None trade.stoploss_order_id = None
@ -877,8 +876,7 @@ class FreqtradeBot:
f"for pair {trade.pair}") f"for pair {trade.pair}")
# Create new stoploss order # Create new stoploss order
if not self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss, if not self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss):
rate=trade.stop_loss):
logger.warning(f"Could not create trailing stoploss order " logger.warning(f"Could not create trailing stoploss order "
f"for pair {trade.pair}.") f"for pair {trade.pair}.")
@ -923,7 +921,7 @@ class FreqtradeBot:
if not trade.open_order_id: if not trade.open_order_id:
continue continue
order = self.exchange.fetch_order(trade.open_order_id, trade.pair) order = self.exchange.fetch_order(trade.open_order_id, trade.pair)
except (ExchangeError, InvalidOrderException): except (ExchangeError):
logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc()) logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc())
continue continue
@ -956,7 +954,7 @@ class FreqtradeBot:
for trade in Trade.get_open_order_trades(): for trade in Trade.get_open_order_trades():
try: try:
order = self.exchange.fetch_order(trade.open_order_id, trade.pair) order = self.exchange.fetch_order(trade.open_order_id, trade.pair)
except (DependencyException, InvalidOrderException): except (ExchangeError):
logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc()) logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc())
continue continue

View File

@ -11,7 +11,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union
import arrow import arrow
from numpy import NAN, mean from numpy import NAN, mean
from freqtrade.exceptions import (ExchangeError, InvalidOrderException, from freqtrade.exceptions import (ExchangeError,
PricingError) PricingError)
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs
from freqtrade.misc import shorten_date from freqtrade.misc import shorten_date
@ -555,7 +555,7 @@ class RPC:
try: try:
self._freqtrade.exchange.cancel_order(trade.open_order_id, trade.pair) self._freqtrade.exchange.cancel_order(trade.open_order_id, trade.pair)
c_count += 1 c_count += 1
except (ExchangeError, InvalidOrderException): except (ExchangeError):
pass pass
# cancel stoploss on exchange ... # cancel stoploss on exchange ...
@ -565,7 +565,7 @@ class RPC:
self._freqtrade.exchange.cancel_stoploss_order(trade.stoploss_order_id, self._freqtrade.exchange.cancel_stoploss_order(trade.stoploss_order_id,
trade.pair) trade.pair)
c_count += 1 c_count += 1
except (ExchangeError, InvalidOrderException): except (ExchangeError):
pass pass
Trade.session.delete(trade) Trade.session.delete(trade)

View File

@ -1301,7 +1301,7 @@ def test_create_stoploss_order_invalid_order(mocker, default_conf, caplog, fee,
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.query.first() trade = Trade.query.first()
caplog.clear() caplog.clear()
freqtrade.create_stoploss_order(trade, 200, 199) freqtrade.create_stoploss_order(trade, 200)
assert trade.stoploss_order_id is None assert trade.stoploss_order_id is None
assert trade.sell_reason == SellType.EMERGENCY_SELL.value assert trade.sell_reason == SellType.EMERGENCY_SELL.value
assert log_has("Unable to place a stoploss order on exchange. ", caplog) assert log_has("Unable to place a stoploss order on exchange. ", caplog)
@ -4107,7 +4107,7 @@ def test_sync_wallet_dry_run(mocker, default_conf, ticker, fee, limit_buy_order,
def test_cancel_all_open_orders(mocker, default_conf, fee, limit_buy_order, limit_sell_order): def test_cancel_all_open_orders(mocker, default_conf, fee, limit_buy_order, limit_sell_order):
default_conf['cancel_open_orders_on_exit'] = True default_conf['cancel_open_orders_on_exit'] = True
mocker.patch('freqtrade.exchange.Exchange.fetch_order', mocker.patch('freqtrade.exchange.Exchange.fetch_order',
side_effect=[DependencyException(), limit_sell_order, limit_buy_order]) side_effect=[ExchangeError(), limit_sell_order, limit_buy_order])
buy_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_buy') buy_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_buy')
sell_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_sell') sell_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_sell')