From 5f2682a7e87d7a351be047a0631e35759a7c0122 Mon Sep 17 00:00:00 2001 From: Whning0513 Date: Thu, 4 Jun 2026 22:38:03 +0800 Subject: [PATCH] fix: handle missing minute-level data in get_higher_eq_freq_feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1854 When running backtests with time_per_step='30min', the benchmark calculation in PortfolioMetrics calls get_higher_eq_freq_feature() with freq='30min'. The benchmark (CSI300) only has daily data, so D.features() raises ValueError/KeyError. The minute-level fallback branch hardcoded a fallback to '1min' without a try/except wrapper — if 1min data also doesn't exist (e.g., when only 30min daily data files are available), the ValueError propagates up with the misleading message 'can't find a freq from [Freq(30min)] that can resample to 1min!'. Fix: wrap the 1min fallback in the same try/except pattern used by the day/week/month branch, adding a 'day' fallback when 1min is unavailable. Also fix type inconsistency in Freq.get_recent_freq(): the first candidate was stored as str(_freq) while subsequent candidates stored the raw _freq (str|Freq), making the return type unpredictable. --- qlib/utils/resam.py | 8 ++++++-- qlib/utils/time.py | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/qlib/utils/resam.py b/qlib/utils/resam.py index 99aedfcd50c..f683b32af7a 100644 --- a/qlib/utils/resam.py +++ b/qlib/utils/resam.py @@ -92,8 +92,12 @@ def get_higher_eq_freq_feature(instruments, fields, start_time=None, end_time=No _result = D.features(instruments, fields, start_time, end_time, freq="1min", disk_cache=disk_cache) _freq = "1min" elif norm_freq == Freq.NORM_FREQ_MINUTE: - _result = D.features(instruments, fields, start_time, end_time, freq="1min", disk_cache=disk_cache) - _freq = "1min" + try: + _result = D.features(instruments, fields, start_time, end_time, freq="1min", disk_cache=disk_cache) + _freq = "1min" + except (ValueError, KeyError): + _result = D.features(instruments, fields, start_time, end_time, freq="day", disk_cache=disk_cache) + _freq = "day" else: raise ValueError(f"freq {freq} is not supported") from value_key_e return _result, _freq diff --git a/qlib/utils/time.py b/qlib/utils/time.py index b052f6ab9f7..50f2d95790a 100644 --- a/qlib/utils/time.py +++ b/qlib/utils/time.py @@ -249,9 +249,9 @@ def get_recent_freq(base_freq: Union[str, "Freq"], freq_list: List[Union[str, "F if _min_delta < 0: continue if min_freq is None: - min_freq = (_min_delta, str(_freq)) + min_freq = (_min_delta, Freq(_freq)) continue - min_freq = min_freq if min_freq[0] <= _min_delta else (_min_delta, _freq) + min_freq = min_freq if min_freq[0] <= _min_delta else (_min_delta, Freq(_freq)) return min_freq[1] if min_freq else None