From bd114eea9587b948ecb490d0ac878d05788d1246 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Tue, 30 Sep 2025 11:40:06 +0200 Subject: [PATCH] refactor(qav3): factor out callable unique hash building MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../user_data/strategies/QuickAdapterV3.py | 19 +++--------------- quickadapter/user_data/strategies/Utils.py | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 6a1273d..463794b 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -1,5 +1,4 @@ import datetime -import functools import hashlib import json import logging @@ -27,6 +26,7 @@ from Utils import ( calculate_quantile, ewo, format_number, + get_callable_sha256, get_distance, get_zl_ma_fn, non_zero_diff, @@ -793,21 +793,8 @@ class QuickAdapterV3(IStrategy): timestamp = int(current_time.timestamp()) candle_duration_secs = max(1, int(self._candle_duration_secs)) candle_start_secs = (timestamp // candle_duration_secs) * candle_duration_secs - callback_code = getattr(callback, "__code__", None) - if callback_code is None and isinstance(callback, functools.partial): - func = callback.func - callback_code = getattr(func, "__code__", None) - if callback_code is None and hasattr(func, "__func__"): - callback_code = getattr(func.__func__, "__code__", None) - if callback_code is None and hasattr(callback, "__func__"): - callback_code = getattr(callback.__func__, "__code__", None) - if callback_code is None and hasattr(callback, "__call__"): - callback_code = getattr(callback.__call__, "__code__", None) - if callback_code is None: - raise ValueError("Unable to retrieve code object from callback") - key = hashlib.sha256( - f"{pair}|{callback_code.co_filename}|{callback_code.co_firstlineno}|{callback_code.co_name}".encode() - ).hexdigest() + callback_hash = get_callable_sha256(callback) + key = hashlib.sha256(f"{pair}|{callback_hash}".encode()).hexdigest() if candle_start_secs != self.last_candle_start_secs.get(key): self.last_candle_start_secs[key] = candle_start_secs try: diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index ccefb83..3610624 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -1,4 +1,6 @@ import copy +import functools +import hashlib import math from enum import IntEnum from functools import lru_cache @@ -111,6 +113,24 @@ def smooth_extrema( ) +def get_callable_sha256(fn: Callable) -> str: + if not callable(fn): + raise ValueError("fn must be callable") + code = getattr(fn, "__code__", None) + if code is None and isinstance(fn, functools.partial): + fn = fn.func + code = getattr(fn, "__code__", None) + if code is None and hasattr(fn, "__func__"): + code = getattr(fn.__func__, "__code__", None) + if code is None and hasattr(fn, "__func__"): + code = getattr(fn.__func__, "__code__", None) + if code is None and hasattr(fn, "__call__"): + code = getattr(fn.__call__, "__code__", None) + if code is None: + raise ValueError("Unable to retrieve code object from fn") + return hashlib.sha256(code.co_code).hexdigest() + + @lru_cache(maxsize=128) def format_number(value: int | float, significant_digits: int = 5) -> str: if not isinstance(value, (int, float)): -- 2.43.0