Bug: FactorDatetimeDailyEvaluator classifies hourly and other sub-daily factor data as daily
Summary
FactorDatetimeDailyEvaluator.evaluate reports sub-daily factor output as daily unless the adjacent datetime difference is exactly one minute.
For example, factor data indexed hourly, every 30 minutes, or every second is currently accepted:
("The generated dataframe is daily.", True)These are not daily observations. The evaluator should reject sub-daily datetime frequencies instead of only rejecting the special one-minute case.
To Reproduce
Check out RD-Agent
mainat commit6762f84f9bc0f5c6486c50a00e128a57ac6c3683.Install RD-Agent from source.
Create
test/qlib/test_factor_datetime_daily_evaluator.py:
import pandas as pd
import pytest
from rdagent.components.coder.factor_coder.eva_utils import (
FactorDatetimeDailyEvaluator,
)
@pytest.mark.parametrize("freq", ["h", "30min", "s"])
def test_datetime_daily_evaluator_rejects_sub_daily_frequency(freq):
datetimes = pd.date_range("2024-01-01 00:00:00", periods=3, freq=freq)
index = pd.MultiIndex.from_product(
[datetimes, ["instrument_1"]],
names=["datetime", "instrument"],
)
gen_df = pd.DataFrame({"factor": [1.0, 2.0, 3.0]}, index=index)
evaluator = object.__new__(FactorDatetimeDailyEvaluator)
evaluator._get_df = lambda _gt_implementation, _implementation: (None, gen_df)
message, is_daily = evaluator.evaluate(None, None)
assert is_daily is False, message- Run:
python -m pytest test/qlib/test_factor_datetime_daily_evaluator.py -q- Observe that all three parameterized cases fail.
Expected Behavior
Hourly, 30-minute, and one-second datetime intervals should be classified as not daily:
is_daily is FalseActual Behavior
Each sub-daily input is classified as daily:
h ('The generated dataframe is daily.', True)
30min ('The generated dataframe is daily.', True)
s ('The generated dataframe is daily.', True)A representative assertion failure is:
AssertionError: The generated dataframe is daily.
assert True is FalseScreenshot
Not applicable; this is a deterministic unit-level reproduction.
Environment
- Name of current operating system: macOS
- Processor architecture: arm64
- Python version: 3.11.15
- RD-Agent version:
0.8.0,main@6762f84f9bc0f5c6486c50a00e128a57ac6c3683 - Package version: pandas
2.3.3, pytest9.1.1
Additional Notes
The root cause appears to be that the evaluator only checks for one exact sub-daily interval:
time_diff = pd.to_datetime(
gen_df.index.get_level_values("datetime")
).to_series().diff().dropna().unique()
if pd.Timedelta(minutes=1) in time_diff:
return (
"The generated dataframe is not daily. The implementation is definitely wrong. Please check the implementation.",
False,
)
return "The generated dataframe is daily.", TrueAny other sub-daily interval, such as hourly or 30-minute data, reaches the final positive result.
A possible fix is to reject datetime differences that are shorter than one day, while still allowing valid daily data with calendar gaps such as weekends or holidays.
Source: microsoft/RD-Agent