Skip to content

Commit 0f5a4c9

Browse files
committed
Add market confirmation gates
1 parent e8a7692 commit 0f5a4c9

19 files changed

Lines changed: 862 additions & 73 deletions

.github/workflows/monthly_advisory_review.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,27 @@ jobs:
7979
AS_OF="${INPUT_AS_OF:-$(date -u +%F)}"
8080
mkdir -p data/output/monthly_advisory_review
8181
THEME_ARGS=()
82+
RESOLVED_THEME_MOMENTUM=""
8283
if [ -n "${THEME_MOMENTUM_PATH}" ] && [ -f "../research-signal-context/${THEME_MOMENTUM_PATH}" ]; then
83-
THEME_ARGS=(--theme-momentum "../research-signal-context/${THEME_MOMENTUM_PATH}")
84+
RESOLVED_THEME_MOMENTUM="../research-signal-context/${THEME_MOMENTUM_PATH}"
85+
THEME_ARGS=(--theme-momentum "${RESOLVED_THEME_MOMENTUM}")
8486
fi
8587
MARKET_ARGS=()
8688
if [ -n "${MARKET_CONFIRMATION_PATH}" ] && [ -f "${MARKET_CONFIRMATION_PATH}" ]; then
8789
MARKET_ARGS=(--market-confirmation "${MARKET_CONFIRMATION_PATH}")
90+
else
91+
GENERATED_MARKET_CONFIRMATION="data/output/monthly_advisory_review/market_confirmation_${AS_OF}.csv"
92+
MARKET_BUILD_ARGS=(
93+
--as-of "${AS_OF}"
94+
--political-watchlist "../political-events/${POLITICAL_WATCHLIST_PATH}"
95+
--ai-signal "../research-signal-context/${AI_SIGNAL_PATH}"
96+
--output "${GENERATED_MARKET_CONFIRMATION}"
97+
)
98+
if [ -n "${RESOLVED_THEME_MOMENTUM}" ]; then
99+
MARKET_BUILD_ARGS+=(--theme-momentum "${RESOLVED_THEME_MOMENTUM}")
100+
fi
101+
python scripts/build_market_confirmation.py "${MARKET_BUILD_ARGS[@]}"
102+
MARKET_ARGS=(--market-confirmation "${GENERATED_MARKET_CONFIRMATION}")
88103
fi
89104
python scripts/build_advisory_report.py \
90105
--as-of "${AS_OF}" \

.github/workflows/publish_advisory_site.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,27 @@ jobs:
8888
AS_OF="${INPUT_AS_OF:-$(date -u +%F)}"
8989
mkdir -p data/output/published site
9090
THEME_ARGS=()
91+
RESOLVED_THEME_MOMENTUM=""
9192
if [ -n "${THEME_MOMENTUM_PATH}" ] && [ -f "../research-signal-context/${THEME_MOMENTUM_PATH}" ]; then
92-
THEME_ARGS=(--theme-momentum "../research-signal-context/${THEME_MOMENTUM_PATH}")
93+
RESOLVED_THEME_MOMENTUM="../research-signal-context/${THEME_MOMENTUM_PATH}"
94+
THEME_ARGS=(--theme-momentum "${RESOLVED_THEME_MOMENTUM}")
9395
fi
9496
MARKET_ARGS=()
9597
if [ -n "${MARKET_CONFIRMATION_PATH}" ] && [ -f "${MARKET_CONFIRMATION_PATH}" ]; then
9698
MARKET_ARGS=(--market-confirmation "${MARKET_CONFIRMATION_PATH}")
99+
else
100+
GENERATED_MARKET_CONFIRMATION="data/output/published/market_confirmation_${AS_OF}.csv"
101+
MARKET_BUILD_ARGS=(
102+
--as-of "${AS_OF}"
103+
--political-watchlist "../political-events/${POLITICAL_WATCHLIST_PATH}"
104+
--ai-signal "../research-signal-context/${AI_SIGNAL_PATH}"
105+
--output "${GENERATED_MARKET_CONFIRMATION}"
106+
)
107+
if [ -n "${RESOLVED_THEME_MOMENTUM}" ]; then
108+
MARKET_BUILD_ARGS+=(--theme-momentum "${RESOLVED_THEME_MOMENTUM}")
109+
fi
110+
python scripts/build_market_confirmation.py "${MARKET_BUILD_ARGS[@]}"
111+
MARKET_ARGS=(--market-confirmation "${GENERATED_MARKET_CONFIRMATION}")
97112
fi
98113
python scripts/build_advisory_report.py \
99114
--as-of "${AS_OF}" \

.github/workflows/weekly_advisory_review.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,27 @@ jobs:
7373
AS_OF="${INPUT_AS_OF:-$(date -u +%F)}"
7474
mkdir -p data/output/weekly_advisory_review
7575
THEME_ARGS=()
76+
RESOLVED_THEME_MOMENTUM=""
7677
if [ -n "${THEME_MOMENTUM_PATH}" ] && [ -f "../research-signal-context/${THEME_MOMENTUM_PATH}" ]; then
77-
THEME_ARGS=(--theme-momentum "../research-signal-context/${THEME_MOMENTUM_PATH}")
78+
RESOLVED_THEME_MOMENTUM="../research-signal-context/${THEME_MOMENTUM_PATH}"
79+
THEME_ARGS=(--theme-momentum "${RESOLVED_THEME_MOMENTUM}")
7880
fi
7981
MARKET_ARGS=()
8082
if [ -n "${MARKET_CONFIRMATION_PATH}" ] && [ -f "${MARKET_CONFIRMATION_PATH}" ]; then
8183
MARKET_ARGS=(--market-confirmation "${MARKET_CONFIRMATION_PATH}")
84+
else
85+
GENERATED_MARKET_CONFIRMATION="data/output/weekly_advisory_review/market_confirmation_${AS_OF}.csv"
86+
MARKET_BUILD_ARGS=(
87+
--as-of "${AS_OF}"
88+
--political-watchlist "../political-events/${POLITICAL_WATCHLIST_PATH}"
89+
--ai-signal "../research-signal-context/${AI_SIGNAL_PATH}"
90+
--output "${GENERATED_MARKET_CONFIRMATION}"
91+
)
92+
if [ -n "${RESOLVED_THEME_MOMENTUM}" ]; then
93+
MARKET_BUILD_ARGS+=(--theme-momentum "${RESOLVED_THEME_MOMENTUM}")
94+
fi
95+
python scripts/build_market_confirmation.py "${MARKET_BUILD_ARGS[@]}"
96+
MARKET_ARGS=(--market-confirmation "${GENERATED_MARKET_CONFIRMATION}")
8297
fi
8398
python scripts/build_advisory_report.py \
8499
--as-of "${AS_OF}" \

README.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ Key documents:
4141

4242
Advisor is the final composition layer. Source ownership by horizon is:
4343

44-
- Short term (`1-10 trading days`): `source_events.csv` / `political_events.csv` from `PoliticalEventTrackingResearch` for event and policy/news catalysts.
45-
- Medium term (`2-12 weeks`): `theme_momentum_snapshot.json` from `ResearchSignalContextPipelines`, now explicitly marked as `medium_horizon_theme_context`.
44+
- Short term (`1-10 trading days`): event and policy/news catalysts plus generated `market_confirmation.csv`, focused on relative strength, volume, drawdown, and volatility.
45+
- Medium term (`2-12 weeks`): `theme_momentum_snapshot.json` from `ResearchSignalContextPipelines`, now explicitly marked as `medium_horizon_theme_context`, focused on theme momentum and symbol momentum.
4646
- Long term (`1-3 years`): `latest_signal.json` / `signal_history/*.json` from `ResearchSignalContextPipelines` as AI shadow context.
4747

48-
Final recommendations are still deterministic Advisor outputs. The signal context repository does not directly produce short-term recommendations or replace the final decision engine. Advisor now records separate short/medium/long horizon scores for each final pick; public pages keep the simpler final recommendation layout.
48+
Final recommendations are still deterministic Advisor outputs. The signal context repository does not directly produce short-term recommendations or replace the final decision engine. Advisor now records separate short/medium/long horizon scores and gates for each final pick; public pages keep the simpler final recommendation layout.
4949

5050
## Boundary
5151

@@ -171,6 +171,32 @@ Notification channel rules are documented in
171171
[`docs/notification_format.md`](docs/notification_format.md) and
172172
[`docs/notification_format.zh-CN.md`](docs/notification_format.zh-CN.md).
173173

174+
## Market Confirmation
175+
176+
`scripts/build_market_confirmation.py` collects symbols from the watchlist,
177+
signal context, and theme momentum snapshot, then writes a
178+
`market_confirmation.csv` file:
179+
180+
```bash
181+
python scripts/build_market_confirmation.py \
182+
--as-of 2026-05-30 \
183+
--political-watchlist examples/political_watchlist.example.csv \
184+
--ai-signal examples/research_signal_context.example.json \
185+
--theme-momentum examples/theme_momentum_snapshot.example.json \
186+
--output data/output/market_confirmation_2026-05-30.csv
187+
```
188+
189+
The generated columns include `return_5d`, `return_20d`, `return_63d`,
190+
relative returns versus SPY, volume z-score, 63-day drawdown, 21-day annualized
191+
volatility, and `market_score`. The weekly/monthly/publish workflows generate
192+
this file automatically before building advisory reports.
193+
194+
Yahoo chart is currently the no-dependency free price endpoint. If it is
195+
unavailable, the script falls back to price-momentum fields already saved in
196+
`theme_momentum_snapshot.json`, so report generation continues. Random free
197+
proxy pools should not be treated as a stable production data source; prefer
198+
organization-owned price snapshots, caches, or auditable controlled proxies.
199+
174200
## Output Contract
175201

176202
The main JSON artifact is `ModelRecommendationReport`:

README.zh-CN.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ QuantStrategyLab 的“智慧顾投”研究协调仓库。它生成非个性化
2929

3030
Advisor 是最终合成层,三个周期的输入分工如下:
3131

32-
- 短线(1-10 个交易日):`PoliticalEventTrackingResearch``source_events.csv` / `political_events.csv`用于事件和新闻政策催化
33-
- 中线(2-12 周):`ResearchSignalContextPipelines``theme_momentum_snapshot.json`,现在明确标记为 `medium_horizon_theme_context`
32+
- 短线(1-10 个交易日):事件/新闻政策催化 + 自动生成的 `market_confirmation.csv`重点看相对强度、成交量、回撤和波动
33+
- 中线(2-12 周):`ResearchSignalContextPipelines``theme_momentum_snapshot.json`,现在明确标记为 `medium_horizon_theme_context`,重点看主题动量和个股动量
3434
- 长线(1-3 年):`ResearchSignalContextPipelines``latest_signal.json` / `signal_history/*.json`,作为 AI shadow 背景。
3535

36-
最终推荐仍由本仓库确定性合成。信号上下文仓库不直接输出短线推荐,也不替代本仓库的最终决策。本仓库会为最终推荐记录短/中/长线独立评分,但公开页面仍保持简洁,只展示最终列表、背景、理由和风险。
36+
最终推荐仍由本仓库确定性合成。信号上下文仓库不直接输出短线推荐,也不替代本仓库的最终决策。本仓库会为最终推荐记录短/中/长线独立评分和独立门槛,但公开页面仍保持简洁,只展示最终列表、背景、理由和风险。
3737

3838
## 当前 MVP
3939

@@ -68,7 +68,7 @@ python scripts/build_advisory_report.py \
6868

6969
## 版本管理
7070

71-
- Python 包版本:`0.1.2`
71+
- Python 包版本:`0.1.3`
7272
- 报告 schema:`schema_version = 5`
7373
- 报告 contract:`model_recommendations.v5`
7474
- 报告 manifest:`<output-json>.manifest.json`
@@ -200,4 +200,19 @@ python scripts/build_advisory_report.py \
200200
基础 `recommendations[]` 评级仍来自事件、watchlist 和 AI 背景;`final_decisions` 会用中线主题动量和可选市场确认对最终公开列表排序。候选池不改变仓位或执行状态。
201201
线上 workflow 如果找不到 `data/output/theme_momentum_snapshot.json`,会自动跳过这个展示区块。
202202

203-
Yahoo chart 下载只作为临时 fallback。不要把随机免费代理 IP 池作为稳定生产方案;它有稳定性、数据污染、封禁、隐私和合规风险。更稳的做法是使用本组织已有价格快照、缓存文件,或可审计的自有代理/数据源。
203+
## 市场确认
204+
205+
`scripts/build_market_confirmation.py` 会从 watchlist、信号上下文和主题动量快照收集股票代码,生成 `market_confirmation.csv`
206+
207+
```bash
208+
python scripts/build_market_confirmation.py \
209+
--as-of 2026-05-30 \
210+
--political-watchlist examples/political_watchlist.example.csv \
211+
--ai-signal examples/research_signal_context.example.json \
212+
--theme-momentum examples/theme_momentum_snapshot.example.json \
213+
--output data/output/market_confirmation_2026-05-30.csv
214+
```
215+
216+
字段包括 `return_5d``return_20d``return_63d`、相对 SPY 收益、成交量 z-score、63 日回撤、21 日年化波动和 `market_score`。线上 weekly/monthly/publish workflow 会自动生成该文件,再传给报告生成器。
217+
218+
Yahoo chart 下载只是当前无依赖的免费行情入口;如果不可用,脚本会退回到 `theme_momentum_snapshot.json` 里的价格动量信息,报告仍能生成。不要把随机免费代理 IP 池作为稳定生产方案;它有稳定性、数据污染、封禁、隐私和合规风险。更稳的做法是使用本组织已有价格快照、缓存文件,或可审计的自有代理/数据源。

docs/advisory_contract.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ momentum_score
167167
medium_context_score
168168
long_context_score
169169
horizon_scores.short|medium|long
170+
horizon_actions.short|medium|long
170171
supporting_context.short|medium|long
171172
selection_trace[]
172173
business_summary
@@ -175,11 +176,14 @@ why_selected[]
175176
risk_summary
176177
```
177178

178-
Scoring intent by horizon:
179+
Scoring and gate intent by horizon:
179180

180-
- short: event/source evidence first, optionally confirmed by recent market behavior;
181-
- medium: theme momentum and individual momentum first, with event/news and optional market confirmation as supporting inputs;
182-
- long: saved AI shadow context and durable theme context first, with event/news as supporting evidence.
181+
- short: recent market confirmation is required; event/news evidence and momentum
182+
can upgrade confidence;
183+
- medium: theme momentum and individual momentum are required for final
184+
recommendation; event/news and market confirmation are supporting inputs;
185+
- long: saved AI shadow context or durable long-horizon context must be strong;
186+
event/news is supporting evidence.
183187

184188
These fields are audit metadata. Public HTML/RSS/Telegram renderers still show
185189
only final recommendations, stock background, recommendation reasons, and risks.

docs/data_factor_roadmap.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,12 @@ Priority order:
8989
releases, SEC/EDGAR, company IR, policy/procurement sources, alias maps, and
9090
source registry coverage.
9191
3. Add optional market confirmation CSVs while keeping report generation working
92-
when the data is absent. The CSV should carry point-in-time returns, relative
93-
returns, abnormal volume, drawdown, and volatility; it should not contain
94-
target weights or trade instructions.
92+
when the data is absent. The CSV now carries point-in-time returns, relative
93+
returns, abnormal volume, drawdown, volatility, `market_score`, source, row
94+
count, and warnings. `scripts/build_market_confirmation.py` generates it from
95+
watchlists, saved signal context, and theme momentum snapshots; if the free
96+
price endpoint is unavailable, it falls back to saved theme momentum fields.
97+
It must not contain target weights or trade instructions.
9598
4. Add event review inputs for 1/5/20/60 trading-day follow-up.
9699
5. Add fundamentals/valuation snapshots for risk explanation, not execution.
97100
6. Only then consider read-only references from existing snapshot repositories.

docs/data_factor_roadmap.zh-CN.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,10 @@ Crypto 可作为跨资产风险情绪参考,但暂时不应混入 US equity
178178
- X / Truth Social / 社区内容暂不作为稳定默认源。
179179

180180
3.`QuantAdvisorResearch` 增加 market confirmation 输入,但保持可选:
181-
- 当前 CSV 字段为 `symbol,as_of,return_5d,return_20d,return_63d,relative_return_20d,relative_return_63d,volume_zscore,drawdown_63d,volatility_21d`
182-
- 如果没有市场确认数据,报告继续生成;该输入只影响 `final_decisions` 的短/中/长线审计评分,不包含目标仓位或交易指令。
181+
- 当前 CSV 字段为 `symbol,as_of,return_5d,return_20d,return_63d,relative_return_20d,relative_return_63d,volume_zscore,drawdown_63d,volatility_21d,market_score,data_source,price_observation_count,warnings`
182+
- `scripts/build_market_confirmation.py` 已能自动从 watchlist、信号上下文和主题动量快照收集标的,线上 workflow 默认生成该 CSV。
183+
- 如果免费行情接口不可用,脚本会退回到 `theme_momentum_snapshot.json` 中的价格动量字段;报告继续生成,但短线结论会更保守。
184+
- 该输入只影响 `final_decisions` 的短/中/长线审计评分,不包含目标仓位或交易指令。
183185

184186
4. 增加事件复盘结果输入:
185187
- `event_id,symbol,event_date,window,absolute_return,benchmark_relative_return`

docs/system_design.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,17 @@ execution targets for this advisory pipeline.
5151
## Horizon Ownership
5252

5353
- Short term (`1-10 trading days`): event evidence from
54-
`PoliticalEventTrackingResearch`.
54+
`PoliticalEventTrackingResearch`, plus Advisor-generated market confirmation
55+
for relative strength, volume, drawdown, and volatility.
5556
- Medium term (`2-12 weeks`): `theme_momentum_snapshot.json` from
56-
`ResearchSignalContextPipelines`, marked as `medium_horizon_theme_context`.
57+
`ResearchSignalContextPipelines`, marked as `medium_horizon_theme_context`,
58+
focused on theme momentum and symbol momentum.
5759
- Long term (`1-3 years`): `latest_signal.json` and `signal_history/*.json` from
5860
`ResearchSignalContextPipelines` as AI shadow context.
5961

60-
`QuantAdvisorResearch` records per-recommendation `supporting_context` so each
61-
final recommendation can be traced back to short-, medium-, and long-horizon
62-
inputs.
62+
`QuantAdvisorResearch` records per-recommendation `supporting_context`,
63+
`horizon_scores`, and `horizon_actions` so each final recommendation can be
64+
traced back to short-, medium-, and long-horizon inputs and gates.
6365

6466
## Design Patterns
6567

@@ -101,6 +103,11 @@ The public HTML/RSS/Telegram outputs should stay direct:
101103
- never show orders, target weights, target share quantities, account suitability,
102104
or account-specific allocation advice.
103105

106+
Market confirmation is optional at the contract level, but the scheduled weekly,
107+
monthly, and publish workflows generate it automatically. Short-horizon gates
108+
require market confirmation, medium-horizon gates are led by theme and symbol
109+
momentum, and long-horizon gates require durable AI shadow or context strength.
110+
104111
## Fixture vs Live Inputs
105112

106113
Reports built from `examples/` are `source_mode=fixture` and are suitable for

docs/system_design.zh-CN.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ symbol_theme_exposure
109109

110110
## 短中长线来源分工
111111

112-
- 短线(1-10 个交易日):事件事实层负责,主要来自 `PoliticalEventTrackingResearch` 的官方来源、新闻政策和事件新鲜度
113-
- 中线(2-12 周):主题上下文层负责,`ResearchSignalContextPipelines``theme_momentum_snapshot.json` 标记为 `medium_horizon_theme_context`
112+
- 短线(1-10 个交易日):事件事实层 + 市场确认共同负责。事件来自 `PoliticalEventTrackingResearch`,市场确认由本仓库生成,主要看相对强度、成交量、回撤和波动
113+
- 中线(2-12 周):主题上下文层负责,`ResearchSignalContextPipelines``theme_momentum_snapshot.json` 标记为 `medium_horizon_theme_context`,主要看主题动量和个股动量
114114
- 长线(1-3 年):AI shadow 背景层负责,来自 `latest_signal.json``signal_history/*.json`
115115

116-
`QuantAdvisorResearch` 只在最后做确定性合成,报告中的 `supporting_context` 会记录每个最终推荐用到了短线、中线、长线哪些输入。
116+
`QuantAdvisorResearch` 只在最后做确定性合成,报告中的 `supporting_context``horizon_scores``horizon_actions` 会记录每个最终推荐用到了短线、中线、长线哪些输入,以及每个周期是否达到推荐或观察门槛
117117

118118
## Theme momentum 展示边界
119119

@@ -127,4 +127,6 @@ symbol_theme_exposure
127127

128128
如果上游 `ResearchSignalContextPipelines` 没有生成该 snapshot,workflow 会跳过该输入,报告仍可正常生成。
129129

130-
Yahoo chart 只能作为临时 fallback。随机免费代理 IP 池不应进入稳定生产链路;如果需要代理,应使用自控代理或更稳定的数据快照,并记录来源、时间和 hash,便于 replay。
130+
`market_confirmation.csv` 是可选输入,但线上 workflow 默认会自动生成。短线门槛要求有市场确认;中线门槛以主题动量和个股动量为主;长线门槛要求 AI shadow 或长期上下文足够强。
131+
132+
Yahoo chart 只能作为当前无依赖行情入口。随机免费代理 IP 池不应进入稳定生产链路;如果需要代理,应使用自控代理或更稳定的数据快照,并记录来源、时间和 hash,便于 replay。

0 commit comments

Comments
 (0)