Skip to content

fix missing capital flow buy guard - #1289

Merged
ZhuLinsen merged 4 commits into
mainfrom
codex/fix-missing-capital-flow-guard
May 15, 2026
Merged

fix missing capital flow buy guard#1289
ZhuLinsen merged 4 commits into
mainfrom
codex/fix-missing-capital-flow-guard

Conversation

@ZhuLinsen

Copy link
Copy Markdown
Owner

Summary

Fixes #1286.

  • Downgrade direct buy conclusions to hold / watch-only when the capital-flow block exists but is unavailable or empty.
  • Lower confidence and cap the sentiment score so missing fund-flow data is not presented as a high-confidence buy basis.
  • Preserve the existing unavailable-flow behavior for sell and non-buy conclusions.

Root Cause

stabilize_decision_with_structure() previously skipped calibration when capital flow was unavailable. That meant a buy conclusion could remain unchanged even though the fund-flow evidence needed to confirm the buy was missing.

Validation

  • python -m py_compile src/analyzer.py
  • python -m pytest tests/test_decision_stability.py -q (13 passed)

Risk

Reports become more conservative when the configured data source cannot provide fund-flow data. This is intentional for safety, but it may reduce direct buy calls in unsupported/free-data environments.

Rollback

Revert this PR to restore the old skip-calibration behavior for unavailable capital-flow data.

@github-actions github-actions Bot added ai documentation Improvements or additions to documentation size/M testing labels May 13, 2026
@github-actions

github-actions Bot commented May 13, 2026

Copy link
Copy Markdown

🤖 自动审查报告

项目 结果
📊 变更文件 3 个
➕ 新增行数 184 行
➖ 删除行数 60 行
🔍 静态检查 ✅ 通过
🧠 AI 审查 ✅ 已完成

📁 修改的文件

  • 📝 docs/CHANGELOG.md (+1/-0)
  • 📝 src/analyzer.py (+145/-46)
  • 📝 tests/test_decision_stability.py (+38/-14)

🧠 AI 代码审查意见

结论

Ready to Merge

结构化审查结果

必要性

通过
PR 明确解决了 #1286,即在资金流数据不可用时,防止系统错误地给出高置信度的买入结论。这增强了分析报告的严谨性和安全性,避免因数据缺失导致误判,具有明确的业务价值。

关联性

通过
PR 描述明确指出 "Fixes #1286",与现有 Issue 建立了清晰的关联。

类型

fix

描述完整性

完整
PR 描述包含了总结(Summary)、根本原因(Root Cause)、验证命令与结果、兼容性风险(Risk)和回滚方案(Rollback),信息非常全面。CI 检查状态也已确认 py_compileflake8 通过。

风险级别


关键风险:报告结果会更加保守,在不支持资金流数据或数据缺失的环境中,直接买入的建议可能会减少。PR 描述已充分说明这一风险,并解释这是有意为之,旨在提高安全性。代码逻辑处理方式合理,避免了潜在的误导性结论,因此风险可控。

必改项

建议项

  1. 关于 scripts/ci_gate.sh 执行情况的说明
    • 文件: N/A (PR 描述)
    • 建议: 虽然本次 CI 已通过语法和致命 lint 检查,且修改内容主要集中在 Python 逻辑和测试,但根据审查规则,对于 Python 后端改动,PR 描述中若未说明 ./scripts/ci_gate.sh 的执行情况或给出跳过原因,建议在描述中补充。此项不构成阻断,仅为规范建议。

💡 提示: 请确保代码已通过本地测试,并遵循项目代码规范。

@ZhuLinsen
ZhuLinsen marked this pull request as ready for review May 13, 2026 15:02
Copilot AI review requested due to automatic review settings May 13, 2026 15:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a decision-stability edge case where a direct buy recommendation could remain intact even when the capital-flow block exists but is unavailable/empty, leading to overconfident buy conclusions.

Changes:

  • Adjust stabilize_decision_with_structure() so that when capital flow is unavailable and the inferred decision is buy, the result is downgraded to hold/watch-only, with lowered confidence and a capped sentiment score.
  • Add a dedicated downgrade helper to populate dashboard/risk fields consistently for the “missing capital flow” buy-guard case.
  • Update regression tests and changelog to reflect the new conservative behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/analyzer.py Applies a stricter guard for buy signals when capital-flow data is unavailable, and introduces a dedicated downgrade helper.
tests/test_decision_stability.py Updates assertions to expect buy downgrades (while preserving existing sell/unavailable behavior) and strengthens regression coverage.
docs/CHANGELOG.md Documents the behavior change in the [Unreleased] section using the repo’s flat bullet format.
Comments suppressed due to low confidence (1)

tests/test_decision_stability.py:217

  • This test now expects a buy downgrade (decision_type="hold" and decision_stability.applied=True) when capital_flow.status is an unavailable variant, but the test name still says “skips_calibration…”. Consider renaming it to match the new downgrade behavior to avoid confusion.
    assert buy_result.decision_type == "hold"
    assert buy_result.operation_advice == "持有观察"
    assert buy_result.dashboard["decision_stability"]["applied"] is True

Comment on lines +195 to +198
assert result.decision_type == "hold"
assert result.operation_advice == "持有观察"
assert result.dashboard["decision_stability"]["applied"] is True
assert "资金流数据缺失" in result.dashboard["decision_stability"]["capital_flow_status"]
Comment thread src/analyzer.py Outdated
Comment on lines +1042 to +1066
status_text = _capital_flow_status_for_stability(flow_status, language)
if language == "zh":
advice = "持有观察"
reason = f"{status_text},买入结论缺少资金面确认,先按观察处理。"
signal_type = "🟡持有观望"
no_position = "空仓先不追买,等待资金流恢复、支撑确认或有效突破后再行动。"
has_position = "持仓以关键支撑为风控线,资金流恢复前控制仓位。"
confidence = "低"
else:
advice = "Hold and watch"
reason = f"{status_text}; the buy call lacks capital-flow confirmation, so treat it as watch-only."
signal_type = "🟡 Hold / Watch"
no_position = "Do not chase; wait for capital-flow recovery, support confirmation, or a valid breakout."
has_position = "Use key support as the risk line and keep position size controlled until capital flow recovers."
confidence = "Low"

result.decision_type = "hold"
result.operation_advice = advice
result.confidence_level = confidence
try:
score = int(getattr(result, "sentiment_score", 50))
except (TypeError, ValueError):
score = 50
result.sentiment_score = min(59, max(45, score))

@ZhuLinsen ZhuLinsen left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

评审结论

  • 必要性:通过。该 PR 针对资金流不可用时仍保留直接买入结论的问题,属于实际决策安全修复。
  • 是否有对应 issue:有,Fixes #1286
  • PR 类型:fix,修改 src/analyzer.py 的决策稳定性逻辑,并补充回归测试与 changelog。
  • description 完整性:完整。已说明问题、根因、修复点、验证命令、风险和回滚方式,符合本仓库 AGENTS.md 对 fix 类 PR 的交付要求。
  • 是否可直接合入:可。CI 已通过,改动范围聚焦,docs/CHANGELOG.md 已按 [Unreleased] 扁平格式补充记录;当前 mergeable_state=blocked 不单独构成阻断。

主要问题

  1. [Nice to have] tests/test_decision_stability.py 中仍有部分测试名使用 skips_calibration... 表述,但断言已经改为降级买入结论。该问题不影响运行时正确性,也不应阻断合入,但建议后续同步重命名,避免测试意图和当前行为不一致。

🤖 此回复由 OpenReview Bot 自动生成,仅供参考。如有疑问请 @维护者。

@ZhuLinsen
ZhuLinsen force-pushed the codex/fix-missing-capital-flow-guard branch from 3abc092 to 204a6b0 Compare May 15, 2026 12:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 204a6b0aad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/analyzer.py
Comment on lines 724 to 727
decision_type = infer_decision_type_from_advice(
getattr(result, "decision_type", ""),
default=getattr(result, "decision_type", "hold") or "hold",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect buy advice before skipping unavailable flow

When decision_type is hold or otherwise non-buy while the user-visible operation_advice still says 买入/Buy (the model returns both fields, and only missing decision_type is inferred from advice), this guard treats the result as non-buy and calls the unavailable-flow path, leaving the buy advice and high score unchanged despite missing capital-flow data. The unavailable-flow buy guard should reconcile or infer from operation_advice before deciding whether to skip the downgrade.

Useful? React with 👍 / 👎.

@ZhuLinsen
ZhuLinsen force-pushed the codex/fix-missing-capital-flow-guard branch from 9e7fa99 to 732d846 Compare May 15, 2026 12:57
@ZhuLinsen ZhuLinsen changed the title [codex] fix missing capital flow buy guard fix missing capital flow buy guard May 15, 2026
@ZhuLinsen
ZhuLinsen merged commit e22cf8e into main May 15, 2026
2 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4164b64ea5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/analyzer.py
Comment on lines +735 to +738
if flow_bias == "unavailable":
if isinstance(fundamental_context, dict) and "capital_flow" in fundamental_context:
if decision_type == "buy" or advice_decision_type == "buy":
_downgrade_buy_without_capital_flow(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve buys for markets without capital-flow support

When analyzing US/HK stocks or ETFs, DataFetcherManager still returns a capital_flow block with status: not_supported (for example data_provider/base.py:2142-2146 and 2339-2345), and the pipeline always passes that context into this guard. This new branch therefore downgrades every otherwise valid buy call for those supported markets solely because A-share capital-flow data is unavailable, even though that data source is not expected to exist there. Gate the downgrade to markets/data sources where capital flow is actually an applicable confirmation signal, otherwise non-CN/ETF reports can no longer produce buy recommendations.

Useful? React with 👍 / 👎.

Anyone878 pushed a commit to Anyone878/daily_stock_analysis that referenced this pull request May 17, 2026
EchoingFootsteps pushed a commit to EchoingFootsteps/daily_stock_analysis that referenced this pull request Jul 4, 2026
bmwu pushed a commit to bmwu/daily_stock_analysis that referenced this pull request Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai documentation Improvements or additions to documentation size/L size/M testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 基本面/资金面缺失时仍可能输出高置信买入结论

2 participants