diff --git a/docs/bot-basics.md b/docs/bot-basics.md index 80443a0bf..67cc5cd1b 100644 --- a/docs/bot-basics.md +++ b/docs/bot-basics.md @@ -56,7 +56,11 @@ This loop will be repeated again and again until the bot is stopped. * Calculate buy / sell signals (calls `populate_buy_trend()` and `populate_sell_trend()` once per pair). * Loops per candle simulating entry and exit points. * Confirm trade buy / sell (calls `confirm_trade_entry()` and `confirm_trade_exit()` if implemented in the strategy). + * Call `custom_entry_price()` (if implemented in the strategy) to determine entry price (Prices are moved to be within the opening candle). + * Determine stake size by calling the `custom_stake_amount()` callback. * Call `custom_stoploss()` and `custom_sell()` to find custom exit points. + * Call `custom_exit_price()` to determine exit price (Prices are moved to be within the closing candle). + * Generate backtest report output !!! Note diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 7a7756652..869a985ae 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -387,8 +387,9 @@ class AwesomeStrategy(IStrategy): **Example**: If the new_entryprice is 97, the proposed_rate is 100 and the `custom_price_max_distance_ratio` is set to 2%, The retained valid custom entry price will be 98, which is 2% below the current (proposed) rate. -!!! Warning "No backtesting support" - Custom entry-prices are currently not supported during backtesting. +!!! Warning "Backtesting" + While Custom prices are supported in backtesting (starting with 2021.12), prices will be moved to within the candle's high/low prices. + This behavior is currently in testing, and might be changed at a later point. ## Custom order timeout rules diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 1d28a91f5..a561502fa 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -342,10 +342,7 @@ class Backtesting: # use Open rate if open_rate > calculated sell rate return sell_row[OPEN_IDX] - # Use the maximum between close_rate and low as we - # cannot sell outside of a candle. - # Applies when a new ROI setting comes in place and the whole candle is above that. - return min(max(close_rate, sell_row[LOW_IDX]), sell_row[HIGH_IDX]) + return close_rate else: # This should not be reached... @@ -373,6 +370,9 @@ class Backtesting: pair=trade.pair, trade=trade, current_time=sell_row[DATE_IDX], proposed_rate=closerate, current_profit=current_profit) + # Use the maximum between close_rate and low as we cannot sell outside of a candle. + # Applies when a new ROI setting comes in place and the whole candle is above that. + closerate = min(max(closerate, sell_row[LOW_IDX]), sell_row[HIGH_IDX]) # Confirm trade exit: time_in_force = self.strategy.order_time_in_force['sell'] @@ -437,6 +437,9 @@ class Backtesting: pair=pair, current_time=row[DATE_IDX].to_pydatetime(), proposed_rate=row[OPEN_IDX]) # default value is the open rate + # Move rate to within the candle's low/high rate + propose_rate = min(max(propose_rate, row[LOW_IDX]), row[HIGH_IDX]) + min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, propose_rate, -0.05) or 0 max_stake_amount = self.wallets.get_available_stake_amount()