test(factor): test_analyzer三个never-ran测试修复——补read_db_daily假bars(analyzer真读库建prices,缺bars触发DBG空守卫短路tears/IC)+factor日期对齐生产aware口径(Asia/Shanghai);此批测试原在任何环境都没跑过(Mac缺依赖skip/容器缺pytest/CI只跑data_platform),Mac补齐lock依赖后暴露;全量900绿 [nas]
This commit is contained in:
@@ -6,6 +6,22 @@ sys.path.insert(0, _VNPY_SRC)
|
||||
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
from types import SimpleNamespace
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
_SH = ZoneInfo("Asia/Shanghai")
|
||||
|
||||
|
||||
def _fake_bars(symbol, days, price=100.0):
|
||||
"""read_db_daily 假 bars。analyzer 会单独调 read_db_daily 取 close 建 prices,
|
||||
且 prices 日期须与 factor 日期对齐(aware, Asia/Shanghai)——不喂 bars 会触发
|
||||
DBG empty 守卫直接 continue,tears/IC 永不被调到(2026-08-15 前这批测试在
|
||||
任何环境都没跑过:Mac 缺依赖 skip/容器缺 pytest/CI 只跑 data_platform)。"""
|
||||
return [
|
||||
SimpleNamespace(datetime=datetime(2024, 1, d), vt_symbol=symbol, close_price=price)
|
||||
for d in days
|
||||
]
|
||||
|
||||
|
||||
def test_run_factor_analysis_returns_report():
|
||||
@@ -113,12 +129,17 @@ def test_run_factor_analysis_calls_tears(tmp_path):
|
||||
|
||||
with patch("sanguo_factor.analyzer.AlphaLabSession") as MS, \
|
||||
patch("sanguo_factor.analyzer.get_clean_factor_and_forward_returns") as MC, \
|
||||
patch("sanguo_factor.analyzer.create_full_tear_sheet") as MT:
|
||||
patch("sanguo_factor.analyzer.create_full_tear_sheet") as MT, \
|
||||
patch("sanguo_data.datareader.read_db_daily",
|
||||
return_value=_fake_bars("600000", (2, 3, 4, 5, 8))):
|
||||
import polars as pl
|
||||
# 非空 + aware 日期(生产 compute_factors 会 localize;naive 会被 prices 对齐
|
||||
# isin 过滤成空触发 DBG 守卫)
|
||||
_days = (2, 3, 4, 5, 8)
|
||||
MS.return_value.compute_factors.return_value = pl.DataFrame({
|
||||
"datetime": [],
|
||||
"vt_symbol": [],
|
||||
"ma5": []
|
||||
"datetime": [datetime(2024, 1, d, tzinfo=_SH) for d in _days],
|
||||
"vt_symbol": ["600000"] * len(_days),
|
||||
"ma5": [0.5] * len(_days),
|
||||
})
|
||||
MC.return_value = MagicMock()
|
||||
report = run_factor_analysis(
|
||||
@@ -144,7 +165,7 @@ def test_run_factor_analysis_extracts_ic_values(tmp_path):
|
||||
from sanguo_factor.analyzer import run_factor_analysis
|
||||
|
||||
# Create mock factor_data with MultiIndex (datetime, asset) and IC columns
|
||||
dates = pd.date_range("2024-01-01", periods=10, freq="D")
|
||||
dates = pd.date_range("2024-01-01", periods=10, freq="D", tz="Asia/Shanghai")
|
||||
assets = ["AAPL", "GOOGL"]
|
||||
index = pd.MultiIndex.from_product([dates, assets], names=["datetime", "asset"])
|
||||
|
||||
@@ -162,7 +183,7 @@ def test_run_factor_analysis_extracts_ic_values(tmp_path):
|
||||
"10D": [0.12, 0.10, 0.13, 0.11, 0.12, 0.11, 0.12, 0.10, 0.11, 0.12]
|
||||
}, index=dates)
|
||||
|
||||
# Mock polars DataFrame
|
||||
# Mock polars DataFrame(datetime 用带时区 ISO 串,与 _fake_bars localize 后对齐)
|
||||
mock_pl_df = MagicMock()
|
||||
mock_pl_df.to_pandas.return_value = pd.DataFrame({
|
||||
"datetime": [d.isoformat() for d in dates for _ in assets],
|
||||
@@ -174,7 +195,9 @@ def test_run_factor_analysis_extracts_ic_values(tmp_path):
|
||||
with patch("sanguo_factor.analyzer.AlphaLabSession") as MS, \
|
||||
patch("sanguo_factor.analyzer.get_clean_factor_and_forward_returns") as MC, \
|
||||
patch("sanguo_factor.analyzer.create_full_tear_sheet") as MT, \
|
||||
patch("sanguo_factor.analyzer.factor_information_coefficient") as MIC:
|
||||
patch("sanguo_factor.analyzer.factor_information_coefficient") as MIC, \
|
||||
patch("sanguo_data.datareader.read_db_daily",
|
||||
return_value=_fake_bars("AAPL", range(1, 11)) + _fake_bars("GOOGL", range(1, 11))):
|
||||
|
||||
# Mock compute_factors to return polars DataFrame
|
||||
MS.return_value.compute_factors.return_value = mock_pl_df
|
||||
@@ -221,10 +244,10 @@ def test_run_factor_analysis_ic_extraction_fails_gracefully(tmp_path):
|
||||
from sanguo_factor.analyzer import run_factor_analysis
|
||||
import pandas as pd
|
||||
|
||||
# Mock polars DataFrame
|
||||
# Mock polars DataFrame(datetime 带时区,与 _fake_bars 对齐防 DBG 空守卫)
|
||||
mock_pl_df = MagicMock()
|
||||
mock_pl_df.to_pandas.return_value = pd.DataFrame({
|
||||
"datetime": ["2024-01-01"],
|
||||
"datetime": ["2024-01-01T00:00:00+08:00"],
|
||||
"vt_symbol": ["AAPL"],
|
||||
"ma5": [0.5],
|
||||
"close": [100.0]
|
||||
@@ -233,7 +256,9 @@ def test_run_factor_analysis_ic_extraction_fails_gracefully(tmp_path):
|
||||
with patch("sanguo_factor.analyzer.AlphaLabSession") as MS, \
|
||||
patch("sanguo_factor.analyzer.get_clean_factor_and_forward_returns") as MC, \
|
||||
patch("sanguo_factor.analyzer.create_full_tear_sheet") as MT, \
|
||||
patch("sanguo_factor.analyzer.factor_information_coefficient") as MIC:
|
||||
patch("sanguo_factor.analyzer.factor_information_coefficient") as MIC, \
|
||||
patch("sanguo_data.datareader.read_db_daily",
|
||||
return_value=_fake_bars("AAPL", (1, 2))):
|
||||
|
||||
MS.return_value.compute_factors.return_value = mock_pl_df
|
||||
|
||||
|
||||
Reference in New Issue
Block a user