Add "nr_of_successfull_entries"

This commit is contained in:
Matthias 2022-02-13 15:10:09 +01:00
parent 5c9dddb7f3
commit bcfa73d492
6 changed files with 38 additions and 13 deletions

View File

@ -593,6 +593,8 @@ Additional orders also result in additional fees and those orders don't count to
This callback is **not** called when there is an open order (either buy or sell) waiting for execution, or when you have reached the maximum amount of extra buys that you have set on `max_entry_position_adjustment`.
`adjust_trade_position()` is called very frequently for the duration of a trade, so you must keep your implementation as performant as possible.
Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position, no matter if it's a long or short trade.
!!! Note "About stake size"
Using fixed stake size means it will be the amount used for the first order, just like without position adjustment.
If you wish to buy additional orders with DCA, then make sure to leave enough funds in the wallet for that.
@ -663,7 +665,7 @@ class DigDeeperStrategy(IStrategy):
return None
filled_buys = trade.select_filled_orders('buy')
count_of_buys = trade.nr_of_successful_buys
count_of_entries = trade.nr_of_successful_entries
# Allow up to 3 additional increasingly larger buys (4 in total)
# Initial buy is 1x
# If that falls to -5% profit, we buy 1.25x more, average profit should increase to roughly -2.2%
@ -676,7 +678,7 @@ class DigDeeperStrategy(IStrategy):
# This returns first order stake size
stake_amount = filled_buys[0].cost
# This then calculates current safety order size
stake_amount = stake_amount * (1 + (count_of_buys * 0.25))
stake_amount = stake_amount * (1 + (count_of_entries * 0.25))
return stake_amount
except Exception as exception:
return None

View File

@ -510,7 +510,7 @@ class FreqtradeBot(LoggingMixin):
"""
# TODO-lev: Check what changes are necessary for DCA in relation to shorts.
if self.strategy.max_entry_position_adjustment > -1:
count_of_buys = trade.nr_of_successful_buys
count_of_buys = trade.nr_of_successful_entries
if count_of_buys > self.strategy.max_entry_position_adjustment:
logger.debug(f"Max adjustment entries for {trade.pair} has been reached.")
return

View File

@ -464,11 +464,11 @@ class Backtesting:
# Check if we need to adjust our current positions
if self.strategy.position_adjustment_enable:
check_adjust_buy = True
check_adjust_entry = True
if self.strategy.max_entry_position_adjustment > -1:
count_of_buys = trade.nr_of_successful_buys
check_adjust_buy = (count_of_buys <= self.strategy.max_entry_position_adjustment)
if check_adjust_buy:
entry_count = trade.nr_of_successful_entries
check_adjust_entry = (entry_count <= self.strategy.max_entry_position_adjustment)
if check_adjust_entry:
trade = self._get_adjust_trade_entry_for_candle(trade, sell_row)
sell_candle_time: datetime = sell_row[DATE_IDX].to_pydatetime()
@ -729,7 +729,7 @@ class Backtesting:
for pair in open_trades.keys():
if len(open_trades[pair]) > 0:
for trade in open_trades[pair]:
if trade.open_order_id and trade.nr_of_successful_buys == 0:
if trade.open_order_id and trade.nr_of_successful_entries == 0:
# Ignore trade if buy-order did not fill yet
continue
sell_row = data[pair][-1]
@ -782,7 +782,7 @@ class Backtesting:
if timedout:
if order.side == 'buy':
self.timedout_entry_orders += 1
if trade.nr_of_successful_buys == 0:
if trade.nr_of_successful_entries == 0:
# Remove trade due to buy timeout expiration.
return True
else:

View File

@ -889,6 +889,8 @@ class LocalTrade():
total_stake += tmp_price * tmp_amount
if total_amount > 0:
# TODO-lev: This should update leverage as well -
# as averaged trades might have different leverage
self.open_rate = total_stake / total_amount
self.stake_amount = total_stake
self.amount = total_amount
@ -936,10 +938,28 @@ class LocalTrade():
(o.filled or 0) > 0 and
o.status in NON_OPEN_EXCHANGE_STATES]
@property
def nr_of_successful_entries(self) -> int:
"""
Helper function to count the number of entry orders that have been filled.
:return: int count of entry orders that have been filled for this trade.
"""
return len(self.select_filled_orders(self.enter_side))
@property
def nr_of_successful_exits(self) -> int:
"""
Helper function to count the number of exit orders that have been filled.
:return: int count of exit orders that have been filled for this trade.
"""
return len(self.select_filled_orders(self.exit_side))
@property
def nr_of_successful_buys(self) -> int:
"""
Helper function to count the number of buy orders that have been filled.
WARNING: Please use nr_of_successful_entries for short support.
:return: int count of buy orders that have been filled for this trade.
"""
@ -949,6 +969,7 @@ class LocalTrade():
def nr_of_successful_sells(self) -> int:
"""
Helper function to count the number of sell orders that have been filled.
WARNING: Please use nr_of_successful_exits for short support.
:return: int count of sell orders that have been filled for this trade.
"""
return len(self.select_filled_orders('sell'))

View File

@ -261,11 +261,11 @@ class RPC:
profit_str
]
if self._config.get('position_adjustment_enable', False):
max_buy_str = ''
max_entry_str = ''
if self._config.get('max_entry_position_adjustment', -1) > 0:
max_buy_str = f"/{self._config['max_entry_position_adjustment'] + 1}"
filled_buys = trade.nr_of_successful_buys
detail_trade.append(f"{filled_buys}{max_buy_str}")
max_entry_str = f"/{self._config['max_entry_position_adjustment'] + 1}"
filled_entries = trade.nr_of_successful_entries
detail_trade.append(f"{filled_entries}{max_entry_str}")
trades_list.append(detail_trade)
profitcol = "Profit"
if self._fiat_converter:

View File

@ -2418,6 +2418,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee):
assert trade.fee_open_cost == o1_fee_cost
assert trade.open_trade_value == o1_trade_val
assert trade.nr_of_successful_buys == 1
assert trade.nr_of_successful_entries == 1
order2 = Order(
ft_order_side='buy',
@ -2554,6 +2555,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee):
assert trade.fee_open_cost == 3 * o1_fee_cost
assert trade.open_trade_value == 3 * o1_trade_val
assert trade.nr_of_successful_buys == 3
assert trade.nr_of_successful_entries == 3
@pytest.mark.usefixtures("init_persistence")