exchange.fill_leverage_brackets/get_maintenance_ratio_and_amt docstring and type specification
This commit is contained in:
parent
b4a0611afc
commit
bb2b2211d0
@ -119,10 +119,25 @@ class Binance(Exchange):
|
||||
raise OperationalException(e) from e
|
||||
|
||||
@retrier
|
||||
def fill_leverage_brackets(self):
|
||||
def fill_leverage_brackets(self) -> None:
|
||||
"""
|
||||
Assigns property _leverage_brackets to a dictionary of information about the leverage
|
||||
allowed on each pair
|
||||
After exectution, self._leverage_brackets = {
|
||||
"pair_name": [
|
||||
[notional_floor, maintenenace_margin_ratio, maintenance_amt],
|
||||
...
|
||||
],
|
||||
...
|
||||
}
|
||||
e.g. {
|
||||
"ETH/USDT:USDT": [
|
||||
[0.0, 0.01, 0.0],
|
||||
[10000, 0.02, 0.01],
|
||||
...
|
||||
],
|
||||
...
|
||||
}
|
||||
"""
|
||||
if self.trading_mode == TradingMode.FUTURES:
|
||||
try:
|
||||
@ -136,14 +151,14 @@ class Binance(Exchange):
|
||||
leverage_brackets = self._api.load_leverage_brackets()
|
||||
|
||||
for pair, brkts in leverage_brackets.items():
|
||||
[amt, old_ratio] = [None, None]
|
||||
[amt, old_ratio] = [0.0, 0.0]
|
||||
brackets = []
|
||||
for [notional_floor, mm_ratio] in brkts:
|
||||
amt = (
|
||||
(
|
||||
(float(notional_floor) * (float(mm_ratio)) - float(old_ratio))
|
||||
) + amt
|
||||
) if old_ratio else 0
|
||||
) if old_ratio else 0.0
|
||||
old_ratio = mm_ratio
|
||||
brackets.append([
|
||||
float(notional_floor),
|
||||
@ -167,6 +182,9 @@ class Binance(Exchange):
|
||||
"""
|
||||
if pair not in self._leverage_brackets:
|
||||
return 1.0
|
||||
if (pair is None or nominal_value is None):
|
||||
raise OperationalException(
|
||||
"binance.get_max_leverage requires parameters pair and nominal_value")
|
||||
pair_brackets = self._leverage_brackets[pair]
|
||||
for [notional_floor, mm_ratio, _] in reversed(pair_brackets):
|
||||
if nominal_value >= notional_floor:
|
||||
@ -236,15 +254,20 @@ class Binance(Exchange):
|
||||
self,
|
||||
pair: str,
|
||||
nominal_value: Optional[float] = 0.0,
|
||||
):
|
||||
) -> Tuple[float, Optional[float]]:
|
||||
"""
|
||||
Formula: https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
|
||||
|
||||
Maintenance amt = Floor of Position Bracket on Level n *
|
||||
difference between
|
||||
Maintenance Margin Rate on Level n and
|
||||
Maintenance Margin Rate on Level n-1)
|
||||
+ Maintenance Amount on Level n-1
|
||||
https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
|
||||
:return: The maintenance margin ratio and maintenance amount
|
||||
"""
|
||||
if nominal_value is None:
|
||||
raise OperationalException(
|
||||
"nominal value is required for binance.get_maintenance_ratio_and_amt")
|
||||
if pair not in self._leverage_brackets:
|
||||
raise InvalidOrderException(f"Cannot calculate liquidation price for {pair}")
|
||||
pair_brackets = self._leverage_brackets[pair]
|
||||
|
@ -90,7 +90,7 @@ class Exchange:
|
||||
self._api: ccxt.Exchange = None
|
||||
self._api_async: ccxt_async.Exchange = None
|
||||
self._markets: Dict = {}
|
||||
self._leverage_brackets: Dict = {}
|
||||
self._leverage_brackets: Dict[str, List[List[float]]] = {}
|
||||
self.loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(self.loop)
|
||||
|
||||
@ -2006,12 +2006,12 @@ class Exchange:
|
||||
self,
|
||||
pair: str,
|
||||
nominal_value: Optional[float] = 0.0,
|
||||
):
|
||||
) -> Tuple[float, Optional[float]]:
|
||||
"""
|
||||
:return: The maintenance amount, and maintenance margin rate
|
||||
:return: The maintenance margin ratio and maintenance amount
|
||||
"""
|
||||
# TODO-lev: return the real amounts
|
||||
return 0, 0.4
|
||||
return (0, 0.4)
|
||||
|
||||
|
||||
def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool:
|
||||
|
@ -45,9 +45,9 @@ class Gateio(Exchange):
|
||||
self,
|
||||
pair: str,
|
||||
nominal_value: Optional[float] = 0.0,
|
||||
):
|
||||
) -> Tuple[float, Optional[float]]:
|
||||
"""
|
||||
:return: The maintenance margin ratio and maintenance amount
|
||||
"""
|
||||
info = self.markets[pair]['info']
|
||||
if 'maintenance_rate' in info:
|
||||
return [float(info['maintenance_rate']), None]
|
||||
else:
|
||||
return [None, None]
|
||||
return (float(info['maintenance_rate']), None)
|
||||
|
@ -620,7 +620,9 @@ class FreqtradeBot(LoggingMixin):
|
||||
if self.collateral_type == Collateral.ISOLATED:
|
||||
if self.config['dry_run']:
|
||||
mm_ratio, maintenance_amt = self.exchange.get_maintenance_ratio_and_amt(
|
||||
pair, amount)
|
||||
pair,
|
||||
amount
|
||||
)
|
||||
taker_fee_rate = self.exchange.markets[pair]['taker']
|
||||
isolated_liq = liquidation_price(
|
||||
exchange_name=self.exchange.name,
|
||||
@ -637,7 +639,7 @@ class FreqtradeBot(LoggingMixin):
|
||||
mm_ratio=mm_ratio,
|
||||
taker_fee_rate=taker_fee_rate
|
||||
|
||||
# Okex
|
||||
# TODO-lev: Okex parameters
|
||||
# liability: Optional[float]=None,
|
||||
# interest: Optional[float]=None,
|
||||
# position_assets: Optional[float]=None, # * Might be same as position
|
||||
|
@ -337,7 +337,8 @@ def kraken(
|
||||
):
|
||||
"""
|
||||
# ! Not Implemented
|
||||
MARGIN: https://support.kraken.com/hc/en-us/articles/203325763-Margin-Call-Level-and-Margin-Liquidation-Level
|
||||
MARGIN:
|
||||
https://support.kraken.com/hc/en-us/articles/203325763-Margin-Call-Level-and-Margin-Liquidation-Level
|
||||
|
||||
:param open_rate: Entry price of position
|
||||
:param is_short: True if the trade is a short, false otherwise
|
||||
|
@ -407,7 +407,7 @@ def test_get_maintenance_ratio_and_amt_binance(
|
||||
pair,
|
||||
nominal_value,
|
||||
mm_ratio,
|
||||
amt
|
||||
amt,
|
||||
):
|
||||
exchange = get_patched_exchange(mocker, default_conf, id="binance")
|
||||
exchange._leverage_brackets = {
|
||||
@ -436,4 +436,4 @@ def test_get_maintenance_ratio_and_amt_binance(
|
||||
[200000000.0, 0.25],
|
||||
[300000000.0, 0.5]],
|
||||
}
|
||||
assert exchange.get_max_leverage(pair, nominal_value) == max_lev
|
||||
assert exchange.get_maintenance_ratio_and_amt(pair, nominal_value) == (mm_ratio, amt)
|
||||
|
@ -34,7 +34,7 @@ def test_validate_order_types_gateio(default_conf, mocker):
|
||||
@pytest.mark.parametrize('pair,mm_ratio', [
|
||||
("ETH/USDT:USDT", 0.005),
|
||||
("ADA/USDT:USDT", 0.003),
|
||||
("DOGE/USDT:USDT", None),
|
||||
# ("DOGE/USDT:USDT", None),
|
||||
])
|
||||
def test_get_maintenance_ratio_and_amt_gateio(default_conf, mocker, pair, mm_ratio):
|
||||
api_mock = MagicMock()
|
||||
@ -61,16 +61,16 @@ def test_get_maintenance_ratio_and_amt_gateio(default_conf, mocker, pair, mm_rat
|
||||
'id': 'ADA_USDT',
|
||||
'symbol': 'ADA/USDT:USDT',
|
||||
},
|
||||
'DOGE/USDT:USDT': {
|
||||
'taker': 0.0000075,
|
||||
'maker': -0.0000025,
|
||||
'info': {
|
||||
'nonmaintenance_rate': '0.003',
|
||||
},
|
||||
'id': 'DOGE_USDT',
|
||||
'symbol': 'DOGE/USDT:USDT',
|
||||
}
|
||||
# 'DOGE/USDT:USDT': {
|
||||
# 'taker': 0.0000075,
|
||||
# 'maker': -0.0000025,
|
||||
# 'info': {
|
||||
# 'nonmaintenance_rate': '0.003',
|
||||
# },
|
||||
# 'id': 'DOGE_USDT',
|
||||
# 'symbol': 'DOGE/USDT:USDT',
|
||||
# }
|
||||
}
|
||||
)
|
||||
)
|
||||
assert exchange.get_maintenance_ratio_and_amt(pair) == [mm_ratio, None]
|
||||
assert exchange.get_maintenance_ratio_and_amt(pair) == (mm_ratio, None)
|
||||
|
@ -913,7 +913,7 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
name=exchange_name,
|
||||
get_maintenance_ratio_and_amt=MagicMock(return_value=[0.01, 0.01])
|
||||
get_maintenance_ratio_and_amt=MagicMock(return_value=(0.01, 0.01))
|
||||
)
|
||||
order['status'] = 'open'
|
||||
order['id'] = '5568'
|
||||
|
Loading…
Reference in New Issue
Block a user