add logging for data sufficiency check and stock evaluation process

This commit is contained in:
Your Name 2025-10-09 20:21:15 +08:00
parent 744829032e
commit 8cc64cd0c0
2 changed files with 75 additions and 1 deletions

View File

@ -208,6 +208,13 @@ def check_data_sufficiency(
broker = DataBroker() broker = DataBroker()
# 记录检查开始
LOGGER.debug(
"开始检查数据充分性 ts_code=%s date=%s min_days=%d",
ts_code, trade_date, min_days,
extra=LOG_EXTRA
)
# 检查历史收盘价数据 # 检查历史收盘价数据
close_series = broker.fetch_series("daily", "close", ts_code, trade_date, min_days) close_series = broker.fetch_series("daily", "close", ts_code, trade_date, min_days)
# 计算有效值的数量 # 计算有效值的数量

View File

@ -12,6 +12,7 @@ from app.features.validation import check_data_sufficiency
from app.utils.config import get_config from app.utils.config import get_config
from app.utils.data_access import DataBroker from app.utils.data_access import DataBroker
from app.utils.db import db_session from app.utils.db import db_session
from app.utils.logging import get_logger
def _get_latest_trading_date() -> datetime.date: def _get_latest_trading_date() -> datetime.date:
@ -36,8 +37,14 @@ def _get_latest_trading_date() -> datetime.date:
def render_stock_evaluation() -> None: def render_stock_evaluation() -> None:
"""渲染股票筛选与评估页面。""" """渲染股票筛选与评估页面。"""
LOGGER = get_logger(__name__)
LOG_EXTRA = {"stage": "stock_evaluation_ui"}
st.subheader("股票筛选与评估") st.subheader("股票筛选与评估")
# 记录页面加载
LOGGER.info("股票筛选与评估页面已加载", extra=LOG_EXTRA)
# 1. 时间范围选择 # 1. 时间范围选择
col1, col2 = st.columns(2) col1, col2 = st.columns(2)
with col1: with col1:
@ -150,6 +157,15 @@ def render_stock_evaluation() -> None:
# 同步评估函数 # 同步评估函数
def run_evaluation_sync(): def run_evaluation_sync():
try: try:
# 记录评估开始
LOGGER.info(
"开始因子评估 因子数量=%s 评估日期=%s%s",
len(selected_factors),
start_date,
end_date,
extra=LOG_EXTRA
)
st.session_state.evaluation_status = 'running' st.session_state.evaluation_status = 'running'
results = [] results = []
@ -221,11 +237,21 @@ def render_stock_evaluation() -> None:
# 生成股票评分 # 生成股票评分
with st.spinner("正在生成股票评分..."): with st.spinner("正在生成股票评分..."):
# 使用IC均值作为权重但如果IC均值全为零则使用均匀分布
if all(mean == 0 for mean in ic_means):
factor_weights = [1.0 / len(ic_means)] * len(ic_means)
LOGGER.info("所有因子IC均值均为零使用均匀权重", extra=LOG_EXTRA)
else:
# 将IC均值归一化为权重
abs_sum = sum(abs(m) for m in ic_means)
factor_weights = [m / abs_sum for m in ic_means]
LOGGER.info("使用IC均值作为权重: %s", factor_weights, extra=LOG_EXTRA)
scores = _calculate_stock_scores( scores = _calculate_stock_scores(
universe, universe,
selected_factors, selected_factors,
end_date, end_date,
ic_means factor_weights
) )
if scores: if scores:
@ -256,8 +282,20 @@ def _calculate_stock_scores(
factor_weights: List[float] factor_weights: List[float]
) -> List[Dict[str, str]]: ) -> List[Dict[str, str]]:
"""计算股票的综合评分。""" """计算股票的综合评分。"""
LOGGER = get_logger(__name__)
LOG_EXTRA = {"stage": "stock_evaluation"}
broker = DataBroker() broker = DataBroker()
# 记录评估开始
LOGGER.info(
"开始股票评估评估日期=%s 因子数量=%d 权重=%s",
eval_date.strftime("%Y-%m-%d"),
len(factors),
factor_weights,
extra=LOG_EXTRA
)
# 标准化权重 # 标准化权重
weights = np.array(factor_weights) weights = np.array(factor_weights)
abs_sum = np.sum(np.abs(weights)) abs_sum = np.sum(np.abs(weights))
@ -269,15 +307,30 @@ def _calculate_stock_scores(
# 获取所有股票的因子值 # 获取所有股票的因子值
stocks = universe or broker.get_all_stocks(eval_date.strftime("%Y%m%d")) stocks = universe or broker.get_all_stocks(eval_date.strftime("%Y%m%d"))
# 记录股票列表信息
LOGGER.info(
"获取股票列表 universe_size=%d total_stocks=%d",
len(universe) if universe else 0,
len(stocks),
extra=LOG_EXTRA
)
results = [] results = []
evaluated_count = 0
skipped_count = 0
for ts_code in stocks: for ts_code in stocks:
# 检查数据是否充分
if not check_data_sufficiency(ts_code, eval_date.strftime("%Y%m%d")): if not check_data_sufficiency(ts_code, eval_date.strftime("%Y%m%d")):
skipped_count += 1
continue continue
# 获取股票信息 # 获取股票信息
info = broker.get_stock_info(ts_code) info = broker.get_stock_info(ts_code)
if not info: if not info:
skipped_count += 1
continue continue
# 获取因子值 # 获取因子值
@ -285,14 +338,18 @@ def _calculate_stock_scores(
for factor in factors: for factor in factors:
value = broker.fetch_latest_factor(ts_code, factor, eval_date) value = broker.fetch_latest_factor(ts_code, factor, eval_date)
if value is None: if value is None:
skipped_count += 1
break break
factor_values.append(value) factor_values.append(value)
# 检查是否所有因子值都已获取
if len(factor_values) != len(factors): if len(factor_values) != len(factors):
skipped_count += 1
continue continue
# 计算综合评分 # 计算综合评分
score = np.dot(factor_values, weights) score = np.dot(factor_values, weights)
evaluated_count += 1
results.append({ results.append({
"股票代码": ts_code, "股票代码": ts_code,
@ -301,6 +358,16 @@ def _calculate_stock_scores(
"综合评分": f"{score:.4f}" "综合评分": f"{score:.4f}"
}) })
# 记录评估完成信息
LOGGER.info(
"股票评估完成 总股票数=%d 已评估=%d 跳过=%d 结果数=%d",
len(stocks),
evaluated_count,
skipped_count,
len(results),
extra=LOG_EXTRA
)
return results return results