feat(selection): M6.2 条件选股(method=condition + 财务可见性防护)
- quant/selection.run_condition_selection:结构化条件 AND 求值 —— 字段域 static.*(行业/市场…)、技术列与派生量(close/volume/ma20/ma60)、已注册因子 (momentum_60 等)、fundamental.*(announce_date<=as_of 的最新已公告财务值); 条件支持 value 字面量与 ref 字段比较(如 close > ma60);结果带 filter_status/reason - SelectionQuery 校验调整:condition 模式为纯过滤(不再强制 top_n/top_pct) - FinancialRepository 新增 list_announced_many(批量防未来函数读取)+ SQLAlchemy 实现; SelectionService 注入 financial_repo 并按 announce_date 取每股最新一版 - tests/test_selection_condition.py:8 例(行业 in/ne、动量>0、close>ma60 ref、阈值、 ROE 过滤且未来公告不可见、缺财务 repo 报错、更早 as_of 排除);全量 pytest 通过
This commit is contained in:
@@ -280,6 +280,28 @@ class SqlAlchemyFinancialRepository:
|
||||
rows = self._session.scalars(stmt).all()
|
||||
return [FinancialIndicator.model_validate(r, from_attributes=True) for r in rows]
|
||||
|
||||
def list_announced_many(
|
||||
self,
|
||||
symbols: Sequence[str],
|
||||
as_of_date: date,
|
||||
) -> list[FinancialIndicator]:
|
||||
"""批量:这些股票 announce_date <= as_of_date 的全部记录(防未来函数)。"""
|
||||
if not symbols:
|
||||
return []
|
||||
rows = self._session.scalars(
|
||||
select(FinancialIndicatorModel)
|
||||
.where(
|
||||
FinancialIndicatorModel.symbol.in_(list(symbols)),
|
||||
FinancialIndicatorModel.announce_date <= as_of_date,
|
||||
)
|
||||
.order_by(
|
||||
FinancialIndicatorModel.symbol,
|
||||
FinancialIndicatorModel.announce_date,
|
||||
FinancialIndicatorModel.report_date,
|
||||
)
|
||||
).all()
|
||||
return [FinancialIndicator.model_validate(r, from_attributes=True) for r in rows]
|
||||
|
||||
|
||||
class SqlAlchemySyncLogRepository:
|
||||
def __init__(self, session: Session) -> None:
|
||||
|
||||
Reference in New Issue
Block a user