From: Jérôme Benoit Date: Thu, 20 Mar 2025 11:47:32 +0000 (+0100) Subject: feat(qav3): make SL/TP labeling window aware X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=3d0a3f9e89a06e2389da7a8bc4775dceb5774d69;p=freqai-strategies.git feat(qav3): make SL/TP labeling window aware Signed-off-by: Jérôme Benoit --- diff --git a/quickadapter/docs/ labeling_window.txt b/quickadapter/docs/ labeling_window.txt new file mode 100644 index 0000000..e1f0068 --- /dev/null +++ b/quickadapter/docs/ labeling_window.txt @@ -0,0 +1,42 @@ +- = candle = { open, close, high, low, volume, natr_ratio_label_window, ... } dataframe + +Labeling window: +---------------- + +[ label window ] size can change because of HPO + + now + | +------------------------------------------------------------------------------------- + ][ label window ][ label window ][ label window ][ label window ] + +Price movement expectation over the labeling window: +---------------------------------------------------- + +trade candles = current candle date - trade candle date / timeframe (in the same time unit) + + trade candle + | +------------------------------- -> trade natr * trade open rate = expected price movement in the future label window candles +[ trade natr label window ] + + + trade candle current candle + | | +--------------------------------- -> current natr * current rate = expected price movement in the future label window candles +[ current natr label window ] + + trade candle current candle + | | +------------------------------------------------------------------ -> current natr * current rate * trade candles // label window = expected price movement in the future +[ current natr label window ][ current natr label window ] (trade candles // label window) label window candles + + + + + + + + + + diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 37e63b7..e0744f0 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -44,7 +44,7 @@ class QuickAdapterV3(IStrategy): INTERFACE_VERSION = 3 def version(self) -> str: - return "3.1.11" + return "3.1.12" timeframe = "5m" @@ -398,12 +398,29 @@ class QuickAdapterV3(IStrategy): entry_candle = df.loc[(df["date"] == entry_date)] if entry_candle.empty: return None - return entry_candle.squeeze() + return entry_candle + + def get_trade_candles(self, df: DataFrame, trade: Trade) -> int | None: + entry_candle = self.get_trade_entry_candle(df, trade) + if isna(entry_candle): + return None + entry_candle = entry_candle.squeeze() + entry_candle_date = entry_candle["date"] + current_candle_date = df["date"].iloc[-1] + if isna(current_candle_date): + return None + trade_duration_minutes = ( + current_candle_date - entry_candle_date + ).total_seconds() / 60.0 + return max( + int(trade_duration_minutes / timeframe_to_minutes(self.timeframe)), 1 + ) def get_trade_entry_natr(self, df: DataFrame, trade: Trade) -> float | None: entry_candle = self.get_trade_entry_candle(df, trade) if isna(entry_candle): return None + entry_candle = entry_candle.squeeze() return entry_candle["natr_ratio_labeling_window"] def get_trade_stoploss_distance(self, df: DataFrame, trade: Trade) -> float | None: @@ -423,11 +440,19 @@ class QuickAdapterV3(IStrategy): def get_stoploss_distance( self, df: DataFrame, trade: Trade, current_rate: float ) -> float | None: - trade_stoploss_distance = self.get_trade_stoploss_distance(df, trade) - current_stoploss_distance = self.get_current_stoploss_distance(df, current_rate) - if isna(trade_stoploss_distance) or isna(current_stoploss_distance): + label_window_frequency = self.get_trade_candles(df, trade) // ( + self.get_label_period_candles(trade.pair) * 2 + ) + # trade_stoploss_distance = self.get_trade_stoploss_distance(df, trade) + current_stoploss_distance = self.get_current_stoploss_distance( + df, current_rate + ) / self.get_trade_candles(df, trade) + # if isna(trade_stoploss_distance) or isna(current_stoploss_distance): + # return None + # return max(trade_stoploss_distance, current_stoploss_distance) + if isna(current_stoploss_distance): return None - return max(trade_stoploss_distance, current_stoploss_distance) + return current_stoploss_distance def custom_stoploss( self, @@ -537,7 +562,7 @@ class QuickAdapterV3(IStrategy): ) -> bool: max_open_trades_per_side = self.max_open_trades_per_side() if max_open_trades_per_side >= 0: - open_trades = Trade.get_trades(trade_filter=Trade.is_open.is_(True)) + open_trades = Trade.get_open_trades() num_shorts, num_longs = 0, 0 for trade in open_trades: if "short" in trade.enter_tag: