commit
5cc2a15b02
@ -46,7 +46,7 @@ DEFAULT_DATAFRAME_COLUMNS = ['date', 'open', 'high', 'low', 'close', 'volume']
|
||||
# it has wide consequences for stored trades files
|
||||
DEFAULT_TRADES_COLUMNS = ['timestamp', 'id', 'type', 'side', 'price', 'amount', 'cost']
|
||||
TRADING_MODES = ['spot', 'margin', 'futures']
|
||||
MARGIN_MODES = ['cross', 'isolated']
|
||||
MARGIN_MODES = ['cross', 'isolated', '']
|
||||
|
||||
LAST_BT_RESULT_FN = '.last_result.json'
|
||||
FTHYPT_FILEVERSION = 'fthypt_fileversion'
|
||||
|
@ -9,3 +9,4 @@ class MarginMode(Enum):
|
||||
"""
|
||||
CROSS = "cross"
|
||||
ISOLATED = "isolated"
|
||||
NONE = ''
|
||||
|
@ -909,11 +909,10 @@ class Exchange:
|
||||
side: str,
|
||||
amount: float,
|
||||
rate: float,
|
||||
leverage: float,
|
||||
reduceOnly: bool = False,
|
||||
leverage: float = 1.0,
|
||||
time_in_force: str = 'gtc',
|
||||
) -> Dict:
|
||||
# TODO-lev: remove default for leverage
|
||||
if self._config['dry_run']:
|
||||
dry_order = self.create_dry_run_order(pair, ordertype, side, amount, rate, leverage)
|
||||
return dry_order
|
||||
|
@ -601,7 +601,7 @@ class FreqtradeBot(LoggingMixin):
|
||||
self,
|
||||
pair: str,
|
||||
open_rate: float,
|
||||
amount: float,
|
||||
amount: float, # quote currency, includes leverage
|
||||
leverage: float,
|
||||
is_short: bool
|
||||
) -> Tuple[float, Optional[float]]:
|
||||
@ -1272,7 +1272,8 @@ class FreqtradeBot(LoggingMixin):
|
||||
# to the order dict acquired before cancelling.
|
||||
# we need to fall back to the values from order if corder does not contain these keys.
|
||||
trade.amount = filled_amount
|
||||
# TODO-lev: Check edge cases, we don't want to make leverage > 1.0 if we don't have to
|
||||
# * Check edge cases, we don't want to make leverage > 1.0 if we don't have to
|
||||
# * (for leverage modes which aren't isolated futures)
|
||||
|
||||
trade.stake_amount = trade.amount * trade.open_rate
|
||||
self.update_trade_state(trade, trade.open_order_id, corder)
|
||||
@ -1339,13 +1340,14 @@ class FreqtradeBot(LoggingMixin):
|
||||
:return: amount to sell
|
||||
:raise: DependencyException: if available balance is not within 2% of the available amount.
|
||||
"""
|
||||
# TODO-lev Maybe update?
|
||||
# Update wallets to ensure amounts tied up in a stoploss is now free!
|
||||
self.wallets.update()
|
||||
trade_base_currency = self.exchange.get_pair_base_currency(pair)
|
||||
wallet_amount = self.wallets.get_free(trade_base_currency)
|
||||
logger.debug(f"{pair} - Wallet: {wallet_amount} - Trade-amount: {amount}")
|
||||
if wallet_amount >= amount:
|
||||
# TODO-lev: Get wallet amount + value of positions
|
||||
if wallet_amount >= amount or self.trading_mode == TradingMode.FUTURES:
|
||||
# A safe exit amount isn't needed for futures, you can just exit/close the position
|
||||
return amount
|
||||
elif wallet_amount > amount * 0.98:
|
||||
logger.info(f"{pair} - Falling back to wallet-amount {wallet_amount} -> {amount}.")
|
||||
@ -1423,6 +1425,7 @@ class FreqtradeBot(LoggingMixin):
|
||||
side=trade.exit_side,
|
||||
amount=amount,
|
||||
rate=limit,
|
||||
leverage=trade.leverage,
|
||||
reduceOnly=self.trading_mode == TradingMode.FUTURES,
|
||||
time_in_force=time_in_force
|
||||
)
|
||||
|
@ -333,8 +333,12 @@ class Backtesting:
|
||||
df_analyzed.loc[:, col] = 0 if not tag_col else None
|
||||
|
||||
# Update dataprovider cache
|
||||
self.dataprovider._set_cached_df(pair, self.timeframe, df_analyzed, CandleType.SPOT)
|
||||
# TODO-lev: Candle-type should be conditional, either "spot" or futures
|
||||
self.dataprovider._set_cached_df(
|
||||
pair,
|
||||
self.timeframe,
|
||||
df_analyzed,
|
||||
self.config['candle_type_def']
|
||||
)
|
||||
|
||||
df_analyzed = df_analyzed.drop(df_analyzed.head(1).index)
|
||||
|
||||
@ -497,7 +501,7 @@ class Backtesting:
|
||||
sell_candle_time: datetime = sell_row[DATE_IDX].to_pydatetime()
|
||||
|
||||
if self.trading_mode == TradingMode.FUTURES:
|
||||
# TODO-lev: Other fees / liquidation price?
|
||||
# TODO-lev: liquidation price?
|
||||
trade.funding_fees = self.exchange.calculate_funding_fees(
|
||||
self.futures_data[trade.pair],
|
||||
amount=trade.amount,
|
||||
|
@ -569,7 +569,6 @@ class LocalTrade():
|
||||
payment = "BUY" if self.is_short else "SELL"
|
||||
# * On margin shorts, you buy a little bit more than the amount (amount + interest)
|
||||
logger.info(f'{order_type.upper()}_{payment} has been fulfilled for {self}.')
|
||||
# TODO-lev: Double check this
|
||||
self.close(safe_value_fallback(order, 'average', 'price'))
|
||||
elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'):
|
||||
self.stoploss_order_id = None
|
||||
|
@ -431,7 +431,6 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra
|
||||
)
|
||||
fig.add_trace(candles, 1, 1)
|
||||
|
||||
# TODO-lev: Needs short equivalent
|
||||
if 'enter_long' in data.columns:
|
||||
df_buy = data[data['enter_long'] == 1]
|
||||
if len(df_buy) > 0:
|
||||
@ -537,7 +536,7 @@ def generate_profit_graph(pairs: str, data: Dict[str, pd.DataFrame],
|
||||
"Profit per pair",
|
||||
"Parallelism",
|
||||
"Underwater",
|
||||
])
|
||||
])
|
||||
fig['layout'].update(title="Freqtrade Profit plot")
|
||||
fig['layout']['yaxis1'].update(title='Price')
|
||||
fig['layout']['yaxis2'].update(title=f'Profit {stake_currency}')
|
||||
|
@ -1213,7 +1213,8 @@ def test_buy_dry_run(default_conf, mocker):
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype='limit', side="buy",
|
||||
amount=1, rate=200, time_in_force='gtc')
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force='gtc')
|
||||
assert 'id' in order
|
||||
assert 'dry_run_buy_' in order['id']
|
||||
|
||||
@ -1238,7 +1239,8 @@ def test_buy_prod(default_conf, mocker, exchange_name):
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -1257,7 +1259,9 @@ def test_buy_prod(default_conf, mocker, exchange_name):
|
||||
side="buy",
|
||||
amount=1,
|
||||
rate=200,
|
||||
time_in_force=time_in_force)
|
||||
leverage=1.0,
|
||||
time_in_force=time_in_force
|
||||
)
|
||||
assert api_mock.create_order.call_args[0][0] == 'ETH/BTC'
|
||||
assert api_mock.create_order.call_args[0][1] == order_type
|
||||
assert api_mock.create_order.call_args[0][2] == 'buy'
|
||||
@ -1269,31 +1273,36 @@ def test_buy_prod(default_conf, mocker, exchange_name):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("Not enough funds"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
with pytest.raises(DependencyException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype='limit', side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
with pytest.raises(DependencyException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype='market', side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
with pytest.raises(TemporaryError):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("Network disconnect"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
with pytest.raises(OperationalException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("Unknown error"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
@ -1317,7 +1326,8 @@ def test_buy_considers_time_in_force(default_conf, mocker, exchange_name):
|
||||
time_in_force = 'ioc'
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -1334,7 +1344,8 @@ def test_buy_considers_time_in_force(default_conf, mocker, exchange_name):
|
||||
time_in_force = 'ioc'
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -1353,7 +1364,7 @@ def test_sell_dry_run(default_conf, mocker):
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype='limit',
|
||||
side="sell", amount=1, rate=200)
|
||||
side="sell", amount=1, rate=200, leverage=1.0)
|
||||
assert 'id' in order
|
||||
assert 'dry_run_sell_' in order['id']
|
||||
|
||||
@ -1378,7 +1389,7 @@ def test_sell_prod(default_conf, mocker, exchange_name):
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type,
|
||||
side="sell", amount=1, rate=200)
|
||||
side="sell", amount=1, rate=200, leverage=1.0)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -1392,7 +1403,8 @@ def test_sell_prod(default_conf, mocker, exchange_name):
|
||||
api_mock.create_order.reset_mock()
|
||||
order_type = 'limit'
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type,
|
||||
side="sell", amount=1, rate=200)
|
||||
side="sell", amount=1, rate=200,
|
||||
leverage=1.0)
|
||||
assert api_mock.create_order.call_args[0][0] == 'ETH/BTC'
|
||||
assert api_mock.create_order.call_args[0][1] == order_type
|
||||
assert api_mock.create_order.call_args[0][2] == 'sell'
|
||||
@ -1403,28 +1415,33 @@ def test_sell_prod(default_conf, mocker, exchange_name):
|
||||
with pytest.raises(DependencyException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200,
|
||||
leverage=1.0)
|
||||
|
||||
with pytest.raises(DependencyException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype='limit', side="sell", amount=1, rate=200)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype='limit', side="sell", amount=1, rate=200,
|
||||
leverage=1.0)
|
||||
|
||||
# Market orders don't require price, so the behaviour is slightly different
|
||||
with pytest.raises(DependencyException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype='market', side="sell", amount=1, rate=200)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype='market', side="sell", amount=1, rate=200,
|
||||
leverage=1.0)
|
||||
|
||||
with pytest.raises(TemporaryError):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No Connection"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200,
|
||||
leverage=1.0)
|
||||
|
||||
with pytest.raises(OperationalException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200)
|
||||
exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200,
|
||||
leverage=1.0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
@ -1448,7 +1465,8 @@ def test_sell_considers_time_in_force(default_conf, mocker, exchange_name):
|
||||
time_in_force = 'ioc'
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -1464,7 +1482,8 @@ def test_sell_considers_time_in_force(default_conf, mocker, exchange_name):
|
||||
order_type = 'market'
|
||||
time_in_force = 'ioc'
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
amount=1, rate=200, leverage=1.0,
|
||||
time_in_force=time_in_force)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -3771,9 +3790,10 @@ def test__fetch_and_calculate_funding_fees_datetime_called(
|
||||
d1 = datetime.strptime("2021-09-01 00:00:00 +0000", '%Y-%m-%d %H:%M:%S %z')
|
||||
|
||||
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
||||
# TODO-lev: test this for longs
|
||||
funding_fees = exchange._fetch_and_calculate_funding_fees('ADA/USDT', 30.0, True, d1)
|
||||
assert funding_fees == expected_fees
|
||||
funding_fees = exchange._fetch_and_calculate_funding_fees('ADA/USDT', 30.0, False, d1)
|
||||
assert funding_fees == 0 - expected_fees
|
||||
|
||||
|
||||
@pytest.mark.parametrize('pair,expected_size,trading_mode', [
|
||||
|
@ -32,8 +32,15 @@ def test_buy_kraken_trading_agreement(default_conf, mocker):
|
||||
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken")
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy",
|
||||
amount=1, rate=200, time_in_force=time_in_force)
|
||||
order = exchange.create_order(
|
||||
pair='ETH/BTC',
|
||||
ordertype=order_type,
|
||||
side="buy",
|
||||
amount=1,
|
||||
rate=200,
|
||||
leverage=1.0,
|
||||
time_in_force=time_in_force
|
||||
)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
@ -66,7 +73,7 @@ def test_sell_kraken_trading_agreement(default_conf, mocker):
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken")
|
||||
|
||||
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type,
|
||||
side="sell", amount=1, rate=200)
|
||||
side="sell", amount=1, rate=200, leverage=1.0)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
|
@ -169,7 +169,6 @@ class StrategyTestV3(IStrategy):
|
||||
),
|
||||
'exit_short'] = 1
|
||||
|
||||
# TODO-lev: Add short logic
|
||||
return dataframe
|
||||
|
||||
def leverage(self, pair: str, current_time: datetime, current_rate: float,
|
||||
|
@ -4782,9 +4782,125 @@ def test_get_valid_price(mocker, default_conf_usdt) -> None:
|
||||
assert valid_price_at_min_alwd < proposed_price
|
||||
|
||||
|
||||
def test_leverage_prep():
|
||||
# TODO-lev
|
||||
return
|
||||
@pytest.mark.parametrize(
|
||||
"is_short,trading_mode,exchange_name,margin_mode,leverage,open_rate,amount,expected_liq", [
|
||||
(False, 'spot', 'binance', '', 5.0, 10.0, 1.0, None),
|
||||
(True, 'spot', 'binance', '', 5.0, 10.0, 1.0, None),
|
||||
(False, 'spot', 'gateio', '', 5.0, 10.0, 1.0, None),
|
||||
(True, 'spot', 'gateio', '', 5.0, 10.0, 1.0, None),
|
||||
(False, 'spot', 'okex', '', 5.0, 10.0, 1.0, None),
|
||||
(True, 'spot', 'okex', '', 5.0, 10.0, 1.0, None),
|
||||
# Binance, short
|
||||
(True, 'futures', 'binance', 'isolated', 5.0, 10.0, 1.0, 11.89108910891089),
|
||||
(True, 'futures', 'binance', 'isolated', 3.0, 10.0, 1.0, 13.211221122079207),
|
||||
(True, 'futures', 'binance', 'isolated', 5.0, 8.0, 1.0, 9.514851485148514),
|
||||
(True, 'futures', 'binance', 'isolated', 5.0, 10.0, 0.6, 12.557755775577558),
|
||||
# Binance, long
|
||||
(False, 'futures', 'binance', 'isolated', 5, 10, 1.0, 8.070707070707071),
|
||||
(False, 'futures', 'binance', 'isolated', 5, 8, 1.0, 6.454545454545454),
|
||||
(False, 'futures', 'binance', 'isolated', 3, 10, 1.0, 6.717171717171718),
|
||||
(False, 'futures', 'binance', 'isolated', 5, 10, 0.6, 7.39057239057239),
|
||||
# Gateio/okex, short
|
||||
(True, 'futures', 'gateio', 'isolated', 5, 10, 1.0, 11.87413417771621),
|
||||
(True, 'futures', 'gateio', 'isolated', 5, 10, 2.0, 11.87413417771621),
|
||||
(True, 'futures', 'gateio', 'isolated', 3, 10, 1.0, 13.476180850346978),
|
||||
(True, 'futures', 'gateio', 'isolated', 5, 8, 1.0, 9.499307342172967),
|
||||
# Gateio/okex, long
|
||||
(False, 'futures', 'gateio', 'isolated', 5.0, 10.0, 1.0, 8.085708510208207),
|
||||
(False, 'futures', 'gateio', 'isolated', 3.0, 10.0, 1.0, 6.738090425173506),
|
||||
# (True, 'futures', 'okex', 'isolated', 11.87413417771621),
|
||||
# (False, 'futures', 'okex', 'isolated', 8.085708510208207),
|
||||
]
|
||||
)
|
||||
def test_leverage_prep(
|
||||
mocker,
|
||||
default_conf_usdt,
|
||||
is_short,
|
||||
trading_mode,
|
||||
exchange_name,
|
||||
margin_mode,
|
||||
leverage,
|
||||
open_rate,
|
||||
amount,
|
||||
expected_liq,
|
||||
):
|
||||
"""
|
||||
position = 0.2 * 5
|
||||
wb: wallet balance (stake_amount if isolated)
|
||||
cum_b: maintenance amount
|
||||
side_1: -1 if is_short else 1
|
||||
ep1: entry price
|
||||
mmr_b: maintenance margin ratio
|
||||
|
||||
Binance, Short
|
||||
leverage = 5, open_rate = 10, amount = 1.0
|
||||
((wb + cum_b) - (side_1 * position * ep1)) / ((position * mmr_b) - (side_1 * position))
|
||||
((2 + 0.01) - ((-1) * 1 * 10)) / ((1 * 0.01) - ((-1) * 1)) = 11.89108910891089
|
||||
leverage = 3, open_rate = 10, amount = 1.0
|
||||
((3.3333333333 + 0.01) - ((-1) * 1.0 * 10)) / ((1.0 * 0.01) - ((-1) * 1.0)) = 13.2112211220
|
||||
leverage = 5, open_rate = 8, amount = 1.0
|
||||
((1.6 + 0.01) - ((-1) * 1 * 8)) / ((1 * 0.01) - ((-1) * 1)) = 9.514851485148514
|
||||
leverage = 5, open_rate = 10, amount = 0.6
|
||||
((1.6 + 0.01) - ((-1) * 0.6 * 10)) / ((0.6 * 0.01) - ((-1) * 0.6)) = 12.557755775577558
|
||||
|
||||
Binance, Long
|
||||
leverage = 5, open_rate = 10, amount = 1.0
|
||||
((wb + cum_b) - (side_1 * position * ep1)) / ((position * mmr_b) - (side_1 * position))
|
||||
((2 + 0.01) - (1 * 1 * 10)) / ((1 * 0.01) - (1 * 1)) = 8.070707070707071
|
||||
leverage = 5, open_rate = 8, amount = 1.0
|
||||
((1.6 + 0.01) - (1 * 1 * 8)) / ((1 * 0.01) - (1 * 1)) = 6.454545454545454
|
||||
leverage = 3, open_rate = 10, amount = 1.0
|
||||
((2 + 0.01) - (1 * 0.6 * 10)) / ((0.6 * 0.01) - (1 * 0.6)) = 6.717171717171718
|
||||
leverage = 5, open_rate = 10, amount = 0.6
|
||||
((1.6 + 0.01) - (1 * 0.6 * 10)) / ((0.6 * 0.01) - (1 * 0.6)) = 7.39057239057239
|
||||
|
||||
Gateio/Okex, Short
|
||||
leverage = 5, open_rate = 10, amount = 1.0
|
||||
(open_rate + (wallet_balance / position)) / (1 + (mm_ratio + taker_fee_rate))
|
||||
(10 + (2 / 1.0)) / (1 + (0.01 + 0.0006)) = 11.87413417771621
|
||||
leverage = 5, open_rate = 10, amount = 2.0
|
||||
(10 + (4 / 2.0)) / (1 + (0.01 + 0.0006)) = 11.87413417771621
|
||||
leverage = 3, open_rate = 10, amount = 1.0
|
||||
(10 + (3.3333333333333 / 1.0)) / (1 - (0.01 + 0.0006)) = 13.476180850346978
|
||||
leverage = 5, open_rate = 8, amount = 1.0
|
||||
(8 + (1.6 / 1.0)) / (1 + (0.01 + 0.0006)) = 9.499307342172967
|
||||
|
||||
Gateio/Okex, Long
|
||||
leverage = 5, open_rate = 10, amount = 1.0
|
||||
(open_rate - (wallet_balance / position)) / (1 - (mm_ratio + taker_fee_rate))
|
||||
(10 - (2 / 1)) / (1 - (0.01 + 0.0006)) = 8.085708510208207
|
||||
leverage = 5, open_rate = 10, amount = 2.0
|
||||
(10 - (4 / 2.0)) / (1 + (0.01 + 0.0006)) = 7.916089451810806
|
||||
leverage = 3, open_rate = 10, amount = 1.0
|
||||
(10 - (3.333333333333333333 / 1.0)) / (1 - (0.01 + 0.0006)) = 6.738090425173506
|
||||
leverage = 5, open_rate = 8, amount = 1.0
|
||||
(8 - (1.6 / 1.0)) / (1 + (0.01 + 0.0006)) = 6.332871561448645
|
||||
"""
|
||||
default_conf_usdt['trading_mode'] = trading_mode
|
||||
default_conf_usdt['exchange']['name'] = exchange_name
|
||||
default_conf_usdt['margin_mode'] = margin_mode
|
||||
mocker.patch('freqtrade.exchange.Gateio.validate_ordertypes')
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker, id=exchange_name)
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
|
||||
freqtrade.exchange.get_maintenance_ratio_and_amt = MagicMock(return_value=(0.01, 0.01))
|
||||
freqtrade.exchange.name = exchange_name
|
||||
# default_conf_usdt.update({
|
||||
# "dry_run": False,
|
||||
# })
|
||||
(interest, liq) = freqtrade.leverage_prep(
|
||||
pair='ETH/USDT:USDT',
|
||||
open_rate=open_rate,
|
||||
amount=amount,
|
||||
leverage=leverage,
|
||||
is_short=is_short,
|
||||
)
|
||||
assert interest == 0.0
|
||||
if expected_liq is None:
|
||||
assert liq is None
|
||||
else:
|
||||
isclose(expected_liq, liq)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('trading_mode,calls,t1,t2', [
|
||||
|
Loading…
Reference in New Issue
Block a user