Merge pull request #7491 from freqtrade/partial_close_leverage
Partial close leverage
This commit is contained in:
commit
578da343dc
@ -643,7 +643,7 @@ This callback is **not** called when there is an open order (either buy or sell)
|
||||
|
||||
Additional Buys are ignored once you have reached the maximum amount of extra buys that you have set on `max_entry_position_adjustment`, but the callback is called anyway looking for partial exits.
|
||||
|
||||
Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position (negative values will decrease your position), no matter if it's a long or short trade. Modifications to leverage are not possible.
|
||||
Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position (negative values will decrease your position), no matter if it's a long or short trade. Modifications to leverage are not possible, and the stake-amount is assumed to be before applying leverage.
|
||||
|
||||
!!! Note "About stake size"
|
||||
Using fixed stake size means it will be the amount used for the first order, just like without position adjustment.
|
||||
|
@ -597,7 +597,7 @@ class FreqtradeBot(LoggingMixin):
|
||||
# We should decrease our position
|
||||
amount = self.exchange.amount_to_contract_precision(
|
||||
trade.pair,
|
||||
abs(float(FtPrecise(stake_amount) / FtPrecise(current_exit_rate))))
|
||||
abs(float(FtPrecise(stake_amount * trade.leverage) / FtPrecise(current_exit_rate))))
|
||||
if amount > trade.amount:
|
||||
# This is currently ineffective as remaining would become < min tradable
|
||||
# Fixing this would require checking for 0.0 there -
|
||||
|
@ -540,7 +540,7 @@ class Backtesting:
|
||||
|
||||
if stake_amount is not None and stake_amount < 0.0:
|
||||
amount = amount_to_contract_precision(
|
||||
abs(stake_amount) / current_rate, trade.amount_precision,
|
||||
abs(stake_amount * trade.leverage) / current_rate, trade.amount_precision,
|
||||
self.precision_mode, trade.contract_size)
|
||||
if amount == 0.0:
|
||||
return trade
|
||||
|
@ -93,11 +93,16 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) ->
|
||||
t["close_rate"], 6) < round(ln.iloc[0]["high"], 6))
|
||||
|
||||
|
||||
def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> None:
|
||||
@pytest.mark.parametrize('leverage', [
|
||||
1, 2
|
||||
])
|
||||
def test_backtest_position_adjustment_detailed(default_conf, fee, mocker, leverage) -> None:
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=10)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_leverage", return_value=10)
|
||||
|
||||
patch_exchange(mocker)
|
||||
default_conf.update({
|
||||
"stake_amount": 100.0,
|
||||
@ -105,6 +110,7 @@ def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> Non
|
||||
"strategy": "StrategyTestV3"
|
||||
})
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._can_short = True
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
pair = 'XRP/USDT'
|
||||
row = [
|
||||
@ -120,18 +126,19 @@ def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> Non
|
||||
'', # enter_tag
|
||||
'', # exit_tag
|
||||
]
|
||||
backtesting.strategy.leverage = MagicMock(return_value=leverage)
|
||||
trade = backtesting._enter_trade(pair, row=row, direction='long')
|
||||
trade.orders[0].close_bt_order(row[0], trade)
|
||||
assert trade
|
||||
assert pytest.approx(trade.stake_amount) == 100.0
|
||||
assert pytest.approx(trade.amount) == 47.61904762
|
||||
assert pytest.approx(trade.amount) == 47.61904762 * leverage
|
||||
assert len(trade.orders) == 1
|
||||
backtesting.strategy.adjust_trade_position = MagicMock(return_value=None)
|
||||
|
||||
trade = backtesting._get_adjust_trade_entry_for_candle(trade, row)
|
||||
assert trade
|
||||
assert pytest.approx(trade.stake_amount) == 100.0
|
||||
assert pytest.approx(trade.amount) == 47.61904762
|
||||
assert pytest.approx(trade.amount) == 47.61904762 * leverage
|
||||
assert len(trade.orders) == 1
|
||||
# Increase position by 100
|
||||
backtesting.strategy.adjust_trade_position = MagicMock(return_value=100)
|
||||
@ -140,7 +147,7 @@ def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> Non
|
||||
|
||||
assert trade
|
||||
assert pytest.approx(trade.stake_amount) == 200.0
|
||||
assert pytest.approx(trade.amount) == 95.23809524
|
||||
assert pytest.approx(trade.amount) == 95.23809524 * leverage
|
||||
assert len(trade.orders) == 2
|
||||
|
||||
# Reduce by more than amount - no change to trade.
|
||||
@ -150,7 +157,7 @@ def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> Non
|
||||
|
||||
assert trade
|
||||
assert pytest.approx(trade.stake_amount) == 200.0
|
||||
assert pytest.approx(trade.amount) == 95.23809524
|
||||
assert pytest.approx(trade.amount) == 95.23809524 * leverage
|
||||
assert len(trade.orders) == 2
|
||||
assert trade.nr_of_successful_entries == 2
|
||||
|
||||
@ -160,7 +167,7 @@ def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> Non
|
||||
|
||||
assert trade
|
||||
assert pytest.approx(trade.stake_amount) == 100.0
|
||||
assert pytest.approx(trade.amount) == 47.61904762
|
||||
assert pytest.approx(trade.amount) == 47.61904762 * leverage
|
||||
assert len(trade.orders) == 3
|
||||
assert trade.nr_of_successful_entries == 2
|
||||
assert trade.nr_of_successful_exits == 1
|
||||
@ -171,7 +178,7 @@ def test_backtest_position_adjustment_detailed(default_conf, fee, mocker) -> Non
|
||||
|
||||
assert trade
|
||||
assert pytest.approx(trade.stake_amount) == 100.0
|
||||
assert pytest.approx(trade.amount) == 47.61904762
|
||||
assert pytest.approx(trade.amount) == 47.61904762 * leverage
|
||||
assert len(trade.orders) == 3
|
||||
assert trade.nr_of_successful_entries == 2
|
||||
assert trade.nr_of_successful_exits == 1
|
||||
|
@ -2,7 +2,7 @@ from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from freqtrade.enums import ExitCheckTuple, ExitType
|
||||
from freqtrade.enums import ExitCheckTuple, ExitType, TradingMode
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.persistence.models import Order
|
||||
from freqtrade.rpc.rpc import RPC
|
||||
@ -455,10 +455,12 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, fee, mocker) -> None:
|
||||
assert pytest.approx(trade.orders[-1].amount) == 61.538461232
|
||||
|
||||
|
||||
def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog) -> None:
|
||||
@pytest.mark.parametrize('leverage', [1, 2])
|
||||
def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, leverage) -> None:
|
||||
default_conf_usdt['position_adjustment_enable'] = True
|
||||
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
freqtrade.trading_mode = TradingMode.FUTURES
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_usdt,
|
||||
@ -467,15 +469,17 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog) -> Non
|
||||
price_to_precision=lambda s, x, y: y,
|
||||
get_min_pair_stake_amount=MagicMock(return_value=10),
|
||||
)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_leverage", return_value=10)
|
||||
|
||||
patch_get_signal(freqtrade)
|
||||
freqtrade.strategy.leverage = MagicMock(return_value=leverage)
|
||||
freqtrade.enter_positions()
|
||||
|
||||
assert len(Trade.get_trades().all()) == 1
|
||||
trade = Trade.get_trades().first()
|
||||
assert len(trade.orders) == 1
|
||||
assert pytest.approx(trade.stake_amount) == 60
|
||||
assert pytest.approx(trade.amount) == 30.0
|
||||
assert pytest.approx(trade.amount) == 30.0 * leverage
|
||||
assert trade.open_rate == 2.0
|
||||
|
||||
# Too small size
|
||||
@ -484,8 +488,9 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog) -> Non
|
||||
trade = Trade.get_trades().first()
|
||||
assert len(trade.orders) == 1
|
||||
assert pytest.approx(trade.stake_amount) == 60
|
||||
assert pytest.approx(trade.amount) == 30.0
|
||||
assert log_has_re("Remaining amount of 1.6.* would be smaller than the minimum of 10.", caplog)
|
||||
assert pytest.approx(trade.amount) == 30.0 * leverage
|
||||
assert log_has_re(
|
||||
r"Remaining amount of \d\.\d+.* would be smaller than the minimum of 10.", caplog)
|
||||
|
||||
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-20)
|
||||
|
||||
@ -494,7 +499,7 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog) -> Non
|
||||
assert len(trade.orders) == 2
|
||||
assert trade.orders[-1].ft_order_side == 'sell'
|
||||
assert pytest.approx(trade.stake_amount) == 40.198
|
||||
assert pytest.approx(trade.amount) == 20.099
|
||||
assert pytest.approx(trade.amount) == 20.099 * leverage
|
||||
assert trade.open_rate == 2.0
|
||||
assert trade.is_open
|
||||
caplog.clear()
|
||||
|
Loading…
Reference in New Issue
Block a user