Merge pull request #6260 from stash86/pos_adjust
Add max_buy_position_adjustment as attribute
This commit is contained in:
@@ -371,7 +371,9 @@ CONF_SCHEMA = {
|
||||
'type': 'string',
|
||||
'enum': AVAILABLE_DATAHANDLERS,
|
||||
'default': 'jsongz'
|
||||
}
|
||||
},
|
||||
'position_adjustment_enable': {'type': 'boolean', 'default': False},
|
||||
'max_entry_position_adjustment': {'type': ['integer', 'number'], 'minimum': -1},
|
||||
},
|
||||
'definitions': {
|
||||
'exchange': {
|
||||
|
@@ -462,8 +462,8 @@ class FreqtradeBot(LoggingMixin):
|
||||
try:
|
||||
self.check_and_call_adjust_trade_position(trade)
|
||||
except DependencyException as exception:
|
||||
logger.warning('Unable to adjust position of trade for %s: %s',
|
||||
trade.pair, exception)
|
||||
logger.warning(
|
||||
f"Unable to adjust position of trade for {trade.pair}: {exception}")
|
||||
|
||||
def check_and_call_adjust_trade_position(self, trade: Trade):
|
||||
"""
|
||||
@@ -471,6 +471,13 @@ class FreqtradeBot(LoggingMixin):
|
||||
If the strategy triggers the adjustment, a new order gets issued.
|
||||
Once that completes, the existing trade is modified to match new data.
|
||||
"""
|
||||
if self.strategy.max_entry_position_adjustment > -1:
|
||||
count_of_buys = trade.nr_of_successful_buys
|
||||
if count_of_buys > self.strategy.max_entry_position_adjustment:
|
||||
logger.debug(f"Max adjustment entries for {trade.pair} has been reached.")
|
||||
return
|
||||
else:
|
||||
logger.debug("Max adjustment entries is set to unlimited.")
|
||||
current_rate = self.exchange.get_rate(trade.pair, refresh=True, side="buy")
|
||||
current_profit = trade.calc_profit_ratio(current_rate)
|
||||
|
||||
|
@@ -381,7 +381,12 @@ class Backtesting:
|
||||
|
||||
# Check if we need to adjust our current positions
|
||||
if self.strategy.position_adjustment_enable:
|
||||
trade = self._get_adjust_trade_entry_for_candle(trade, sell_row)
|
||||
check_adjust_buy = 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:
|
||||
trade = self._get_adjust_trade_entry_for_candle(trade, sell_row)
|
||||
|
||||
sell_candle_time = sell_row[DATE_IDX].to_pydatetime()
|
||||
sell = self.strategy.should_sell(trade, sell_row[OPEN_IDX], # type: ignore
|
||||
|
@@ -97,7 +97,8 @@ class StrategyResolver(IResolver):
|
||||
("sell_profit_offset", 0.0),
|
||||
("disable_dataframe_checks", False),
|
||||
("ignore_buying_expired_candle_after", 0),
|
||||
("position_adjustment_enable", False)
|
||||
("position_adjustment_enable", False),
|
||||
("max_entry_position_adjustment", -1),
|
||||
]
|
||||
for attribute, default in attributes:
|
||||
StrategyResolver._override_attribute_helper(strategy, config,
|
||||
|
@@ -173,6 +173,8 @@ class ShowConfig(BaseModel):
|
||||
bot_name: str
|
||||
state: str
|
||||
runmode: str
|
||||
position_adjustment_enable: bool
|
||||
max_entry_position_adjustment: int
|
||||
|
||||
|
||||
class TradeSchema(BaseModel):
|
||||
|
@@ -136,7 +136,12 @@ class RPC:
|
||||
'ask_strategy': config.get('ask_strategy', {}),
|
||||
'bid_strategy': config.get('bid_strategy', {}),
|
||||
'state': str(botstate),
|
||||
'runmode': config['runmode'].value
|
||||
'runmode': config['runmode'].value,
|
||||
'position_adjustment_enable': config.get('position_adjustment_enable', False),
|
||||
'max_entry_position_adjustment': (
|
||||
config['max_entry_position_adjustment']
|
||||
if config['max_entry_position_adjustment'] != float('inf')
|
||||
else -1)
|
||||
}
|
||||
return val
|
||||
|
||||
@@ -247,8 +252,9 @@ class RPC:
|
||||
profit_str
|
||||
]
|
||||
if self._config.get('position_adjustment_enable', False):
|
||||
filled_buys = trade.select_filled_orders('buy')
|
||||
detail_trade.append(str(len(filled_buys)))
|
||||
max_buy = self._config['max_entry_position_adjustment'] + 1
|
||||
filled_buys = trade.nr_of_successful_buys
|
||||
detail_trade.append(f"{filled_buys}/{max_buy}")
|
||||
trades_list.append(detail_trade)
|
||||
profitcol = "Profit"
|
||||
if self._fiat_converter:
|
||||
|
@@ -1347,6 +1347,14 @@ class Telegram(RPCHandler):
|
||||
else:
|
||||
sl_info = f"*Stoploss:* `{val['stoploss']}`\n"
|
||||
|
||||
if val['position_adjustment_enable']:
|
||||
pa_info = (
|
||||
f"*Position adjustment:* On\n"
|
||||
f"*Max enter position adjustment:* `{val['max_entry_position_adjustment']}`\n"
|
||||
)
|
||||
else:
|
||||
pa_info = "*Position adjustment:* Off\n"
|
||||
|
||||
self._send_msg(
|
||||
f"*Mode:* `{'Dry-run' if val['dry_run'] else 'Live'}`\n"
|
||||
f"*Exchange:* `{val['exchange']}`\n"
|
||||
@@ -1356,6 +1364,7 @@ class Telegram(RPCHandler):
|
||||
f"*Ask strategy:* ```\n{json.dumps(val['ask_strategy'])}```\n"
|
||||
f"*Bid strategy:* ```\n{json.dumps(val['bid_strategy'])}```\n"
|
||||
f"{sl_info}"
|
||||
f"{pa_info}"
|
||||
f"*Timeframe:* `{val['timeframe']}`\n"
|
||||
f"*Strategy:* `{val['strategy']}`\n"
|
||||
f"*Current state:* `{val['state']}`"
|
||||
|
@@ -108,6 +108,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
|
||||
# Position adjustment is disabled by default
|
||||
position_adjustment_enable: bool = False
|
||||
max_entry_position_adjustment: int = -1
|
||||
|
||||
# Number of seconds after which the candle will no longer result in a buy on expired candles
|
||||
ignore_buying_expired_candle_after: int = 0
|
||||
|
Reference in New Issue
Block a user