mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 18:23:55 +00:00
Added short functionality to exchange stoplss methods
This commit is contained in:
parent
4ac2237937
commit
6ac0ab0233
|
@ -30,8 +30,11 @@ class Binance(Exchange):
|
||||||
Returns True if adjustment is necessary.
|
Returns True if adjustment is necessary.
|
||||||
:param side: "buy" or "sell"
|
:param side: "buy" or "sell"
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Short support
|
|
||||||
return order['type'] == 'stop_loss_limit' and stop_loss > float(order['info']['stopPrice'])
|
return order['type'] == 'stop_loss_limit' and (
|
||||||
|
side == "sell" and stop_loss > float(order['info']['stopPrice']) or
|
||||||
|
side == "buy" and stop_loss < float(order['info']['stopPrice'])
|
||||||
|
)
|
||||||
|
|
||||||
@retrier(retries=0)
|
@retrier(retries=0)
|
||||||
def stoploss(self, pair: str, amount: float,
|
def stoploss(self, pair: str, amount: float,
|
||||||
|
@ -42,7 +45,6 @@ class Binance(Exchange):
|
||||||
It may work with a limited number of other exchanges, but this has not been tested yet.
|
It may work with a limited number of other exchanges, but this has not been tested yet.
|
||||||
:param side: "buy" or "sell"
|
:param side: "buy" or "sell"
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Short support
|
|
||||||
# Limit price threshold: As limit price should always be below stop-price
|
# Limit price threshold: As limit price should always be below stop-price
|
||||||
limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
|
limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
|
||||||
rate = stop_price * limit_price_pct
|
rate = stop_price * limit_price_pct
|
||||||
|
@ -51,14 +53,16 @@ class Binance(Exchange):
|
||||||
|
|
||||||
stop_price = self.price_to_precision(pair, stop_price)
|
stop_price = self.price_to_precision(pair, stop_price)
|
||||||
|
|
||||||
|
bad_stop_price = (stop_price <= rate) if side == "sell" else (stop_price >= rate)
|
||||||
|
|
||||||
# Ensure rate is less than stop price
|
# Ensure rate is less than stop price
|
||||||
if stop_price <= rate:
|
if bad_stop_price:
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
'In stoploss limit order, stop price should be more than limit price')
|
'In stoploss limit order, stop price should be better than limit price')
|
||||||
|
|
||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
dry_order = self.create_dry_run_order(
|
dry_order = self.create_dry_run_order(
|
||||||
pair, ordertype, "sell", amount, stop_price)
|
pair, ordertype, side, amount, stop_price)
|
||||||
return dry_order
|
return dry_order
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -69,7 +73,7 @@ class Binance(Exchange):
|
||||||
|
|
||||||
rate = self.price_to_precision(pair, rate)
|
rate = self.price_to_precision(pair, rate)
|
||||||
|
|
||||||
order = self._api.create_order(symbol=pair, type=ordertype, side='sell',
|
order = self._api.create_order(symbol=pair, type=ordertype, side=side,
|
||||||
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)
|
||||||
|
@ -77,21 +81,21 @@ class Binance(Exchange):
|
||||||
return order
|
return order
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise InsufficientFundsError(
|
raise InsufficientFundsError(
|
||||||
f'Insufficient funds to create {ordertype} sell order on market {pair}. '
|
f'Insufficient funds to create {ordertype} {side} order on market {pair}. '
|
||||||
f'Tried to sell amount {amount} at rate {rate}. '
|
f'Tried to {side} amount {amount} at rate {rate}. '
|
||||||
f'Message: {e}') from e
|
f'Message: {e}') from e
|
||||||
except ccxt.InvalidOrder as e:
|
except ccxt.InvalidOrder as e:
|
||||||
# Errors:
|
# Errors:
|
||||||
# `binance Order would trigger immediately.`
|
# `binance Order would trigger immediately.`
|
||||||
raise InvalidOrderException(
|
raise InvalidOrderException(
|
||||||
f'Could not create {ordertype} sell order on market {pair}. '
|
f'Could not create {ordertype} {side} order on market {pair}. '
|
||||||
f'Tried to sell amount {amount} at rate {rate}. '
|
f'Tried to {side} amount {amount} at rate {rate}. '
|
||||||
f'Message: {e}') from e
|
f'Message: {e}') from e
|
||||||
except ccxt.DDoSProtection as e:
|
except ccxt.DDoSProtection as e:
|
||||||
raise DDosProtection(e) from e
|
raise DDosProtection(e) from e
|
||||||
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
||||||
raise TemporaryError(
|
raise TemporaryError(
|
||||||
f'Could not place sell order due to {e.__class__.__name__}. Message: {e}') from e
|
f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}') from e
|
||||||
except ccxt.BaseError as e:
|
except ccxt.BaseError as e:
|
||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,10 @@ class Ftx(Exchange):
|
||||||
Verify stop_loss against stoploss-order value (limit or price)
|
Verify stop_loss against stoploss-order value (limit or price)
|
||||||
Returns True if adjustment is necessary.
|
Returns True if adjustment is necessary.
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Short support
|
return order['type'] == 'stop' and (
|
||||||
return order['type'] == 'stop' and stop_loss > float(order['price'])
|
side == "sell" and stop_loss > float(order['price']) or
|
||||||
|
side == "buy" and stop_loss < float(order['price'])
|
||||||
|
)
|
||||||
|
|
||||||
@retrier(retries=0)
|
@retrier(retries=0)
|
||||||
def stoploss(self, pair: str, amount: float,
|
def stoploss(self, pair: str, amount: float,
|
||||||
|
@ -48,7 +50,6 @@ class Ftx(Exchange):
|
||||||
|
|
||||||
Limit orders are defined by having orderPrice set, otherwise a market order is used.
|
Limit orders are defined by having orderPrice set, otherwise a market order is used.
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Short support
|
|
||||||
|
|
||||||
limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
|
limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
|
||||||
limit_rate = stop_price * limit_price_pct
|
limit_rate = stop_price * limit_price_pct
|
||||||
|
@ -59,7 +60,7 @@ class Ftx(Exchange):
|
||||||
|
|
||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
dry_order = self.create_dry_run_order(
|
dry_order = self.create_dry_run_order(
|
||||||
pair, ordertype, "sell", amount, stop_price)
|
pair, ordertype, side, amount, stop_price)
|
||||||
return dry_order
|
return dry_order
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -71,7 +72,7 @@ class Ftx(Exchange):
|
||||||
params['stopPrice'] = stop_price
|
params['stopPrice'] = stop_price
|
||||||
amount = self.amount_to_precision(pair, amount)
|
amount = self.amount_to_precision(pair, amount)
|
||||||
|
|
||||||
order = self._api.create_order(symbol=pair, type=ordertype, side='sell',
|
order = self._api.create_order(symbol=pair, type=ordertype, side=side,
|
||||||
amount=amount, params=params)
|
amount=amount, params=params)
|
||||||
self._log_exchange_response('create_stoploss_order', order)
|
self._log_exchange_response('create_stoploss_order', order)
|
||||||
logger.info('stoploss order added for %s. '
|
logger.info('stoploss order added for %s. '
|
||||||
|
@ -79,19 +80,19 @@ class Ftx(Exchange):
|
||||||
return order
|
return order
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise InsufficientFundsError(
|
raise InsufficientFundsError(
|
||||||
f'Insufficient funds to create {ordertype} sell order on market {pair}. '
|
f'Insufficient funds to create {ordertype} {side} order on market {pair}. '
|
||||||
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
||||||
f'Message: {e}') from e
|
f'Message: {e}') from e
|
||||||
except ccxt.InvalidOrder as e:
|
except ccxt.InvalidOrder as e:
|
||||||
raise InvalidOrderException(
|
raise InvalidOrderException(
|
||||||
f'Could not create {ordertype} sell order on market {pair}. '
|
f'Could not create {ordertype} {side} order on market {pair}. '
|
||||||
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
||||||
f'Message: {e}') from e
|
f'Message: {e}') from e
|
||||||
except ccxt.DDoSProtection as e:
|
except ccxt.DDoSProtection as e:
|
||||||
raise DDosProtection(e) from e
|
raise DDosProtection(e) from e
|
||||||
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
||||||
raise TemporaryError(
|
raise TemporaryError(
|
||||||
f'Could not place sell order due to {e.__class__.__name__}. Message: {e}') from e
|
f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}') from e
|
||||||
except ccxt.BaseError as e:
|
except ccxt.BaseError as e:
|
||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,10 @@ class Kraken(Exchange):
|
||||||
Verify stop_loss against stoploss-order value (limit or price)
|
Verify stop_loss against stoploss-order value (limit or price)
|
||||||
Returns True if adjustment is necessary.
|
Returns True if adjustment is necessary.
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Short support
|
return (order['type'] in ('stop-loss', 'stop-loss-limit') and (
|
||||||
return (order['type'] in ('stop-loss', 'stop-loss-limit')
|
(side == "sell" and stop_loss > float(order['price'])) or
|
||||||
and stop_loss > float(order['price']))
|
(side == "buy" and stop_loss < float(order['price']))
|
||||||
|
))
|
||||||
|
|
||||||
@ retrier(retries=0)
|
@ retrier(retries=0)
|
||||||
def stoploss(self, pair: str, amount: float,
|
def stoploss(self, pair: str, amount: float,
|
||||||
|
@ -83,7 +84,6 @@ class Kraken(Exchange):
|
||||||
Creates a stoploss market order.
|
Creates a stoploss market order.
|
||||||
Stoploss market orders is the only stoploss type supported by kraken.
|
Stoploss market orders is the only stoploss type supported by kraken.
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Short support
|
|
||||||
params = self._params.copy()
|
params = self._params.copy()
|
||||||
|
|
||||||
if order_types.get('stoploss', 'market') == 'limit':
|
if order_types.get('stoploss', 'market') == 'limit':
|
||||||
|
@ -98,13 +98,13 @@ class Kraken(Exchange):
|
||||||
|
|
||||||
if self._config['dry_run']:
|
if self._config['dry_run']:
|
||||||
dry_order = self.create_dry_run_order(
|
dry_order = self.create_dry_run_order(
|
||||||
pair, ordertype, "sell", amount, stop_price)
|
pair, ordertype, side, amount, stop_price)
|
||||||
return dry_order
|
return dry_order
|
||||||
|
|
||||||
try:
|
try:
|
||||||
amount = self.amount_to_precision(pair, amount)
|
amount = self.amount_to_precision(pair, amount)
|
||||||
|
|
||||||
order = self._api.create_order(symbol=pair, type=ordertype, side='sell',
|
order = self._api.create_order(symbol=pair, type=ordertype, side=side,
|
||||||
amount=amount, price=stop_price, params=params)
|
amount=amount, price=stop_price, params=params)
|
||||||
self._log_exchange_response('create_stoploss_order', order)
|
self._log_exchange_response('create_stoploss_order', order)
|
||||||
logger.info('stoploss order added for %s. '
|
logger.info('stoploss order added for %s. '
|
||||||
|
@ -112,19 +112,19 @@ class Kraken(Exchange):
|
||||||
return order
|
return order
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise InsufficientFundsError(
|
raise InsufficientFundsError(
|
||||||
f'Insufficient funds to create {ordertype} sell order on market {pair}. '
|
f'Insufficient funds to create {ordertype} {side} order on market {pair}. '
|
||||||
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
||||||
f'Message: {e}') from e
|
f'Message: {e}') from e
|
||||||
except ccxt.InvalidOrder as e:
|
except ccxt.InvalidOrder as e:
|
||||||
raise InvalidOrderException(
|
raise InvalidOrderException(
|
||||||
f'Could not create {ordertype} sell order on market {pair}. '
|
f'Could not create {ordertype} {side} order on market {pair}. '
|
||||||
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
|
||||||
f'Message: {e}') from e
|
f'Message: {e}') from e
|
||||||
except ccxt.DDoSProtection as e:
|
except ccxt.DDoSProtection as e:
|
||||||
raise DDosProtection(e) from e
|
raise DDosProtection(e) from e
|
||||||
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
||||||
raise TemporaryError(
|
raise TemporaryError(
|
||||||
f'Could not place sell order due to {e.__class__.__name__}. Message: {e}') from e
|
f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}') from e
|
||||||
except ccxt.BaseError as e:
|
except ccxt.BaseError as e:
|
||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
|
@ -133,7 +133,6 @@ class Kraken(Exchange):
|
||||||
Assigns property _leverage_brackets to a dictionary of information about the leverage
|
Assigns property _leverage_brackets to a dictionary of information about the leverage
|
||||||
allowed on each pair
|
allowed on each pair
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Not sure if this works correctly for futures
|
|
||||||
leverages = {}
|
leverages = {}
|
||||||
try:
|
try:
|
||||||
for pair, market in self._api.load_markets().items():
|
for pair, market in self._api.load_markets().items():
|
||||||
|
|
|
@ -499,7 +499,6 @@ class LocalTrade():
|
||||||
lower_stop = new_loss < self.stop_loss
|
lower_stop = new_loss < self.stop_loss
|
||||||
|
|
||||||
# stop losses only walk up, never down!,
|
# stop losses only walk up, never down!,
|
||||||
# TODO-lev
|
|
||||||
# ? But adding more to a leveraged trade would create a lower liquidation price,
|
# ? But adding more to a leveraged trade would create a lower liquidation price,
|
||||||
# ? decreasing the minimum stoploss
|
# ? decreasing the minimum stoploss
|
||||||
if (higher_stop and not self.is_short) or (lower_stop and self.is_short):
|
if (higher_stop and not self.is_short) or (lower_stop and self.is_short):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user