From: Jérôme Benoit Date: Tue, 28 Jul 2026 15:15:27 +0000 (+0200) Subject: fix(quickadapter): preserve take-profit JSON history (#145) X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=7dc50004f3f25e5099f7594dff14d08a7545c295;p=freqai-strategies.git fix(quickadapter): preserve take-profit JSON history (#145) * fix(quickadapter): preserve take-profit JSON history * refactor(quickadapter): drop over-engineered take-profit history migration Remove the history_v2 versioned key, its legacy-migration branches, the scalar cd_type/JSON-string recovery paths and the getter write side effect. The history custom-data row has only ever been written as a dict, so its cd_type is always "dict" and those defensive branches are unreachable dead code; a stored dict round-trips as a dict with list fields, and the shared callback wrapper logs rather than silently swallows exceptions. _get_trade_history reverts to the minimal reader keyed by the literal "history", matching the other custom-data row keys in this file. The take-profit JSON fix for #134 is preserved: the _TakeProfitHistoryEntry alias keeps the list arm and safe_append_trade_take_profit_price still accepts a two-element tuple or list with a non-bool int stage and non-bool numeric price. --- diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 4ef5055..c81dcec 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -105,6 +105,7 @@ CandleDeviationCacheKey = tuple[ str, DfSignature, float, float, int, InterpolationDirection, float ] CandleThresholdCacheKey = tuple[str, DfSignature, str, int, float, float] +_TakeProfitHistoryEntry = float | tuple[int, float] | list[int | float] class _TradeHistory(TypedDict): @@ -112,7 +113,7 @@ class _TradeHistory(TypedDict): # _UNREALIZED_PNL_TIMEFRAME_KEY / _LEGACY_UNREALIZED_PNL_TIMEFRAME_MINUTES_KEY # constants (a TypedDict field cannot reference a constant). unrealized_pnl: list[float] - take_profit_price: list[float | tuple[int, float]] + take_profit_price: list[_TakeProfitHistoryEntry] unrealized_pnl_candle_date: NotRequired[str] unrealized_pnl_timeframe: NotRequired[str] unrealized_pnl_timeframe_minutes: NotRequired[int] @@ -1540,7 +1541,7 @@ class QuickAdapterV3(IStrategy): @staticmethod def get_trade_take_profit_price_history( trade: Trade, - ) -> list[float | tuple[int, float]]: + ) -> list[_TakeProfitHistoryEntry]: history = QuickAdapterV3._get_trade_history(trade) return history.get("take_profit_price", []) @@ -1619,7 +1620,7 @@ class QuickAdapterV3(IStrategy): def append_trade_take_profit_price( self, trade: Trade, take_profit_price: float, exit_stage: int - ) -> list[float | tuple[int, float]]: + ) -> list[_TakeProfitHistoryEntry]: history = QuickAdapterV3._get_trade_history(trade) price_history = history.setdefault("take_profit_price", []) price_history.append((exit_stage, take_profit_price)) @@ -1631,7 +1632,7 @@ class QuickAdapterV3(IStrategy): def safe_append_trade_take_profit_price( self, trade: Trade, take_profit_price: float, exit_stage: int - ) -> list[float | tuple[int, float]]: + ) -> list[_TakeProfitHistoryEntry]: trade_take_profit_price_history = ( QuickAdapterV3.get_trade_take_profit_price_history(trade) ) @@ -1642,13 +1643,21 @@ class QuickAdapterV3(IStrategy): ) previous_exit_stage = None previous_take_profit_price = None - if isinstance(previous_take_profit_entry, tuple): - previous_exit_stage = ( - previous_take_profit_entry[0] if previous_take_profit_entry else None - ) - previous_take_profit_price = ( - previous_take_profit_entry[1] if previous_take_profit_entry else None + if ( + isinstance(previous_take_profit_entry, (tuple, list)) + and len(previous_take_profit_entry) == 2 + ): + candidate_exit_stage, candidate_take_profit_price = ( + previous_take_profit_entry ) + if ( + isinstance(candidate_exit_stage, int) + and not isinstance(candidate_exit_stage, bool) + and isinstance(candidate_take_profit_price, (int, float)) + and not isinstance(candidate_take_profit_price, bool) + ): + previous_exit_stage = candidate_exit_stage + previous_take_profit_price = candidate_take_profit_price elif isinstance(previous_take_profit_entry, float): previous_exit_stage = -1 previous_take_profit_price = previous_take_profit_entry