Develop #5

Merged
sakibcc merged 6 commits from develop into main 2026-08-09 09:46:02 +08:00
4 changed files with 53 additions and 8 deletions
Showing only changes of commit aed8948b79 - Show all commits
+10
View File
@@ -7,6 +7,16 @@
**历史可复现分析**:给定一个历史交易日,在当前目标股票池范围内重建该日的行情与估值状态;价格采用数据库中当前最新修订的前复权行情,不要求还原某次同步时的价格版本。 **历史可复现分析**:给定一个历史交易日,在当前目标股票池范围内重建该日的行情与估值状态;价格采用数据库中当前最新修订的前复权行情,不要求还原某次同步时的价格版本。
_Avoid_: 用当前市值回填历史、把当前目标股票池当作无幸存者偏差的长期回测宇宙 _Avoid_: 用当前市值回填历史、把当前目标股票池当作无幸存者偏差的长期回测宇宙
**选股策略**:一组针对明确目标交易日、依赖该日之前历史行情的选股规则;它产出可解释的选股信号,不等同于交易执行指令或收益承诺。
**知行 B1**:当前迁移中的知行选股策略名称;它按知行公式语义评估目标交易日,并包含七种可以独立命中的子信号。
**子信号**:选股公式中具有独立业务含义的命中分支;同一只股票在同一交易日可以同时命中多个子信号,不能因为存在合并条件而丢失分类信息。
**公式语义**:公式原文及已确认业务调整所表达的规则意图;当旧代码与公式意图冲突时,公式语义是迁移后的判断依据,旧代码只作为实现参考和差异证据。
**历史样本验证**:使用固定的历史行情样本和固定期望结果验证策略规则;它用于发现规则迁移偏差,不等同于回测收益评价。
## 市场数据 ## 市场数据
**股票主数据**:描述证券标识及其在市场中的基础状态,例如代码、名称、交易所和上市状态。 **股票主数据**:描述证券标识及其在市场中的基础状态,例如代码、名称、交易所和上市状态。
@@ -0,0 +1,31 @@
---
status: accepted
---
# 选股策略以公式语义为准并独立保留子信号
知行选股策略迁移时,以通达信公式原文和已确认的业务调整作为规则语义来源,
旧项目 Python 实现只作为迁移参考与差异证据。原因是旧实现存在无法历史重放的
数据行为,也会在多个 XG 条件同时命中时只保留第一个分类;直接追求旧输出兼容
会把实现缺陷固化到新系统。
新策略使用 `zhixing_b1` 作为业务标识,并把七种子信号作为独立分类。同一股票、
同一交易日可以产生多条不同分类的信号;每条信号的稳定身份由股票、交易日、
策略标识和子信号分类共同确定。
## Considered Options
- **完全兼容旧 Python 输出**:迁移成本较低,但会保留旧的首个分类截断和历史
数据前视风险。
- **只按公式返回一条合并信号**:实现简单,但会丢失子信号的解释性和后续统计
维度。
- **按公式语义计算并独立返回全部子信号**:需要增加分类结果和差异测试,但能
保持规则意图、解释能力和历史重放边界。
## Consequences
- golden 验证需要同时记录命中分类集合和有意的旧实现差异。
- 后续信号持久化可以使用 `(ts_code, trade_date, strategy, category)` 作为唯一
键,但本 ADR 不决定具体数据库表或 HTTP 契约。
- 其他策略迁移时仍需逐一确认其公式来源与历史依赖,不能自动套用旧策略的输出
兼容规则。
@@ -425,8 +425,7 @@ class SyncMarketData:
failure = self._failure("daily_basic", key, exc) failure = self._failure("daily_basic", key, exc)
failures.append(failure) failures.append(failure)
logger.warning( logger.warning(
"market_data_sync_item_failed batch_id=%s stage=daily_basic item=%s " "market_data_sync_item_failed batch_id=%s stage=daily_basic item=%s error_type=%s",
"error_type=%s",
batch_id, batch_id,
key, key,
failure.error_type, failure.error_type,
@@ -520,10 +519,16 @@ class SyncMarketData:
) -> None: ) -> None:
"""Log bounded, secret-free progress for a batch stage.""" """Log bounded, secret-free progress for a batch stage."""
if not force and total > _PROGRESS_LOG_INTERVAL and current not in { if (
1, not force
total, and total > _PROGRESS_LOG_INTERVAL
} and current % _PROGRESS_LOG_INTERVAL != 0: and current
not in {
1,
total,
}
and current % _PROGRESS_LOG_INTERVAL != 0
):
return return
logger.info( logger.info(
"market_data_sync_progress batch_id=%s stage=%s progress=%d/%d item=%s " "market_data_sync_progress batch_id=%s stage=%s progress=%d/%d item=%s "
@@ -190,8 +190,7 @@ def test_sync_logs_progress_for_initialize_and_daily_update(
assert initialize.status == "success" assert initialize.status == "success"
assert any("stage=daily_basic" in message for message in initialize_messages) assert any("stage=daily_basic" in message for message in initialize_messages)
assert any( assert any(
"stage=bar" in message and "progress=1/1" in message "stage=bar" in message and "progress=1/1" in message for message in initialize_messages
for message in initialize_messages
) )
caplog.clear() caplog.clear()