mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 23:47:46 +00:00
222 lines
9.0 KiB
Python
222 lines
9.0 KiB
Python
"""Tests for factor_coder — evaluators, task, workspace."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
|
|
# =============================================================================
|
|
# FactorTask
|
|
# =============================================================================
|
|
|
|
|
|
class TestFactorTask:
|
|
def test_construction_fields(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
t = FactorTask(
|
|
factor_name="f1",
|
|
factor_description="desc",
|
|
factor_formulation="formula",
|
|
variables={"x": 1},
|
|
resource="r1",
|
|
)
|
|
assert t.factor_name == "f1"
|
|
assert t.factor_description == "desc"
|
|
assert t.factor_formulation == "formula"
|
|
assert t.variables == {"x": 1}
|
|
assert t.factor_resources == "r1"
|
|
assert t.factor_implementation is False
|
|
assert t.base_code is None # from CoSTEERTask
|
|
|
|
def test_get_task_information(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
t = FactorTask("f1", "desc", "formula", variables={"x": 1})
|
|
info = t.get_task_information()
|
|
assert "factor_name: f1" in info
|
|
assert "factor_description: desc" in info
|
|
assert "factor_formulation: formula" in info
|
|
assert "variables: {'x': 1}" in info
|
|
|
|
def test_get_task_brief_information(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
t = FactorTask("f1", "desc", "formula")
|
|
info = t.get_task_brief_information()
|
|
assert "factor_name: f1" in info
|
|
|
|
def test_get_task_information_and_implementation_result(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
t = FactorTask("f1", "desc", "formula")
|
|
result = t.get_task_information_and_implementation_result()
|
|
assert result["factor_name"] == "f1"
|
|
assert result["factor_description"] == "desc"
|
|
assert "factor_implementation" in result
|
|
|
|
def test_from_dict(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
d = {
|
|
"factor_name": "f2",
|
|
"factor_description": "d2",
|
|
"factor_formulation": "f2",
|
|
"variables": {},
|
|
"resource": None,
|
|
"factor_implementation": True,
|
|
}
|
|
t = FactorTask.from_dict(d)
|
|
assert t.factor_name == "f2"
|
|
assert t.factor_implementation is True
|
|
|
|
def test_repr(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
t = FactorTask("myfactor", "desc", "formula")
|
|
assert "FactorTask" in repr(t)
|
|
assert "myfactor" in repr(t)
|
|
|
|
|
|
# =============================================================================
|
|
# FactorFBWorkspace
|
|
# =============================================================================
|
|
|
|
|
|
class TestFactorFBWorkspace:
|
|
def test_init_sets_workspace_path(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorFBWorkspace, FactorTask
|
|
t = FactorTask("f1", "desc", "formula")
|
|
ws = FactorFBWorkspace(target_task=t)
|
|
assert ws.workspace_path is not None
|
|
# Directory is created lazily by execute(), not in __init__
|
|
assert isinstance(ws.workspace_path, Path)
|
|
|
|
def test_execute_returns_message_and_dataframe(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorFBWorkspace, FactorTask
|
|
t = FactorTask("f1", "desc", "formula")
|
|
t.version = 1
|
|
ws = FactorFBWorkspace(target_task=t)
|
|
# Inject valid factor code
|
|
ws.inject_files(**{
|
|
"factor.py": (
|
|
"import pandas as pd\n"
|
|
"import numpy as np\n"
|
|
"data = pd.read_hdf('intraday_pv.h5', key='data')\n"
|
|
"factor_val = data['$close'].pct_change()\n"
|
|
"factor_val = factor_val.to_frame('f1')\n"
|
|
"factor_val.to_hdf('result.h5', key='data', mode='w')\n"
|
|
),
|
|
})
|
|
msg, df = ws.execute()
|
|
assert isinstance(msg, str)
|
|
assert df is not None
|
|
|
|
def test_execute_succeeds_and_returns_data(self):
|
|
from rdagent.components.coder.factor_coder.factor import FactorFBWorkspace, FactorTask
|
|
t = FactorTask("fl1", "desc", "formula")
|
|
ws = FactorFBWorkspace(target_task=t)
|
|
ws.inject_files(**{
|
|
"factor.py": (
|
|
"import pandas as pd\n"
|
|
"data = pd.read_hdf('intraday_pv.h5', key='data')\n"
|
|
"factor_val = data['$close'].pct_change().to_frame('fl1')\n"
|
|
"factor_val.to_hdf('result.h5', key='data', mode='w')\n"
|
|
),
|
|
})
|
|
msg, df = ws.execute()
|
|
assert FactorFBWorkspace.FB_EXEC_SUCCESS in msg
|
|
assert FactorFBWorkspace.FB_OUTPUT_FILE_FOUND in msg
|
|
assert df is not None
|
|
|
|
|
|
# =============================================================================
|
|
# FactorEvaluatorForCoder (partial integration)
|
|
# =============================================================================
|
|
|
|
|
|
class TestFactorEvaluatorForCoder:
|
|
def test_init_creates_sub_evaluators(self):
|
|
from rdagent.components.coder.factor_coder.evaluators import FactorEvaluatorForCoder
|
|
mock_scen = MagicMock()
|
|
eva = FactorEvaluatorForCoder(scen=mock_scen)
|
|
assert eva.value_evaluator is not None
|
|
assert eva.code_evaluator is not None
|
|
assert eva.final_decision_evaluator is not None
|
|
|
|
def test_evaluate_with_none_implementation(self):
|
|
from rdagent.components.coder.factor_coder.evaluators import FactorEvaluatorForCoder
|
|
eva = FactorEvaluatorForCoder(scen=MagicMock())
|
|
assert eva.evaluate(target_task=MagicMock(), implementation=None) is None
|
|
|
|
def test_evaluate_returns_queried_knowledge_if_present(self):
|
|
from rdagent.components.coder.factor_coder.evaluators import FactorEvaluatorForCoder
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
|
|
eva = FactorEvaluatorForCoder(scen=MagicMock())
|
|
|
|
t = FactorTask("f1", "desc", "formula")
|
|
qk = MagicMock()
|
|
qk.success_task_to_knowledge_dict = {"info_f1": MagicMock(feedback="cached_fb")}
|
|
t.get_task_information = MagicMock(return_value="info_f1")
|
|
qk.failed_task_info_set = set()
|
|
|
|
fb = eva.evaluate(target_task=t, implementation=MagicMock(), queried_knowledge=qk)
|
|
assert fb == "cached_fb" # returned from cache
|
|
|
|
def test_evaluate_skips_failed_task(self):
|
|
from rdagent.components.coder.factor_coder.evaluators import FactorEvaluatorForCoder
|
|
from rdagent.components.coder.factor_coder.factor import FactorTask
|
|
|
|
eva = FactorEvaluatorForCoder(scen=MagicMock())
|
|
|
|
t = FactorTask("f1", "desc", "formula")
|
|
qk = MagicMock()
|
|
qk.success_task_to_knowledge_dict = {}
|
|
t.get_task_information = MagicMock(return_value="info_f1")
|
|
qk.failed_task_info_set = {"info_f1"}
|
|
|
|
fb = eva.evaluate(target_task=t, implementation=MagicMock(), queried_knowledge=qk)
|
|
assert fb.final_decision is False
|
|
assert "failed too many times" in fb.execution_feedback
|
|
|
|
|
|
# =============================================================================
|
|
# FactorEvaluator (eva_utils) — constructors and identity
|
|
# =============================================================================
|
|
|
|
|
|
class TestFactorEvaluatorsInit:
|
|
def test_factor_inf_evaluator_init(self):
|
|
from rdagent.components.coder.factor_coder.eva_utils import FactorInfEvaluator
|
|
eva = FactorInfEvaluator()
|
|
assert str(eva) == "FactorInfEvaluator"
|
|
|
|
def test_factor_single_column_evaluator_init(self):
|
|
from rdagent.components.coder.factor_coder.eva_utils import FactorSingleColumnEvaluator
|
|
eva = FactorSingleColumnEvaluator()
|
|
assert str(eva) == "FactorSingleColumnEvaluator"
|
|
|
|
def test_factor_output_format_evaluator_init(self):
|
|
from rdagent.components.coder.factor_coder.eva_utils import FactorOutputFormatEvaluator
|
|
eva = FactorOutputFormatEvaluator()
|
|
assert str(eva) == "FactorOutputFormatEvaluator"
|
|
|
|
def test_factor_missing_values_evaluator_init(self):
|
|
from rdagent.components.coder.factor_coder.eva_utils import FactorMissingValuesEvaluator
|
|
eva = FactorMissingValuesEvaluator()
|
|
assert str(eva) == "FactorMissingValuesEvaluator"
|
|
|
|
def test_factor_correlation_evaluator_init(self):
|
|
from rdagent.components.coder.factor_coder.eva_utils import FactorCorrelationEvaluator
|
|
eva = FactorCorrelationEvaluator(hard_check=True)
|
|
assert eva.hard_check is True
|
|
assert str(eva) == "FactorCorrelationEvaluator"
|
|
|
|
def test_factor_value_evaluator_init(self):
|
|
from rdagent.components.coder.factor_coder.eva_utils import FactorValueEvaluator
|
|
mock_scen = MagicMock()
|
|
eva = FactorValueEvaluator(mock_scen)
|
|
assert eva.scen is mock_scen
|