Simplify liquidation price calculation

This commit is contained in:
Matthias 2022-02-28 19:45:15 +01:00
parent ab46476e63
commit 79538368db
4 changed files with 22 additions and 19 deletions

View File

@ -2055,23 +2055,23 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def leverage_prep( def get_interest_rate(self) -> float:
"""
Calculate interest rate - necessary for Margin trading.
"""
return 0.0
def get_liquidation_price(
self, self,
pair: str, pair: str,
open_rate: float, open_rate: float,
amount: float, # quote currency, includes leverage amount: float, # quote currency, includes leverage
leverage: float, leverage: float,
is_short: bool is_short: bool
) -> Tuple[float, Optional[float]]: ) -> Optional[float]:
# if TradingMode == TradingMode.MARGIN: if self.trading_mode in (TradingMode.SPOT, TradingMode.MARGIN):
# interest_rate = self.get_interest_rate( return None
# pair=pair,
# open_rate=open_rate,
# is_short=is_short
# )
if self.trading_mode == TradingMode.SPOT:
return (0.0, None)
elif ( elif (
self.margin_mode == MarginMode.ISOLATED and self.margin_mode == MarginMode.ISOLATED and
self.trading_mode == TradingMode.FUTURES self.trading_mode == TradingMode.FUTURES
@ -2086,7 +2086,7 @@ class Exchange:
mm_ex_1=0.0, mm_ex_1=0.0,
upnl_ex_1=0.0, upnl_ex_1=0.0,
) )
return (0.0, isolated_liq) return isolated_liq
else: else:
raise OperationalException( raise OperationalException(
"Freqtrade only supports isolated futures for leverage trading") "Freqtrade only supports isolated futures for leverage trading")
@ -2231,7 +2231,7 @@ class Exchange:
return 0.0 return 0.0
@retrier @retrier
def get_liquidation_price( def get_or_calculate_liquidation_price(
self, self,
pair: str, pair: str,
# Dry-run # Dry-run

View File

@ -19,7 +19,7 @@ from freqtrade.edge import Edge
from freqtrade.enums import (MarginMode, RPCMessageType, RunMode, SellType, SignalDirection, State, from freqtrade.enums import (MarginMode, RPCMessageType, RunMode, SellType, SignalDirection, State,
TradingMode) TradingMode)
from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError, from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError,
InvalidOrderException, OperationalException, PricingError) InvalidOrderException, PricingError)
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.misc import safe_value_fallback, safe_value_fallback2 from freqtrade.misc import safe_value_fallback, safe_value_fallback2
from freqtrade.mixins import LoggingMixin from freqtrade.mixins import LoggingMixin
@ -688,13 +688,14 @@ class FreqtradeBot(LoggingMixin):
amount = safe_value_fallback(order, 'filled', 'amount') amount = safe_value_fallback(order, 'filled', 'amount')
enter_limit_filled_price = safe_value_fallback(order, 'average', 'price') enter_limit_filled_price = safe_value_fallback(order, 'average', 'price')
interest_rate, isolated_liq = self.exchange.leverage_prep( isolated_liq = self.exchange.get_liquidation_price(
leverage=leverage, leverage=leverage,
pair=pair, pair=pair,
amount=amount, amount=amount,
open_rate=enter_limit_filled_price, open_rate=enter_limit_filled_price,
is_short=is_short is_short=is_short
) )
interest_rate = self.exchange.get_interest_rate()
# Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker') fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker')

View File

@ -666,13 +666,16 @@ class Backtesting:
self.order_id_counter += 1 self.order_id_counter += 1
amount = round((stake_amount / propose_rate) * leverage, 8) amount = round((stake_amount / propose_rate) * leverage, 8)
is_short = (direction == 'short') is_short = (direction == 'short')
(interest_rate, isolated_liq) = self.exchange.leverage_prep( isolated_liq = self.exchange.get_liquidation_price(
pair=pair, pair=pair,
open_rate=propose_rate, open_rate=propose_rate,
amount=amount, amount=amount,
leverage=leverage, leverage=leverage,
is_short=is_short, is_short=is_short,
) )
# Necessary for Margin trading. Disabled until support is enabled.
# interest_rate = self.exchange.get_interest_rate()
if trade is None: if trade is None:
# Enter trade # Enter trade
self.trade_id_counter += 1 self.trade_id_counter += 1
@ -694,7 +697,7 @@ class Backtesting:
is_short=is_short, is_short=is_short,
trading_mode=self.trading_mode, trading_mode=self.trading_mode,
leverage=leverage, leverage=leverage,
interest_rate=interest_rate, # interest_rate=interest_rate,
orders=[], orders=[],
) )

View File

@ -4560,7 +4560,7 @@ def test__get_params(mocker, default_conf, exchange_name):
# (False, 'futures', 'okx', 'isolated', 8.085708510208207), # (False, 'futures', 'okx', 'isolated', 8.085708510208207),
] ]
) )
def test_leverage_prep( def test_get_liquidation_price(
mocker, mocker,
default_conf_usdt, default_conf_usdt,
is_short, is_short,
@ -4637,14 +4637,13 @@ def test_leverage_prep(
# default_conf_usdt.update({ # default_conf_usdt.update({
# "dry_run": False, # "dry_run": False,
# }) # })
(interest, liq) = exchange.leverage_prep( liq = exchange.get_liquidation_price(
pair='ETH/USDT:USDT', pair='ETH/USDT:USDT',
open_rate=open_rate, open_rate=open_rate,
amount=amount, amount=amount,
leverage=leverage, leverage=leverage,
is_short=is_short, is_short=is_short,
) )
assert interest == 0.0
if expected_liq is None: if expected_liq is None:
assert liq is None assert liq is None
else: else: