mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-13 03:33:55 +00:00
test_execute_entry liquidation_price test test_get_maintenance_ratio_and_amt_gateio
This commit is contained in:
parent
2d545a2def
commit
387a9fbf36
|
@ -155,7 +155,7 @@ CONF_SCHEMA = {
|
||||||
'ignore_roi_if_buy_signal': {'type': 'boolean'},
|
'ignore_roi_if_buy_signal': {'type': 'boolean'},
|
||||||
'ignore_buying_expired_candle_after': {'type': 'number'},
|
'ignore_buying_expired_candle_after': {'type': 'number'},
|
||||||
'trading_mode': {'type': 'string', 'enum': TRADING_MODES},
|
'trading_mode': {'type': 'string', 'enum': TRADING_MODES},
|
||||||
'collateral_type': {'type': 'string', 'enum': COLLATERAL_TYPES},
|
'collateral': {'type': 'string', 'enum': COLLATERAL_TYPES},
|
||||||
'backtest_breakdown': {
|
'backtest_breakdown': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {'type': 'string', 'enum': BACKTEST_BREAKDOWNS}
|
'items': {'type': 'string', 'enum': BACKTEST_BREAKDOWNS}
|
||||||
|
|
|
@ -107,8 +107,8 @@ class FreqtradeBot(LoggingMixin):
|
||||||
self.trading_mode = TradingMode(self.config.get('trading_mode', 'spot'))
|
self.trading_mode = TradingMode(self.config.get('trading_mode', 'spot'))
|
||||||
|
|
||||||
self.collateral_type: Optional[Collateral] = None
|
self.collateral_type: Optional[Collateral] = None
|
||||||
if 'collateral_type' in self.config:
|
if 'collateral' in self.config:
|
||||||
self.collateral_type = Collateral(self.config['collateral_type'])
|
self.collateral_type = Collateral(self.config['collateral'])
|
||||||
|
|
||||||
self._schedule = Scheduler()
|
self._schedule = Scheduler()
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,8 @@ def liquidation_price(
|
||||||
trading_mode=trading_mode,
|
trading_mode=trading_mode,
|
||||||
collateral=collateral, # type: ignore
|
collateral=collateral, # type: ignore
|
||||||
wallet_balance=wallet_balance,
|
wallet_balance=wallet_balance,
|
||||||
# mm_ex_1=mm_ex_1,
|
mm_ex_1=mm_ex_1, # type: ignore
|
||||||
# upnl_ex_1=upnl_ex_1,
|
upnl_ex_1=upnl_ex_1, # type: ignore
|
||||||
maintenance_amt=maintenance_amt, # type: ignore
|
maintenance_amt=maintenance_amt, # type: ignore
|
||||||
position=position,
|
position=position,
|
||||||
mm_ratio=mm_ratio,
|
mm_ratio=mm_ratio,
|
||||||
|
@ -212,7 +212,6 @@ def binance(
|
||||||
:param open_rate: Entry Price of position (one-way mode)
|
:param open_rate: Entry Price of position (one-way mode)
|
||||||
:param mm_ratio: Maintenance margin rate of position (one-way mode)
|
:param mm_ratio: Maintenance margin rate of position (one-way mode)
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Additional arguments, fill in formulas
|
|
||||||
wb = wallet_balance
|
wb = wallet_balance
|
||||||
tmm_1 = 0.0 if collateral == Collateral.ISOLATED else mm_ex_1
|
tmm_1 = 0.0 if collateral == Collateral.ISOLATED else mm_ex_1
|
||||||
upnl_1 = 0.0 if collateral == Collateral.ISOLATED else upnl_ex_1
|
upnl_1 = 0.0 if collateral == Collateral.ISOLATED else upnl_ex_1
|
||||||
|
@ -223,7 +222,6 @@ def binance(
|
||||||
mmr_b = mm_ratio
|
mmr_b = mm_ratio
|
||||||
|
|
||||||
if trading_mode == TradingMode.MARGIN and collateral == Collateral.CROSS:
|
if trading_mode == TradingMode.MARGIN and collateral == Collateral.CROSS:
|
||||||
# TODO-lev: perform a calculation based on this formula
|
|
||||||
# https://www.binance.com/en/support/faq/f6b010588e55413aa58b7d63ee0125ed
|
# https://www.binance.com/en/support/faq/f6b010588e55413aa58b7d63ee0125ed
|
||||||
exception("binance", trading_mode, collateral)
|
exception("binance", trading_mode, collateral)
|
||||||
elif trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED:
|
elif trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED:
|
||||||
|
@ -235,11 +233,11 @@ def binance(
|
||||||
position * mmr_b - side_1 * position)
|
position * mmr_b - side_1 * position)
|
||||||
|
|
||||||
elif trading_mode == TradingMode.FUTURES and collateral == Collateral.CROSS:
|
elif trading_mode == TradingMode.FUTURES and collateral == Collateral.CROSS:
|
||||||
# TODO-lev: perform a calculation based on this formula
|
|
||||||
# https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
|
# https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
|
||||||
# Liquidation Price of USDⓈ-M Futures Contracts Cross
|
# Liquidation Price of USDⓈ-M Futures Contracts Cross
|
||||||
|
|
||||||
# Isolated margin mode, then TMM=0,UPNL=0
|
# Isolated margin mode, then TMM=0,UPNL=0
|
||||||
|
# * Untested
|
||||||
return (wb - tmm_1 + upnl_1 + cum_b - side_1 * position * ep1) / (
|
return (wb - tmm_1 + upnl_1 + cum_b - side_1 * position * ep1) / (
|
||||||
position * mmr_b - side_1 * position)
|
position * mmr_b - side_1 * position)
|
||||||
|
|
||||||
|
@ -253,18 +251,17 @@ def kraken(
|
||||||
leverage: float,
|
leverage: float,
|
||||||
trading_mode: TradingMode,
|
trading_mode: TradingMode,
|
||||||
collateral: Collateral
|
collateral: Collateral
|
||||||
|
# ...
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Calculates the liquidation price on Kraken
|
Calculates the liquidation price on Kraken
|
||||||
:param trading_mode: spot, margin, futures
|
:param trading_mode: spot, margin, futures
|
||||||
:param collateral: cross, isolated
|
:param collateral: cross, isolated
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Additional arguments, fill in formulas
|
|
||||||
|
|
||||||
if collateral == Collateral.CROSS:
|
if collateral == Collateral.CROSS:
|
||||||
if trading_mode == TradingMode.MARGIN:
|
if trading_mode == TradingMode.MARGIN:
|
||||||
exception("kraken", trading_mode, collateral)
|
exception("kraken", trading_mode, collateral)
|
||||||
# TODO-lev: perform a calculation based on this formula
|
|
||||||
# https://support.kraken.com/hc/en-us/articles/203325763-Margin-Call-Level-and-Margin-Liquidation-Level
|
# https://support.kraken.com/hc/en-us/articles/203325763-Margin-Call-Level-and-Margin-Liquidation-Level
|
||||||
elif trading_mode == TradingMode.FUTURES:
|
elif trading_mode == TradingMode.FUTURES:
|
||||||
exception("kraken", trading_mode, collateral)
|
exception("kraken", trading_mode, collateral)
|
||||||
|
@ -279,6 +276,7 @@ def ftx(
|
||||||
leverage: float,
|
leverage: float,
|
||||||
trading_mode: TradingMode,
|
trading_mode: TradingMode,
|
||||||
collateral: Collateral
|
collateral: Collateral
|
||||||
|
# ...
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Calculates the liquidation price on FTX
|
Calculates the liquidation price on FTX
|
||||||
|
@ -286,7 +284,6 @@ def ftx(
|
||||||
:param collateral: cross, isolated
|
:param collateral: cross, isolated
|
||||||
"""
|
"""
|
||||||
if collateral == Collateral.CROSS:
|
if collateral == Collateral.CROSS:
|
||||||
# TODO-lev: Additional arguments, fill in formulas
|
|
||||||
exception("ftx", trading_mode, collateral)
|
exception("ftx", trading_mode, collateral)
|
||||||
|
|
||||||
# If nothing was returned
|
# If nothing was returned
|
||||||
|
|
|
@ -823,6 +823,8 @@ def get_markets():
|
||||||
'margin': True,
|
'margin': True,
|
||||||
'type': 'spot',
|
'type': 'spot',
|
||||||
'contractSize': None,
|
'contractSize': None,
|
||||||
|
'taker': 0.0006,
|
||||||
|
'maker': 0.0002,
|
||||||
'precision': {
|
'precision': {
|
||||||
'amount': 8,
|
'amount': 8,
|
||||||
'price': 8
|
'price': 8
|
||||||
|
@ -860,6 +862,8 @@ def get_markets():
|
||||||
'margin': True,
|
'margin': True,
|
||||||
'type': 'spot',
|
'type': 'spot',
|
||||||
'contractSize': None,
|
'contractSize': None,
|
||||||
|
'taker': 0.0006,
|
||||||
|
'maker': 0.0002,
|
||||||
'precision': {
|
'precision': {
|
||||||
'amount': 8,
|
'amount': 8,
|
||||||
'price': 8
|
'price': 8
|
||||||
|
@ -892,6 +896,8 @@ def get_markets():
|
||||||
'active': True,
|
'active': True,
|
||||||
'spot': True,
|
'spot': True,
|
||||||
'type': 'spot',
|
'type': 'spot',
|
||||||
|
'taker': 0.0006,
|
||||||
|
'maker': 0.0002,
|
||||||
'precision': {
|
'precision': {
|
||||||
'price': 8,
|
'price': 8,
|
||||||
'amount': 8,
|
'amount': 8,
|
||||||
|
@ -923,6 +929,8 @@ def get_markets():
|
||||||
'active': True,
|
'active': True,
|
||||||
'spot': True,
|
'spot': True,
|
||||||
'type': 'spot',
|
'type': 'spot',
|
||||||
|
'taker': 0.0006,
|
||||||
|
'maker': 0.0002,
|
||||||
'precision': {
|
'precision': {
|
||||||
'price': 8,
|
'price': 8,
|
||||||
'amount': 8,
|
'amount': 8,
|
||||||
|
@ -955,6 +963,8 @@ def get_markets():
|
||||||
'spot': True,
|
'spot': True,
|
||||||
'type': 'spot',
|
'type': 'spot',
|
||||||
'contractSize': None,
|
'contractSize': None,
|
||||||
|
'taker': 0.0006,
|
||||||
|
'maker': 0.0002,
|
||||||
'precision': {
|
'precision': {
|
||||||
'price': 8,
|
'price': 8,
|
||||||
'amount': 8,
|
'amount': 8,
|
||||||
|
@ -1023,6 +1033,8 @@ def get_markets():
|
||||||
'spot': False,
|
'spot': False,
|
||||||
'type': 'swap',
|
'type': 'swap',
|
||||||
'contractSize': 0.01,
|
'contractSize': 0.01,
|
||||||
|
'taker': 0.0006,
|
||||||
|
'maker': 0.0002,
|
||||||
'precision': {
|
'precision': {
|
||||||
'amount': 8,
|
'amount': 8,
|
||||||
'price': 8
|
'price': 8
|
||||||
|
|
|
@ -37,6 +37,8 @@ def test_validate_order_types_gateio(default_conf, mocker):
|
||||||
("DOGE/USDT:USDT", None),
|
("DOGE/USDT:USDT", None),
|
||||||
])
|
])
|
||||||
def test_get_maintenance_ratio_and_amt_gateio(default_conf, mocker, pair, mm_ratio):
|
def test_get_maintenance_ratio_and_amt_gateio(default_conf, mocker, pair, mm_ratio):
|
||||||
|
api_mock = MagicMock()
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="gateio")
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'freqtrade.exchange.Exchange.markets',
|
'freqtrade.exchange.Exchange.markets',
|
||||||
PropertyMock(
|
PropertyMock(
|
||||||
|
@ -71,6 +73,4 @@ def test_get_maintenance_ratio_and_amt_gateio(default_conf, mocker, pair, mm_rat
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
api_mock = MagicMock()
|
|
||||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="gateio")
|
|
||||||
assert exchange.get_maintenance_ratio_and_amt(pair) == [mm_ratio, None]
|
assert exchange.get_maintenance_ratio_and_amt(pair) == [mm_ratio, None]
|
||||||
|
|
|
@ -707,21 +707,45 @@ def test_process_informative_pairs_added(default_conf_usdt, ticker_usdt, mocker)
|
||||||
CandleType.SPOT) in refresh_mock.call_args[0][0]
|
CandleType.SPOT) in refresh_mock.call_args[0][0]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("trading_mode", [
|
@pytest.mark.parametrize("is_short,trading_mode,exchange_name,margin_mode,liq_price", [
|
||||||
'spot',
|
(False, 'spot', 'binance', '', None),
|
||||||
# TODO-lev: Enable other modes
|
(True, 'spot', 'binance', '', None),
|
||||||
# 'margin', 'futures'
|
(False, 'spot', 'gateio', '', None),
|
||||||
]
|
(True, 'spot', 'gateio', '', None),
|
||||||
)
|
(True, 'futures', 'binance', 'isolated', 13.217821782178218),
|
||||||
@pytest.mark.parametrize("is_short", [False, True])
|
(False, 'futures', 'binance', 'isolated', 6.717171717171718),
|
||||||
|
(True, 'futures', 'gateio', 'isolated', 13.198706526760379),
|
||||||
|
(False, 'futures', 'gateio', 'isolated', 6.735367414292449),
|
||||||
|
# TODO-lev: Okex
|
||||||
|
# (False, 'spot', 'okex', 'isolated', ...),
|
||||||
|
# (True, 'futures', 'okex', 'isolated', ...),
|
||||||
|
])
|
||||||
def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
||||||
limit_order_open, is_short, trading_mode) -> None:
|
limit_order_open, is_short, trading_mode,
|
||||||
|
exchange_name, margin_mode, liq_price) -> None:
|
||||||
|
'''
|
||||||
|
exchange_name = binance, is_short = true
|
||||||
|
(wb + cum_b - side_1 * position * ep1) / (position * mmr_b - side_1 * position)
|
||||||
|
((2 + 0.01) - ((-1) * 0.6 * 10)) / ((0.6 * 0.01) - ((-1) * 0.6)) = 13.217821782178218
|
||||||
|
|
||||||
|
exchange_name = binance, is_short = false
|
||||||
|
(wb + cum_b - side_1 * position * ep1) / (position * mmr_b - side_1 * position)
|
||||||
|
(2 + 0.01 - 1 * 0.6 * 10) / (0.6 * 0.01 - 1 * 0.6) = 6.717171717171718
|
||||||
|
|
||||||
|
exchange_name = gateio, is_short = true
|
||||||
|
(open_rate + (wallet_balance / position)) / (1 + (mm_ratio + taker_fee_rate))
|
||||||
|
(10 + (6 / 0.6)) / (1 + (0.01 + 0.0002))
|
||||||
|
13.198706526760379
|
||||||
|
|
||||||
|
exchange_name = gateio, is_short = false
|
||||||
|
(open_rate - (wallet_balance / position)) / (1 - (mm_ratio + taker_fee_rate))
|
||||||
|
(10 - (2 / 0.6)) / (1 - (0.01 + 0.0002)) = 6.735367414292449
|
||||||
|
'''
|
||||||
open_order = limit_order_open[enter_side(is_short)]
|
open_order = limit_order_open[enter_side(is_short)]
|
||||||
order = limit_order[enter_side(is_short)]
|
order = limit_order[enter_side(is_short)]
|
||||||
default_conf_usdt['trading_mode'] = trading_mode
|
default_conf_usdt['trading_mode'] = trading_mode
|
||||||
leverage = 1.0 if trading_mode == 'spot' else 3.0
|
leverage = 1.0 if trading_mode == 'spot' else 5.0
|
||||||
default_conf_usdt['collateral'] = 'cross'
|
default_conf_usdt['collateral'] = margin_mode
|
||||||
patch_RPCManager(mocker)
|
patch_RPCManager(mocker)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||||
|
@ -886,14 +910,24 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
||||||
assert trade.open_rate_requested == 10
|
assert trade.open_rate_requested == 10
|
||||||
|
|
||||||
# In case of custom entry price not float type
|
# In case of custom entry price not float type
|
||||||
|
mocker.patch.multiple(
|
||||||
|
'freqtrade.exchange.Exchange',
|
||||||
|
name=exchange_name,
|
||||||
|
get_maintenance_ratio_and_amt=MagicMock(return_value=[0.01, 0.01])
|
||||||
|
)
|
||||||
order['status'] = 'open'
|
order['status'] = 'open'
|
||||||
order['id'] = '5568'
|
order['id'] = '5568'
|
||||||
freqtrade.strategy.custom_entry_price = lambda **kwargs: "string price"
|
freqtrade.strategy.custom_entry_price = lambda **kwargs: "string price"
|
||||||
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
assert freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
|
||||||
trade = Trade.query.all()[8]
|
trade = Trade.query.all()[8]
|
||||||
|
# Trade(id=9, pair=ETH/USDT, amount=0.20000000, is_short=False,
|
||||||
|
# leverage=1.0, open_rate=10.00000000, open_since=...)
|
||||||
|
# Trade(id=9, pair=ETH/USDT, amount=0.60000000, is_short=True,
|
||||||
|
# leverage=3.0, open_rate=10.00000000, open_since=...)
|
||||||
trade.is_short = is_short
|
trade.is_short = is_short
|
||||||
assert trade
|
assert trade
|
||||||
assert trade.open_rate_requested == 10
|
assert trade.open_rate_requested == 10
|
||||||
|
assert trade.isolated_liq == liq_price
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("is_short", [False, True])
|
@pytest.mark.parametrize("is_short", [False, True])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user