stock-analysis-plugin 0.2.4__tar.gz → 0.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/AGENTS.md +4 -4
  2. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/PKG-INFO +54 -12
  3. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/README.md +53 -11
  4. stock_analysis_plugin-0.2.5/docs/research/issue-44-coverage-sources.md +122 -0
  5. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/dsh/index.ts +155 -7
  6. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/dsh/package.json +1 -1
  7. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/hermes/plugin.yaml +6 -0
  8. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/hermes/schemas.py +106 -5
  9. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/hermes/tools.py +65 -2
  10. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/openclaw/index.ts +95 -6
  11. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/openclaw/openclaw.plugin.json +7 -1
  12. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/openclaw/package.json +1 -1
  13. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/package-lock.json +2 -2
  14. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/package.json +1 -1
  15. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/pi/index.ts +185 -9
  16. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/pyproject.toml +1 -1
  17. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/event-driven/SKILL.md +6 -0
  18. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/growth-quality/SKILL.md +6 -0
  19. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/stock-analysis/SKILL.md +22 -0
  20. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/stock-screener/SKILL.md +18 -0
  21. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/strategy-backtest/SKILL.md +2 -0
  22. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/conftest.py +10 -0
  23. stock_analysis_plugin-0.2.5/tests/test_data_cache.py +47 -0
  24. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_dsh_integration.ts +40 -4
  25. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_hermes_integration.py +61 -0
  26. stock_analysis_plugin-0.2.5/tests/test_kline_adjustment.py +194 -0
  27. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_openclaw_integration.ts +39 -3
  28. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_pi_integration.ts +46 -1
  29. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_screener.py +95 -0
  30. stock_analysis_plugin-0.2.5/tests/test_stock_data.py +307 -0
  31. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_stock_data_failover.py +39 -70
  32. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_stock_data_margin.py +14 -0
  33. stock_analysis_plugin-0.2.5/tests/test_value_data.py +974 -0
  34. stock_analysis_plugin-0.2.5/tools/_cache.py +61 -0
  35. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/capabilities.py +9 -0
  36. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/diagnostics.py +6 -0
  37. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/screener.py +54 -2
  38. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/stock_data.py +241 -99
  39. stock_analysis_plugin-0.2.5/tools/value_data.py +1368 -0
  40. stock_analysis_plugin-0.2.4/tests/test_stock_data.py +0 -147
  41. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/.github/release.yml +0 -0
  42. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/.github/workflows/autofix.yml +0 -0
  43. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/.github/workflows/ci.yml +0 -0
  44. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/.github/workflows/publish.yml +0 -0
  45. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/.gitignore +0 -0
  46. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/.npmignore +0 -0
  47. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/CLAUDE.md +0 -0
  48. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/LICENSE +0 -0
  49. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/docs/hermes-integration.en.md +0 -0
  50. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/docs/hermes-integration.md +0 -0
  51. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/docs/openclaw-integration.md +0 -0
  52. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/docs/pi-integration.en.md +0 -0
  53. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/docs/pi-integration.md +0 -0
  54. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/dsh/README.md +0 -0
  55. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/dsh/cordis.patch.yml +0 -0
  56. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/hermes/__init__.py +0 -0
  57. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/openclaw/.npmignore +0 -0
  58. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/openclaw/README.md +0 -0
  59. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/requirements-dev.txt +0 -0
  60. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/ruff.toml +0 -0
  61. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/schemas/market_review_schema.json +0 -0
  62. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/schemas/report_schema.json +0 -0
  63. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/scripts/ci-resolve-llm-host.mjs +0 -0
  64. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/scripts/setup-python.mjs +0 -0
  65. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/scripts/sync-version.sh +0 -0
  66. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/scripts/venv-python.mjs +0 -0
  67. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/bottom-volume/SKILL.md +0 -0
  68. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/bottom-volume/scripts/gather.py +0 -0
  69. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/box-oscillation/SKILL.md +0 -0
  70. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/box-oscillation/scripts/gather.py +0 -0
  71. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/bull-trend/SKILL.md +0 -0
  72. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/bull-trend/scripts/gather.py +0 -0
  73. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/chan-theory/SKILL.md +0 -0
  74. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/chan-theory/scripts/gather.py +0 -0
  75. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/dragon-head/SKILL.md +0 -0
  76. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/dragon-head/scripts/gather.py +0 -0
  77. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/emotion-cycle/SKILL.md +0 -0
  78. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/emotion-cycle/scripts/gather.py +0 -0
  79. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/event-driven/scripts/gather.py +0 -0
  80. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/expectation-repricing/SKILL.md +0 -0
  81. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/expectation-repricing/scripts/gather.py +0 -0
  82. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/growth-quality/scripts/gather.py +0 -0
  83. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/hot-theme/SKILL.md +0 -0
  84. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/hot-theme/scripts/gather.py +0 -0
  85. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/ma-crossover/SKILL.md +0 -0
  86. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/ma-crossover/scripts/gather.py +0 -0
  87. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/market-review/SKILL.md +0 -0
  88. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/market-review/scripts/gather.py +0 -0
  89. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/one-yang-three-yin/SKILL.md +0 -0
  90. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/one-yang-three-yin/scripts/gather.py +0 -0
  91. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/shrink-pullback/SKILL.md +0 -0
  92. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/shrink-pullback/scripts/gather.py +0 -0
  93. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/stock-analysis/references/short-term-trading.md +0 -0
  94. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/stock-analysis/scripts/gather.py +0 -0
  95. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/stock-screener/scripts/gather.py +0 -0
  96. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/strategy-backtest/scripts/gather.py +0 -0
  97. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/volume-breakout/SKILL.md +0 -0
  98. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/volume-breakout/scripts/gather.py +0 -0
  99. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/wave-theory/SKILL.md +0 -0
  100. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/wave-theory/scripts/gather.py +0 -0
  101. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/skills/wisburg-research/SKILL.md +0 -0
  102. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/bottom_volume.yaml +0 -0
  103. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/box_oscillation.yaml +0 -0
  104. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/bull_trend.yaml +0 -0
  105. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/dragon_head.yaml +0 -0
  106. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/emotion_cycle.yaml +0 -0
  107. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/ma_crossover.yaml +0 -0
  108. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/rsi_oversold.yaml +0 -0
  109. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/shrink_pullback.yaml +0 -0
  110. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/strategies/examples/volume_breakout.yaml +0 -0
  111. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/templates/_macros.j2 +0 -0
  112. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/templates/market_review/full.md.j2 +0 -0
  113. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/templates/stock_analysis/brief.md.j2 +0 -0
  114. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/templates/stock_analysis/full.md.j2 +0 -0
  115. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/__init__.py +0 -0
  116. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/_stubs/dsh-tools.ts +0 -0
  117. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/_stubs/openclaw-sdk.ts +0 -0
  118. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/_stubs/typebox.ts +0 -0
  119. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/dsh_tool_spy.mjs +0 -0
  120. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/host_smoke.mjs +0 -0
  121. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_dsh_e2e.ts +0 -0
  122. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_hermes_llm.py +0 -0
  123. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_host_to_python.py +0 -0
  124. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_openclaw_e2e.ts +0 -0
  125. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_pi_e2e.ts +0 -0
  126. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_pi_llm.ts +0 -0
  127. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/e2e/test_provider_network.py +0 -0
  128. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_alert_rules.py +0 -0
  129. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_anomaly_detect.py +0 -0
  130. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_backtest.py +0 -0
  131. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_backtest_advanced.py +0 -0
  132. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_capabilities.py +0 -0
  133. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_diagnostics.py +0 -0
  134. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_dsh_sdk_compat.ts +0 -0
  135. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_gather.py +0 -0
  136. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_import_parser.py +0 -0
  137. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_market_regime.py +0 -0
  138. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_market_review.py +0 -0
  139. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_name_resolver.py +0 -0
  140. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_pattern.py +0 -0
  141. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_position_context.py +0 -0
  142. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_report_renderer.py +0 -0
  143. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_risk_screening.py +0 -0
  144. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_search_intel.py +0 -0
  145. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_sentiment.py +0 -0
  146. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_setup_python.mjs +0 -0
  147. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_signal_tracker.py +0 -0
  148. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_skill_workflows.py +0 -0
  149. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_stock_data_short_term.py +0 -0
  150. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_subproc.py +0 -0
  151. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_technical.py +0 -0
  152. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_trading_calendar.py +0 -0
  153. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_volume_analysis.py +0 -0
  154. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_watchlist.py +0 -0
  155. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tests/test_watchlist_context.py +0 -0
  156. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/__init__.py +0 -0
  157. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/_subproc.py +0 -0
  158. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/alert_rules.py +0 -0
  159. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/anomaly_detect.py +0 -0
  160. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/backtest.py +0 -0
  161. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/gather.py +0 -0
  162. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/import_parser.py +0 -0
  163. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/market_regime.py +0 -0
  164. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/market_review.py +0 -0
  165. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/name_resolver.py +0 -0
  166. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/pattern.py +0 -0
  167. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/position_context.py +0 -0
  168. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/report_renderer.py +0 -0
  169. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/requirements.txt +0 -0
  170. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/risk_screening.py +0 -0
  171. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/search_intel.py +0 -0
  172. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/signal_tracker.py +0 -0
  173. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/technical.py +0 -0
  174. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/trading_calendar.py +0 -0
  175. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/volume_analysis.py +0 -0
  176. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/watchlist.py +0 -0
  177. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tools/watchlist_context.py +0 -0
  178. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/tsconfig.json +0 -0
  179. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/typings/openclaw/index.d.ts +0 -0
  180. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.5}/typings/pi-agent/index.d.ts +0 -0
@@ -7,13 +7,13 @@ A multi-host agent plugin for stock analysis, screening, and strategy backtestin
7
7
  The architecture is **one Python core, four thin host adapters**:
8
8
 
9
9
  - `tools/*.py` — the shared CLI tools. **This is the single source of truth** for all behavior. Every tool prints JSON to stdout.
10
- - `pi/index.ts` — Pi extension. `pi.registerTool` ×51, each spawns a `tools/*.py` CLI.
10
+ - `pi/index.ts` — Pi extension. `pi.registerTool` ×57, each spawns a `tools/*.py` CLI.
11
11
  - `hermes/` — Hermes plugin (`plugin.yaml` + `register(ctx)` in `__init__.py`; `tools.py` handlers → subprocess to the same CLIs). Discovered via the `hermes_agent.plugins` entry point.
12
- - `openclaw/` — OpenClaw plugin (`openclaw.plugin.json` manifest + `index.ts` `definePluginEntry` + `registerTool` ×51). Bundled with esbuild.
13
- - `dsh/` — dsh bundle (`package.json` `dsh.bundle` + `cordis.patch.yml` + `index.ts` cordis `apply(ctx)` with `defineTool` ×51 via `@deepseek-ai/dsh-tools`; skills via `ctx.skills.register`). Bundled with esbuild, `@deepseek-ai/*` external (peer deps).
12
+ - `openclaw/` — OpenClaw plugin (`openclaw.plugin.json` manifest + `index.ts` `definePluginEntry` + `registerTool` ×57). Bundled with esbuild.
13
+ - `dsh/` — dsh bundle (`package.json` `dsh.bundle` + `cordis.patch.yml` + `index.ts` cordis `apply(ctx)` with `defineTool` ×57 via `@deepseek-ai/dsh-tools`; skills via `ctx.skills.register`). Bundled with esbuild, `@deepseek-ai/*` external (peer deps).
14
14
  - `skills/*/SKILL.md` — 20 workflow / strategy-methodology skills shared by all four hosts.
15
15
 
16
- > **The invariant that matters most:** the four adapters expose the *same* 51 tools over the *same* Python CLIs. A change to a tool's name, parameters, or JSON output shape must be applied to **all four adapters and the relevant SKILL.md together** — never just one.
16
+ > **The invariant that matters most:** the four adapters expose the *same* 57 tools over the *same* Python CLIs. A change to a tool's name, parameters, or JSON output shape must be applied to **all four adapters and the relevant SKILL.md together** — never just one.
17
17
 
18
18
  ---
19
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: stock-analysis-plugin
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: Hermes plugin for stock analysis, screening, and strategy backtesting across A/HK/US/JP/KR/TW markets
5
5
  Project-URL: Homepage, https://github.com/Weaxs/stock-analysis-plugin
6
6
  Project-URL: Repository, https://github.com/Weaxs/stock-analysis-plugin
@@ -65,7 +65,7 @@ A 股 / 港股 / 美股 / 日股 / 韩股 / 台股综合分析、多因子选股
65
65
 
66
66
  ## 功能概览
67
67
 
68
- - **51 个工具** — 行情数据、技术分析、K 线形态、资金流向、财务指标、新闻舆情、风险筛查、市场状态等
68
+ - **57 个工具** — 行情数据、技术分析、K 线形态、资金流向、估值历史、财报日历、股东/ETF/股息、新闻舆情、风险筛查、市场状态等
69
69
  - **20 个 Skills** — 综合分析、全市场选股、策略回测 + 17 个策略方法论(缠论、波浪、龙头、情绪周期等)
70
70
  - **策略回测引擎** — YAML DSL 定义策略,参数化条件组合,自动诊断,按需进行有限轮参数优化
71
71
  - **多数据源 Failover** — 11 个数据源自动容灾切换(akshare / tushare / efinance / 腾讯行情 / 新浪行情 / pytdx / baostock / yfinance / finnhub / longbridge / alphavantage),A 股链路带粘性优选(最近成功的数据源下次优先尝试)
@@ -126,7 +126,7 @@ register(ctx)
126
126
  openclaw plugins install clawhub:@weaxs/openclaw-stock-analysis
127
127
  ```
128
128
 
129
- OpenClaw Gateway 启动后自动加载并注册 51 个 tool。安装时 postinstall 会自动建 `.venv` 并装好 Python 依赖(前提:本机有 `python3 >= 3.10`)。
129
+ OpenClaw Gateway 启动后自动加载并注册 57 个 tool。安装时 postinstall 会自动建 `.venv` 并装好 Python 依赖(前提:本机有 `python3 >= 3.10`)。
130
130
 
131
131
  详见 [OpenClaw 接入指南](docs/openclaw-integration.md),或 plugin 自身说明 [`openclaw/README.md`](openclaw/README.md)。
132
132
 
@@ -137,7 +137,7 @@ dsh plugin --profile <你的profile> add @weaxs/dsh-stock-analysis
137
137
  dsh --profile <你的profile>
138
138
  ```
139
139
 
140
- 作为 dsh bundle 安装:`dsh plugin add` 会把 `cordis.patch.yml` 叠加进 profile 组合,注册 51 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
140
+ 作为 dsh bundle 安装:`dsh plugin add` 会把 `cordis.patch.yml` 叠加进 profile 组合,注册 57 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
141
141
 
142
142
  详见 [`dsh/README.md`](dsh/README.md)。
143
143
 
@@ -269,7 +269,13 @@ Agent 会自动调用行情 → 技术面 → 基本面 → 资金面 → 消息
269
269
 
270
270
  | 工具 | 说明 |
271
271
  |------|------|
272
- | `get_kline` | K 线数据(OHLCV),支持日/周/月线 |
272
+ | `get_valuation_history` | A/HK PE-TTM/PB 历史、正值分位与估值 Band,实际采样窗口 |
273
+ | `get_index_valuation` | 中国指数 PE/PB 历史水位;中证官方多年滚动 PE;可选理杏仁补充 PB |
274
+ | `get_earnings_calendar` | A 股报告期披露与业绩预告;HK 已公告业绩审批董事会排期/供应商备选日期 |
275
+ | `get_shareholder_structure` | A 股股东户数/十大流通股东变化/报告期北向名义持股;HK 南向持股 |
276
+ | `get_etf_details` | A 股 ETF 净值折溢价、规模变动、披露持仓、可选基准成分与跟踪误差 |
277
+ | `get_dividends` | A/HK 历史分红/除息日历/已实现 TTM 股息与连续年数;A/HK 报告期/年度排行 |
278
+ | `get_kline` | K 线数据(OHLCV),支持日/周/月线;A 股股票/ETF 前复权,每条记录 `adjusted=qfq`,指数 `adjusted=none` |
273
279
  | `get_quote` | 实时行情快照(非交易时段返回最近交易日收盘价并以 as_of/stale 标注;ETF 的 premium_discount_rate 为正=溢价、负=折价) |
274
280
  | `get_capital_flow` | 资金流向(仅 A 股) |
275
281
  | `get_news` | 个股相关新闻 |
@@ -414,11 +420,11 @@ position:
414
420
 
415
421
  ## 市场路由规则
416
422
 
417
- | 代码格式 | 示例 | 市场 | 数据源 Failover 链 |
423
+ | 代码格式 | 示例 | 市场 | 行情报价 Failover 链(K 线差异见下方) |
418
424
  |----------|------|------|---------------------|
419
425
  | 6 位纯数字 | `600519`, `000001`, `300750` | A 股 | akshare → tushare → efinance → 腾讯 → 新浪 → pytdx → baostock |
420
426
  | 6 位纯数字(51/52/56/58/15/16/18 开头) | `510300`, `159915` | A 股 ETF | akshare(基金接口)→ tushare → efinance → 腾讯 → 新浪 → pytdx → baostock |
421
- | 带交易所前缀(`sh`/`sz`/`bj` + 6 位数字) | `sh000001`(上证指数), `sz399006`(创业板指) | A 股(显式指定,含指数) | 腾讯 → 新浪(K 线另有 baostock) |
427
+ | 带交易所前缀(`sh`/`sz`/`bj` + 6 位数字) | `sh000001`(上证指数), `sz399006`(创业板指) | A 股(显式指定,含指数) | 腾讯 → 新浪 |
422
428
  | `.HK` 结尾 | `00700.HK`, `09988.HK` | 港股 | yfinance → finnhub → longbridge |
423
429
  | 英文字母 | `AAPL`, `GOOGL`, `TSLA` | 美股 | yfinance → finnhub → longbridge → alphavantage |
424
430
  | `.T` 结尾 | `7203.T` | 日股 | yfinance |
@@ -427,9 +433,43 @@ position:
427
433
 
428
434
  > 各数据源按优先级自动尝试,前一个失败后自动切换到下一个。未配置相关 env var 的数据源会被跳过。
429
435
  > 裸 6 位代码一律按**个股**处理(`000001` 是平安银行);指数需带交易所前缀(`sh000001` = 上证指数),显式前缀代码直接走腾讯/新浪(东财源只认裸代码)。
436
+ > **A 股 K 线口径**:股票/ETF 仅接受前复权数据,链路为 akshare → tushare(仅股票)→ efinance → 腾讯(仅 qfq 数据)→ baostock;带前缀的股票/ETF 先去前缀再走同一链路。新浪和 pytdx 的未复权 K 线不参与股票/ETF 容灾。显式指数 `sh000xxx` / `sz399xxx` 保留原始点位,走腾讯 → 新浪 → baostock。上述路由表的完整链路仍适用于实时行情。
437
+ > K 线响应保留原有 JSON 数组,每条 A 股记录新增 `adjusted`:股票/ETF 为 `"qfq"`,指数为 `"none"`。Tushare 日线通过 `adj_factor` 前复权,周/月线使用 `stk_week_month_adj` 的 qfq 字段;复权权限不足、因子缺失或源只返回原始价格时继续切换,所有可用复权源都失败时返回 JSON `error`,不降级到未复权股票价格。Tushare 复权接口需至少 2000 积分,见[复权因子](https://tushare.pro/document/2?doc_id=28)与[复权周/月线](https://tushare.pro/document/2?doc_id=365)。
430
438
  > **粘性优选**:A 股链路(K 线 / 行情 / 市场快照 / 板块成分)会记住最近一次成功的数据源(缓存在系统临时目录,24h 有效),下次调用优先从它开始;若它已失效则自动顺延并更新记录。港美股链路不做粘性——一次 yfinance 瞬时失败不应让后续全天的 quote 降质。
431
439
  > 日/韩/台股仅 yfinance 一个数据源(免费数据延迟约 15 分钟);港股 / 美股 / 日股 / 韩股 / 台股的 ETF 与其所在市场股票走相同链路。
432
440
 
441
+
442
+ ## 低频价投与增量数据
443
+
444
+ ```bash
445
+ python tools/value_data.py valuation_history 600519 --years 5
446
+ python tools/stock_data.py financials 600519 --annual --periods 10
447
+ python tools/value_data.py earnings_calendar --report-date 2026-09-30 --symbol 600519
448
+ python tools/value_data.py shareholder_structure 600519 --report-date 2026-06-30
449
+ python tools/value_data.py shareholder_structure 0700.HK
450
+ python tools/value_data.py index_valuation 000300 --years 5
451
+ python tools/value_data.py etf_details 510300 --benchmark sh000300 --days 60
452
+ python tools/value_data.py etf_details 510300 --include-full-holdings
453
+ python tools/stock_data.py margin_trading 600519 --days 10 --include-ratio
454
+ python tools/value_data.py dividends --symbol 600519
455
+ python tools/value_data.py dividends --symbol 0700.HK --mode calendar
456
+ python tools/value_data.py dividends --mode ranking --report-date 2025-12-31
457
+ python tools/value_data.py dividends --mode ranking --market HK --report-date 2025-12-31
458
+ python tools/value_data.py earnings_calendar --symbol 0700.HK
459
+ ```
460
+
461
+ 财报、基本信息及估值/股东/ETF/分红等慢变数据缓存到 `~/.stock-analysis/cache`,TTL 一天;板块成分/映射一周。行情报价不缓存。缓存文件原子替换,过期/损坏重拉,错误和显式部分失败不缓存;不以过期数据伪装最新数据。原有临时目录的粘性路由和反向成分缓存保留。
462
+
463
+ 估值使用可得数据的正值样本分位(`<=当前值`),返回 10/25/50/75/90 分位 Band 与实际起止日期;亏损 PE 分位为 null。当前 AKShare 已无 issue 中提到的 `stock_a_indicator_lg`,个股采用百度 PE-TTM/PB 历史,指数采用乐咕乐股;中证全指等通过中证官方历史接口取得多年滚动 PE,近期总股本 PE1 仍单独保留;PB 缺失时可配置 `LIXINGER_TOKEN` 补充理杏仁总市值加权(mcw)历史,返回每个指标的来源与口径,不拼接不同方法的同一指标。未配置或无权限时 PB 保持未知。A 股 `annual=true, periods=10` 请求十年年报;HK 按源实际可得年数返回,不补造缺失比率。
464
+
465
+ 股东数据保留报告期、公告日或港交所披露日:A 股北向优先返回沪深交易所披露的季度合计数量,省略报告期时查最新已公布季度;十大流通股东中的 HKSCC 推断保留在 `northbound_nominee`,仅作明确标注的兜底,缺席不是零;HK 南向取自港交所 Stock Connect CCASS 记录,不等同完整实益股东名册。A 股财报预约/修订是计划,业绩预告是已公告预估,不是实际业绩。HK 单股优先使用 HKEX 主板/GEM 已公告业绩审批董事会排期,标记 `confirmation=official_board_meeting_notice`、`date_kind=scheduled_board_meeting`;这是计划会议日,不是实际披露日。可按已知财政期末过滤;找不到匹配公告时保留 Yahoo 供应商未来排期,`confirmation=provider_only`,未知报告期不归入指定期次,而另列 `unverified_schedules`。日期转为香港日期,公告表也不承诺覆盖所有港股。
466
+
467
+ ETF 使用披露资产规模历史(元)与披露持仓,保留持仓原始证券代码,不冒充实时完整申赎篮子;新增 `basket` 返回沪深交易所发布的完整当日 PCF(跨境代码原样保留),包含申赎单位、每篮子证券数量、现金替代规则与比例;校验基金代码、实际日期和全部组件数量,失败只提示不可用,不冒充完整。PCF 是申赎对价,不是实际持仓,证券数量也不是净值权重。`include_full_holdings=true` 时另取最近可得半年度/年度披露股票表,显式指定年份/月并请求较高行数上限,包含股票数量(股)、市值(人民币元)和实际报告期;返回全部收到的表格行,但不声称覆盖债券/现金等全资产或实时持仓,也不以 PCF 数量验证实际持仓。默认不取数百行明细。提供 `benchmark` 可另查基准指数成分。净值折溢价仅在行情/净值日期相同才计算,IOPV 折溢价另列。跟踪误差使用相同连续交易日区间的基金日净值增长与基准收盘收益差,取样本标准差乘 `sqrt(252)`,不填补缺失日期、不猜测基准。两融占比只匹配同一天的人民币元成交额,缺失则 null。
468
+
469
+ 股息历史将预案与已实施分红分开,TTM 股息率以过去365天已实施名义每股现金/最新价计算(税前,未重算送转股);空历史、已实施记录缺失日期/金额或分红币种与报价币种不一致时,受影响的总额/股息率返回未知,不猜测汇率;历史不完整时不推断连续分红年数。港股日历、现金历史与报价独立降级,保留可用部分并提示失败来源。日历独立返回已公告未来除息日期。A 股排行/选股使用指定报告期已实施方案股息率;HK 指定 `market=HK` 时使用 HKEX/LSEG 公布的年度股息率(百分数),不是当前价 TTM;HK `report_date` 仅支持数据源可得年度的年末。港股股息选股因子也使用同一年度口径。筛选 YAML 可增加 `filters.dividend_yield_min: 3`、`sort_by: dividend_score` 与可选 `dividend_report_date`;缺失为未知,不按0填充。
470
+
471
+ 数据源参考:[AKShare股票接口](https://akshare.akfamily.xyz/data/stock/stock.html)、[指数接口](https://github.com/akfamily/akshare/blob/main/docs/data/index/index.md)、[基金接口](https://github.com/akfamily/akshare/blob/main/docs/data/fund/fund_public.md)、[港交所南向持股](https://www.hkexnews.hk/sdw/search/mutualmarket.aspx?t=hk)、[HKEX 年度股息率](https://www.hkex.com.hk/Listing/Sustainability/Shareholder-Value-in-Focus/Dividend-Yield-Ratio?sc_lang=en)、[理杏仁指数基本面接口](https://www.lixinger.com/api/open-api/html-doc/cn/index/fundamental)。
472
+
433
473
  ## 独立 CLI 使用
434
474
 
435
475
  Python 工具可脱离 Agent 独立使用,所有输出为 JSON:
@@ -487,26 +527,28 @@ GitHub Actions 的 `e2e-host` 使用 Pi、Hermes、OpenClaw、dsh 的真实运
487
527
  ```
488
528
  stock-analysis/
489
529
  ├── pi/ # Pi Agent Extension
490
- │ └── index.ts # 注册 51 个工具 + 20 个 skill
530
+ │ └── index.ts # 注册 57 个工具 + 20 个 skill
491
531
  ├── hermes/ # Hermes Agent Plugin
492
532
  │ ├── plugin.yaml # 插件清单
493
533
  │ ├── __init__.py # register(ctx) 入口
494
534
  │ ├── schemas.py # 工具 JSON Schema 定义
495
- │ └── tools.py # 51 个 handler → subprocess 调 CLI
535
+ │ └── tools.py # 57 个 handler → subprocess 调 CLI
496
536
  ├── openclaw/ # OpenClaw Plugin
497
537
  │ ├── openclaw.plugin.json # manifest(contracts.tools)
498
538
  │ ├── package.json # 含 openclaw 块(pluginApi/SDK 版本)
499
- │ └── index.ts # definePluginEntry + registerTool ×51
539
+ │ └── index.ts # definePluginEntry + registerTool ×57
500
540
  ├── dsh/ # DeepSeek Harness (dsh) Plugin
501
541
  │ ├── cordis.patch.yml # bundle patch(insert 插件入口)
502
542
  │ ├── package.json # 含 dsh.bundle 块(bundle manifest)
503
- │ └── index.ts # cordis apply(ctx) + defineTool ×51
543
+ │ └── index.ts # cordis apply(ctx) + defineTool ×57
504
544
  │
505
- ├── tools/ # 共享 Python CLI 工具(23 个脚本)
545
+ ├── tools/ # 共享 Python CLI 工具
506
546
  │ ├── stock_data.py # 行情 / 资金流 / 新闻 / 财务 / 短线情绪
507
547
  │ ├── signal_tracker.py # AI 买卖建议回测闭环(本地 JSONL 存储)
508
548
  │ ├── technical.py # 技术指标分析
509
549
  │ ├── pattern.py # K 线形态识别
550
+ │ ├── value_data.py # 估值/财报日历/股东/ETF/股息
551
+ │ ├── _cache.py # 用户目录 TTL 缓存
510
552
  │ ├── screener.py # 全市场多因子筛选(含市场情绪调节,--l2 量化增强)
511
553
  │ ├── backtest.py # 策略回测引擎
512
554
  │ ├── volume_analysis.py # 量价分析
@@ -32,7 +32,7 @@ A 股 / 港股 / 美股 / 日股 / 韩股 / 台股综合分析、多因子选股
32
32
 
33
33
  ## 功能概览
34
34
 
35
- - **51 个工具** — 行情数据、技术分析、K 线形态、资金流向、财务指标、新闻舆情、风险筛查、市场状态等
35
+ - **57 个工具** — 行情数据、技术分析、K 线形态、资金流向、估值历史、财报日历、股东/ETF/股息、新闻舆情、风险筛查、市场状态等
36
36
  - **20 个 Skills** — 综合分析、全市场选股、策略回测 + 17 个策略方法论(缠论、波浪、龙头、情绪周期等)
37
37
  - **策略回测引擎** — YAML DSL 定义策略,参数化条件组合,自动诊断,按需进行有限轮参数优化
38
38
  - **多数据源 Failover** — 11 个数据源自动容灾切换(akshare / tushare / efinance / 腾讯行情 / 新浪行情 / pytdx / baostock / yfinance / finnhub / longbridge / alphavantage),A 股链路带粘性优选(最近成功的数据源下次优先尝试)
@@ -93,7 +93,7 @@ register(ctx)
93
93
  openclaw plugins install clawhub:@weaxs/openclaw-stock-analysis
94
94
  ```
95
95
 
96
- OpenClaw Gateway 启动后自动加载并注册 51 个 tool。安装时 postinstall 会自动建 `.venv` 并装好 Python 依赖(前提:本机有 `python3 >= 3.10`)。
96
+ OpenClaw Gateway 启动后自动加载并注册 57 个 tool。安装时 postinstall 会自动建 `.venv` 并装好 Python 依赖(前提:本机有 `python3 >= 3.10`)。
97
97
 
98
98
  详见 [OpenClaw 接入指南](docs/openclaw-integration.md),或 plugin 自身说明 [`openclaw/README.md`](openclaw/README.md)。
99
99
 
@@ -104,7 +104,7 @@ dsh plugin --profile <你的profile> add @weaxs/dsh-stock-analysis
104
104
  dsh --profile <你的profile>
105
105
  ```
106
106
 
107
- 作为 dsh bundle 安装:`dsh plugin add` 会把 `cordis.patch.yml` 叠加进 profile 组合,注册 51 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
107
+ 作为 dsh bundle 安装:`dsh plugin add` 会把 `cordis.patch.yml` 叠加进 profile 组合,注册 57 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
108
108
 
109
109
  详见 [`dsh/README.md`](dsh/README.md)。
110
110
 
@@ -236,7 +236,13 @@ Agent 会自动调用行情 → 技术面 → 基本面 → 资金面 → 消息
236
236
 
237
237
  | 工具 | 说明 |
238
238
  |------|------|
239
- | `get_kline` | K 线数据(OHLCV),支持日/周/月线 |
239
+ | `get_valuation_history` | A/HK PE-TTM/PB 历史、正值分位与估值 Band,实际采样窗口 |
240
+ | `get_index_valuation` | 中国指数 PE/PB 历史水位;中证官方多年滚动 PE;可选理杏仁补充 PB |
241
+ | `get_earnings_calendar` | A 股报告期披露与业绩预告;HK 已公告业绩审批董事会排期/供应商备选日期 |
242
+ | `get_shareholder_structure` | A 股股东户数/十大流通股东变化/报告期北向名义持股;HK 南向持股 |
243
+ | `get_etf_details` | A 股 ETF 净值折溢价、规模变动、披露持仓、可选基准成分与跟踪误差 |
244
+ | `get_dividends` | A/HK 历史分红/除息日历/已实现 TTM 股息与连续年数;A/HK 报告期/年度排行 |
245
+ | `get_kline` | K 线数据(OHLCV),支持日/周/月线;A 股股票/ETF 前复权,每条记录 `adjusted=qfq`,指数 `adjusted=none` |
240
246
  | `get_quote` | 实时行情快照(非交易时段返回最近交易日收盘价并以 as_of/stale 标注;ETF 的 premium_discount_rate 为正=溢价、负=折价) |
241
247
  | `get_capital_flow` | 资金流向(仅 A 股) |
242
248
  | `get_news` | 个股相关新闻 |
@@ -381,11 +387,11 @@ position:
381
387
 
382
388
  ## 市场路由规则
383
389
 
384
- | 代码格式 | 示例 | 市场 | 数据源 Failover 链 |
390
+ | 代码格式 | 示例 | 市场 | 行情报价 Failover 链(K 线差异见下方) |
385
391
  |----------|------|------|---------------------|
386
392
  | 6 位纯数字 | `600519`, `000001`, `300750` | A 股 | akshare → tushare → efinance → 腾讯 → 新浪 → pytdx → baostock |
387
393
  | 6 位纯数字(51/52/56/58/15/16/18 开头) | `510300`, `159915` | A 股 ETF | akshare(基金接口)→ tushare → efinance → 腾讯 → 新浪 → pytdx → baostock |
388
- | 带交易所前缀(`sh`/`sz`/`bj` + 6 位数字) | `sh000001`(上证指数), `sz399006`(创业板指) | A 股(显式指定,含指数) | 腾讯 → 新浪(K 线另有 baostock) |
394
+ | 带交易所前缀(`sh`/`sz`/`bj` + 6 位数字) | `sh000001`(上证指数), `sz399006`(创业板指) | A 股(显式指定,含指数) | 腾讯 → 新浪 |
389
395
  | `.HK` 结尾 | `00700.HK`, `09988.HK` | 港股 | yfinance → finnhub → longbridge |
390
396
  | 英文字母 | `AAPL`, `GOOGL`, `TSLA` | 美股 | yfinance → finnhub → longbridge → alphavantage |
391
397
  | `.T` 结尾 | `7203.T` | 日股 | yfinance |
@@ -394,9 +400,43 @@ position:
394
400
 
395
401
  > 各数据源按优先级自动尝试,前一个失败后自动切换到下一个。未配置相关 env var 的数据源会被跳过。
396
402
  > 裸 6 位代码一律按**个股**处理(`000001` 是平安银行);指数需带交易所前缀(`sh000001` = 上证指数),显式前缀代码直接走腾讯/新浪(东财源只认裸代码)。
403
+ > **A 股 K 线口径**:股票/ETF 仅接受前复权数据,链路为 akshare → tushare(仅股票)→ efinance → 腾讯(仅 qfq 数据)→ baostock;带前缀的股票/ETF 先去前缀再走同一链路。新浪和 pytdx 的未复权 K 线不参与股票/ETF 容灾。显式指数 `sh000xxx` / `sz399xxx` 保留原始点位,走腾讯 → 新浪 → baostock。上述路由表的完整链路仍适用于实时行情。
404
+ > K 线响应保留原有 JSON 数组,每条 A 股记录新增 `adjusted`:股票/ETF 为 `"qfq"`,指数为 `"none"`。Tushare 日线通过 `adj_factor` 前复权,周/月线使用 `stk_week_month_adj` 的 qfq 字段;复权权限不足、因子缺失或源只返回原始价格时继续切换,所有可用复权源都失败时返回 JSON `error`,不降级到未复权股票价格。Tushare 复权接口需至少 2000 积分,见[复权因子](https://tushare.pro/document/2?doc_id=28)与[复权周/月线](https://tushare.pro/document/2?doc_id=365)。
397
405
  > **粘性优选**:A 股链路(K 线 / 行情 / 市场快照 / 板块成分)会记住最近一次成功的数据源(缓存在系统临时目录,24h 有效),下次调用优先从它开始;若它已失效则自动顺延并更新记录。港美股链路不做粘性——一次 yfinance 瞬时失败不应让后续全天的 quote 降质。
398
406
  > 日/韩/台股仅 yfinance 一个数据源(免费数据延迟约 15 分钟);港股 / 美股 / 日股 / 韩股 / 台股的 ETF 与其所在市场股票走相同链路。
399
407
 
408
+
409
+ ## 低频价投与增量数据
410
+
411
+ ```bash
412
+ python tools/value_data.py valuation_history 600519 --years 5
413
+ python tools/stock_data.py financials 600519 --annual --periods 10
414
+ python tools/value_data.py earnings_calendar --report-date 2026-09-30 --symbol 600519
415
+ python tools/value_data.py shareholder_structure 600519 --report-date 2026-06-30
416
+ python tools/value_data.py shareholder_structure 0700.HK
417
+ python tools/value_data.py index_valuation 000300 --years 5
418
+ python tools/value_data.py etf_details 510300 --benchmark sh000300 --days 60
419
+ python tools/value_data.py etf_details 510300 --include-full-holdings
420
+ python tools/stock_data.py margin_trading 600519 --days 10 --include-ratio
421
+ python tools/value_data.py dividends --symbol 600519
422
+ python tools/value_data.py dividends --symbol 0700.HK --mode calendar
423
+ python tools/value_data.py dividends --mode ranking --report-date 2025-12-31
424
+ python tools/value_data.py dividends --mode ranking --market HK --report-date 2025-12-31
425
+ python tools/value_data.py earnings_calendar --symbol 0700.HK
426
+ ```
427
+
428
+ 财报、基本信息及估值/股东/ETF/分红等慢变数据缓存到 `~/.stock-analysis/cache`,TTL 一天;板块成分/映射一周。行情报价不缓存。缓存文件原子替换,过期/损坏重拉,错误和显式部分失败不缓存;不以过期数据伪装最新数据。原有临时目录的粘性路由和反向成分缓存保留。
429
+
430
+ 估值使用可得数据的正值样本分位(`<=当前值`),返回 10/25/50/75/90 分位 Band 与实际起止日期;亏损 PE 分位为 null。当前 AKShare 已无 issue 中提到的 `stock_a_indicator_lg`,个股采用百度 PE-TTM/PB 历史,指数采用乐咕乐股;中证全指等通过中证官方历史接口取得多年滚动 PE,近期总股本 PE1 仍单独保留;PB 缺失时可配置 `LIXINGER_TOKEN` 补充理杏仁总市值加权(mcw)历史,返回每个指标的来源与口径,不拼接不同方法的同一指标。未配置或无权限时 PB 保持未知。A 股 `annual=true, periods=10` 请求十年年报;HK 按源实际可得年数返回,不补造缺失比率。
431
+
432
+ 股东数据保留报告期、公告日或港交所披露日:A 股北向优先返回沪深交易所披露的季度合计数量,省略报告期时查最新已公布季度;十大流通股东中的 HKSCC 推断保留在 `northbound_nominee`,仅作明确标注的兜底,缺席不是零;HK 南向取自港交所 Stock Connect CCASS 记录,不等同完整实益股东名册。A 股财报预约/修订是计划,业绩预告是已公告预估,不是实际业绩。HK 单股优先使用 HKEX 主板/GEM 已公告业绩审批董事会排期,标记 `confirmation=official_board_meeting_notice`、`date_kind=scheduled_board_meeting`;这是计划会议日,不是实际披露日。可按已知财政期末过滤;找不到匹配公告时保留 Yahoo 供应商未来排期,`confirmation=provider_only`,未知报告期不归入指定期次,而另列 `unverified_schedules`。日期转为香港日期,公告表也不承诺覆盖所有港股。
433
+
434
+ ETF 使用披露资产规模历史(元)与披露持仓,保留持仓原始证券代码,不冒充实时完整申赎篮子;新增 `basket` 返回沪深交易所发布的完整当日 PCF(跨境代码原样保留),包含申赎单位、每篮子证券数量、现金替代规则与比例;校验基金代码、实际日期和全部组件数量,失败只提示不可用,不冒充完整。PCF 是申赎对价,不是实际持仓,证券数量也不是净值权重。`include_full_holdings=true` 时另取最近可得半年度/年度披露股票表,显式指定年份/月并请求较高行数上限,包含股票数量(股)、市值(人民币元)和实际报告期;返回全部收到的表格行,但不声称覆盖债券/现金等全资产或实时持仓,也不以 PCF 数量验证实际持仓。默认不取数百行明细。提供 `benchmark` 可另查基准指数成分。净值折溢价仅在行情/净值日期相同才计算,IOPV 折溢价另列。跟踪误差使用相同连续交易日区间的基金日净值增长与基准收盘收益差,取样本标准差乘 `sqrt(252)`,不填补缺失日期、不猜测基准。两融占比只匹配同一天的人民币元成交额,缺失则 null。
435
+
436
+ 股息历史将预案与已实施分红分开,TTM 股息率以过去365天已实施名义每股现金/最新价计算(税前,未重算送转股);空历史、已实施记录缺失日期/金额或分红币种与报价币种不一致时,受影响的总额/股息率返回未知,不猜测汇率;历史不完整时不推断连续分红年数。港股日历、现金历史与报价独立降级,保留可用部分并提示失败来源。日历独立返回已公告未来除息日期。A 股排行/选股使用指定报告期已实施方案股息率;HK 指定 `market=HK` 时使用 HKEX/LSEG 公布的年度股息率(百分数),不是当前价 TTM;HK `report_date` 仅支持数据源可得年度的年末。港股股息选股因子也使用同一年度口径。筛选 YAML 可增加 `filters.dividend_yield_min: 3`、`sort_by: dividend_score` 与可选 `dividend_report_date`;缺失为未知,不按0填充。
437
+
438
+ 数据源参考:[AKShare股票接口](https://akshare.akfamily.xyz/data/stock/stock.html)、[指数接口](https://github.com/akfamily/akshare/blob/main/docs/data/index/index.md)、[基金接口](https://github.com/akfamily/akshare/blob/main/docs/data/fund/fund_public.md)、[港交所南向持股](https://www.hkexnews.hk/sdw/search/mutualmarket.aspx?t=hk)、[HKEX 年度股息率](https://www.hkex.com.hk/Listing/Sustainability/Shareholder-Value-in-Focus/Dividend-Yield-Ratio?sc_lang=en)、[理杏仁指数基本面接口](https://www.lixinger.com/api/open-api/html-doc/cn/index/fundamental)。
439
+
400
440
  ## 独立 CLI 使用
401
441
 
402
442
  Python 工具可脱离 Agent 独立使用,所有输出为 JSON:
@@ -454,26 +494,28 @@ GitHub Actions 的 `e2e-host` 使用 Pi、Hermes、OpenClaw、dsh 的真实运
454
494
  ```
455
495
  stock-analysis/
456
496
  ├── pi/ # Pi Agent Extension
457
- │ └── index.ts # 注册 51 个工具 + 20 个 skill
497
+ │ └── index.ts # 注册 57 个工具 + 20 个 skill
458
498
  ├── hermes/ # Hermes Agent Plugin
459
499
  │ ├── plugin.yaml # 插件清单
460
500
  │ ├── __init__.py # register(ctx) 入口
461
501
  │ ├── schemas.py # 工具 JSON Schema 定义
462
- │ └── tools.py # 51 个 handler → subprocess 调 CLI
502
+ │ └── tools.py # 57 个 handler → subprocess 调 CLI
463
503
  ├── openclaw/ # OpenClaw Plugin
464
504
  │ ├── openclaw.plugin.json # manifest(contracts.tools)
465
505
  │ ├── package.json # 含 openclaw 块(pluginApi/SDK 版本)
466
- │ └── index.ts # definePluginEntry + registerTool ×51
506
+ │ └── index.ts # definePluginEntry + registerTool ×57
467
507
  ├── dsh/ # DeepSeek Harness (dsh) Plugin
468
508
  │ ├── cordis.patch.yml # bundle patch(insert 插件入口)
469
509
  │ ├── package.json # 含 dsh.bundle 块(bundle manifest)
470
- │ └── index.ts # cordis apply(ctx) + defineTool ×51
510
+ │ └── index.ts # cordis apply(ctx) + defineTool ×57
471
511
  │
472
- ├── tools/ # 共享 Python CLI 工具(23 个脚本)
512
+ ├── tools/ # 共享 Python CLI 工具
473
513
  │ ├── stock_data.py # 行情 / 资金流 / 新闻 / 财务 / 短线情绪
474
514
  │ ├── signal_tracker.py # AI 买卖建议回测闭环(本地 JSONL 存储)
475
515
  │ ├── technical.py # 技术指标分析
476
516
  │ ├── pattern.py # K 线形态识别
517
+ │ ├── value_data.py # 估值/财报日历/股东/ETF/股息
518
+ │ ├── _cache.py # 用户目录 TTL 缓存
477
519
  │ ├── screener.py # 全市场多因子筛选(含市场情绪调节,--l2 量化增强)
478
520
  │ ├── backtest.py # 策略回测引擎
479
521
  │ ├── volume_analysis.py # 量价分析
@@ -0,0 +1,122 @@
1
+ # Issue #44 剩余覆盖的一手来源核验
2
+
3
+ 核验日期:2026-10-12;只记录公开 HTTP 实测与官方口径,不改业务代码。探针和原始响应放在 `/tmp/stock-coverage-probes/`,不提交。接口返回 HTTP 200 不等于有数据,须检查业务错误、日期和完整性。
4
+
5
+ ## 1. 北向季度个股持股:沪深官方接口可用
6
+
7
+ [沪股通官方页面](https://www.sse.com.cn/services/hkexsc/hgtscsj/hgtzqcysl/)明示每季度第 5 个沪股通交易日披露上季度单只证券合计持有数量;其[页面 JS](https://www.sse.com.cn/xhtml/home/2021public/querySearch/search_southboundStock_2021.js)提供当前接口。公开 GET:
8
+
9
+ - URL:`https://query.sse.com.cn/commonSoaQuery.do`
10
+ - 参数:`sqlId=FW_HGTZL_HGTSCSJ_HGTZQCYSL_L&tradeDate=20260630&secCodeName=&isPagination=true&pageHelp.pageSize=2000&pageHelp.pageNo=1`;请求头 `Referer: https://www.sse.com.cn/`。
11
+ - `tradeDate` 必须 `YYYYMMDD`,`2026-06-30` 实测返回空。`secCodeName=600519` 实测返回一条,`totalHoldings=53,711,656.00`;日期留空时服务端返回最新已公布的 `20260630`,不能用最近季末代替最新公布期。
12
+ - 全市场实测 `pageHelp.total=2039`、`pageCount=2`,第一页 2000,第二页 39;`result` 字段为 `secCode/secAbbr/tradeDate/totalHoldings`。含 ETF,完整遍历后仍须辨别证券类型。数量为原始证券单位,不能除以/乘以一万;官方表头仅称“合计持有数量”,没有“万股”标记。股票按股、ETF按份解读,单位由证券类型明确标注。
13
+
14
+ [深股通官方页面](https://www.szse.cn/szhk/szhkshareholding/szholdamount/index.html)源代码指定 `SGT_SGTCGSL`。公开 GET:
15
+
16
+ - URL:`https://www.szse.cn/api/report/ShowReport/data`
17
+ - 参数:`SHOWTYPE=JSON&CATALOGID=SGT_SGTCGSL&txtDate=2026Q2&txtZqdm=&tab1PAGENO=1`。单股查询 `txtZqdm=000001` 实测 `cysl=736,878,410`。
18
+ - `txtDate` 必须 `YYYYQn`;`2026-06-30/20260630/2026-2`均未返回数据。响应是数组,第一元素 `metadata/data/error`;行字段 `zqdm/zqjc/cysl`,代码需去尾空格。
19
+ - 全市场实测 2271 条、114 页、每页 20。`tab1PAGESIZE=2000`被忽略;`tab1PAGENO=114`实测 11 条。含配债记录,如最后一行 `381499 维科配债`,不能全部当股票。
20
+ - 空季度返回 `error=请指定查询周期后,再进行查询`,metadata 没有最新公布期。可从沪市服务端最新公布期获得候选季度,再验证深市该季度;不能从空结果声称持股为零。深市完整 114 页尚未全部下载校验去重,第一页/末页及单股已验证。
21
+
22
+ 旧东方财富/AKShare每日北向持股端点没有用于证明新季度数据;上市公司前十大股东中的 HKSCC 名义账户不等价于完整沪深股通持股库。
23
+
24
+ ## 2. 中证全指 000985 长期估值
25
+
26
+ 本地 AKShare `stock_index_pe_lg/stock_index_pb_lg` 的名称映射不含“中证全指”,不能宣称已覆盖。官方 [000985indicator.xls](https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofile/indicator/000985indicator.xls)实测 20 行(2026-09-14 至 2026-10-09),只含 PE1(总股本)、PE2(计算用股本)、股息率1/2,没有 PB;并非长期 PE-TTM/PB。PE是倍数、股息率是百分数,日期整数`YYYYMMDD`。
27
+
28
+ [官方 factsheet](https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/indices/detail/files/zh_CN/000985factsheet.pdf)本次网页检索到 2025-10-31快照,滚动市盈率与市净率均为`--`,不能据此填补长期 PB。主任务另行实测 `stock_zh_index_hist_csindex` 的官方 `csindex-home/perf/index-perf` 多年滚动 PE 返回 1211 个五年样本;本记录未重复该探针。长期 PB 仍缺一条已核验、无凭据的官方或已装 provider 数据路径;不得用全市场 PB或股票`000985.SZ`(大庆华科)冒充指数。
29
+
30
+ ## 3. ETF完整每日 PCF:沪深及跨境样本可用
31
+
32
+ ### 沪市
33
+
34
+ [上交所 PCF页面](https://www.sse.com.cn/disclosure/fund/etflist/)及[官方 JS](https://www.sse.com.cn/xhtml/home/2021public/querySearch/search_fundInformation_2021.js)提供下载:
35
+
36
+ `GET https://query.sse.com.cn/etfDownload/downloadETF2Bulletin.do?fundCode=510300`,请求头 `Referer: https://www.sse.com.cn/`。实测200 XML,`TradingDay=20261012`、`RecordNumber=300`,`ComponentList/Component`实际300条,`CreationRedemptionUnit=900000`。
37
+
38
+ 同接口`fundCode=513100`(跨境纳指ETF)实测 XML,101个组件,最小申赎单位500000。组件有`InstrumentID/InstrumentName/Quantity/SubstitutionFlag/CreationPremiumRate/RedemptionDiscountRate/SubstitutionCashAmount/UnderlyingSecurityID`,美国股票代码如 AAPL;不要要求六位中国证券代码,或把`UnderlyingSecurityID=9999`当无效证券。日期`YYYYMMDD`;Quantity是每一个最小申赎单位的证券数量,NAV/现金金额为人民币元,溢价比例0.1表示10%。下载入口只有最新期参数,历史同接口的有效日期参数未验证。
39
+
40
+ ### 深市
41
+
42
+ [深交所PCF列表](https://www.szse.cn/disclosure/fund/currency/)公开 GET:
43
+
44
+ `https://www.szse.cn/api/report/ShowReport/data?SHOWTYPE=JSON&CATALOGID=sgshqd&txtJCorDH=159915&txtStart=2026-10-09&txtEnd=2026-10-12`
45
+
46
+ 实测2条。`data[i].jjdm`是HTML,`encode-open`给`/files/text/etf/ETF15991520261012.txt`,下载href的`filename`给`pcf_159915_20261012;159915ETF20261012`。文件host必须由官方[下载页](https://www.szse.cn/modules/report/views/eft_download_new.html?path=%2Ffiles%2Ftext%2FETFDown%2F&filename=pcf_159915_20261012%3B159915ETF20261012&opencode=ETF15991520261012.txt)确定为`reportdocs.static.szse.cn`,`www.szse.cn`下相同文件路径实测404。
47
+
48
+ - [159915 XML](https://reportdocs.static.szse.cn/files/text/ETFDown/pcf_159915_20261012.xml):200;namespace=`http://ts.szse.cn/Fund`;`RecordNum=TotalRecordNum=100`,实际100组件,申赎单位1000000。
49
+ - [159915展示文本](https://reportdocs.static.szse.cn/files/text/etf/ETF15991520261012.txt):200,GB18030/中文固定排版,XML优先。
50
+ - [159941跨境纳指ETF XML](https://reportdocs.static.szse.cn/files/text/ETFDown/pcf_159941_20261012.xml):200;`RecordNum=1`,`TotalRecordNum=102`,包含`159900 申赎现金`及海外证券,不能只拿RecordNum=1认定全部篮子只有现金。
51
+ - 深市组件字段为`UnderlyingSecurityID/UnderlyingSecurityIDSource/UnderlyingSymbol/ComponentShare/SubstituteFlag/PremiumRatio/CreationCashSubstitute/RedemptionCashSubstitute`。`Components/Component`与沪市schema不同;日期、单位及基金级现金部分须同时保留。
52
+
53
+ PCF是当日申购赎回对价篮子,含现金替代规则、现金差额与申赎单位;证券数量不能直接叫实际基金持仓,也不能当NAV权重。完整篮子 != 完整真实资产组合,尤其现金替代、跨境现金申赎。实际基金组合仍需定期报告的资产组合/所有股票投资明细,并标报告期,不能把PCF+前十大持仓拼成“完整实时持仓”。本次没有验证所有ETF品类、历史PCF保存年限或半年度报告完整资产解析,因此上述样本通过仅证明该公开路径可实施。
54
+
55
+ ## 4. 次要项:HK股息排行榜与披露日历
56
+
57
+ [HKEX官方股息率网页](https://www.hkex.com.hk/Listing/Sustainability/Shareholder-Value-in-Focus/Dividend-Yield-Ratio?sc_lang=en)已公开全体发行人表格(检索可见按比率排序),供应商LSEG,latest annual及2025/2024/2023/2022口径;这不是今日TTM股息率。页面[官方JS](https://www.hkex.com.hk/lhkexw/js/capitalefficiency.js)调用`getcapitalefficiencylist`,带`LabCI.getToken()`和页参数;未验证该服务URL/公开token获取链,不能宣称当前已有稳定无凭据批量API。另一[证券报价页](https://www.hkex.com.hk/Market-Data/Securities-Prices/Equities?sc_lang=en)公开Dividend Yield(%)及筛选,但同样未核验全市场API完整分页及计算口径。
58
+
59
+ [HKEXnews董事会通知列表](https://www1.hkexnews.hk/search/predefineddoc.xhtml?predefineddocuments=5)公开可读通知标题、公告时间和代码;[HKEX官方FAQ](https://www.hkex.com.hk/Global/Exchange/FAQ/Getting-Started?sc_lang=en)要求相关董事会会议至少提前7个完整营业日公告。可用来构建证据化日历,但必须解析董事会通知正文的会议日期和目的/改期,公告发布时间不是业绩披露日期。仅列表有数据不足以证明完整、准确的未来业绩日历。`hkexgroup.com`Financial Calendar仅HKEX自身发行人,不是所有港股。
60
+
61
+ ### 后续实测更新:HK两项均有可实现的公开来源
62
+
63
+ 以下结果补足上述第4节的接口未验证状态,核验仍为2026-10-12。
64
+
65
+ **HKEX全市场年度股息率榜**:已实际取到完整2808条、2808个唯一证券代码。官方[配置JS](https://www.hkex.com.hk/lhkexw/js/lib/ssdl/ssdlconfig.js)指定服务根`https://www1.hkex.com.hk/hkexwidget/data/`,[页面业务JS](https://www.hkex.com.hk/lhkexw/js/capitalefficiency.js)指定`getcapitalefficiencylist`及参数。请求步骤:
66
+
67
+ 1. GET上述官方Dividend-Yield-Ratio页面,读取HTML内`LabCI.getToken = function () { ... return "..."; };`的公开访问值。函数同时有注释掉的sample return,必须先删除函数块的`//`行注释再提取实际return。只动态使用,不硬编码、不日志、不保存该值。字面`anonymoustoken`实测403。
68
+ 2. GET `https://www1.hkex.com.hk/hkexwidget/data/getcapitalefficiencylist`,参数`token=<页面公开值>&type=DYR&sector=null&hsi=0&page=1&limit=3000&sort=1&dir=1&lang=eng&callback=probe&qid=1`;headers `Referer: https://www.hkex.com.hk/`、`User-Agent: Mozilla/5.0`。完整参数实测200,JSONP固定wrapper `probe(...)`,应解析JSON不可执行JS。第一次省略若干参数/UA的请求403,原因未单变量定位,因此保留官网调用形状。
69
+ 3. 结果`data.responsecode=000`、`totalCount=2808`、`datalist`2808条、`year=[2025,2024,2023,2022]`。`limit=500`实测500条;`limit=100`时page1/2/28各100、page29为8。全量响应和这四个分页逐行相同、totalCount与year相同,未发现首次失败导致的快照不一致。
70
+ 4. 行结构`{sym,nm,period,data}`,例如`169/WANDA HOTEL DEV/2025 Annual`,`data=[408.85,408.85,0.00,0.00,0.00]`(实际为字符串)。`data[0]`为latest annual,比率百分数,`data[1..4]`与year列表逐项对应。空字符串/`N/A`为未知,不能变成0。`period`是其数据所属年度,不能套用A股传入的季度report_date。可能有`mcounter`其他货币交易柜台字段,应明确按发行人/主交易代码口径,不重复排名。
71
+ 5. 一请求足够当前规模,但运行时必须检查`len(datalist)==totalCount`和证券代码唯一,未来超过3000时分页补齐;失败不得返回部分结果并称完整。此榜是年度公开财报口径,并非当日TTM,不应与A股股息数据混写同一计算口径。
72
+
73
+ 安全原始响应:`/tmp/stock-coverage-probes/hk-dividend-limit3000.json`及page1/2/28/29 JSON,均不含访问值。
74
+
75
+ **HK单证券财报日历**:已装yfinance1.3.0实际无需用户凭据取得0700.HK、0388.HK、0005.HK的未来及历史业绩日期。
76
+
77
+ - `Ticker.calendar['Earnings Date']`实测分别为2026-11-18、2026-11-06、2026-10-27。`Ticker.get_earnings_dates(limit=6)`同时返回未来行(Reported EPS空)和历史行(Reported EPS有值),底层当前走[源码中的Yahoo earnings-calendar HTML](https://github.com/ranaroussi/yfinance/blob/main/yfinance/base.py),不是财报报表期末日期。
78
+ - Yahoo官方[0700.HK报价页](https://finance.yahoo.com/quote/0700.HK/)也明示Earnings Date=Nov18,2026。[HSBC自身日历](https://www.hsbc.com/investors/investing-in-hsbc/financial-calendar)证实0005的2026-10-27。HKEX自身[IR页面](https://www.hkexgroup.com/investor-relations?sc_lang=en)本次检索仍标Q3 TBC,Financial Calendar只November2026;Yahoo的0388精确11/6不能仅凭供应商升格为官方确认。
79
+ - `get_earnings_dates`实测返回America/New_York时间,必须先`tz_convert('Asia/Hong_Kong')`再取日期。例如0388历史`2026-02-25 23:00-05:00`实际香港日期2/26,与发行人官网一致。直接取datetime的date会早一天。
80
+ - `calendar`公开接口由源码`datetime.fromtimestamp(...).date()`产生本机日期,且丢弃供应商确认标志,单独依赖它有主机时区风险。内部原始`calendarEvents.earnings`有`earningsDate`Unix秒和`isEarningsDateEstimate`(三个样本均false),但内部方法不是稳定公开接口,且false仅是供应商判断。原始非敏感`calendarEvents`存于`/tmp/stock-coverage-probes/hk-calendar-{0700.HK,0388.HK,0005.HK}.json`。
81
+ - 可交付范围:HK单股provider_estimate/provider_scheduled日期、历史provider_reported日期,来源与确认级别显式标注,报告期未知时保持unknown,不能将requestedquarter作为实际report_date;没有日期则unknown,不能预测填充。未验证全港股或全市场按季度完整排期;实际公布日期若只以历史EPS事件判断仍属供应商记录,官方确认需要对应业绩公告证据。
82
+
83
+ ### HKEX访问值编码故障复现与修复依据
84
+
85
+ 主任务实现首次实时请求403后,追加只读差异验证:同一旧来源HTML的访问值,callback分别`probe/stockrank`均200;fresh HTML的访问值,两个callback均403;requests.Session保留来源页面cookies也403,因此不能通过换callback/Session修复。本次fresh来源函数返回值含URL百分号编码,直接交给`requests.get(params=...)`会把`%`再次编码为`%25`。官网SSDL源码将参数直接拼进querystring,未发生此二次编码。
86
+
87
+ 已用当前fresh页面验证:`urllib.parse.unquote(token_match.group(1))`解码一次后,再交给requests params,`callback=stockrank,limit=3000`实际200且2808条完整响应。不需要旧访问值、硬编码或用户凭据。首次研究旧HTML值为未百分号编码形态,故未暴露此差异。实现应覆盖“官网值已percent-encoded”的用例,且任何失败信息不得带包含访问值的请求URL。此修复验证只在`/tmp/hk_token_decode.py`探针进行,本研究代理未改业务代码。
88
+
89
+ ## 第三轮补足验证:无凭据长期PB与官方HK排期
90
+
91
+ ### 000985长期PB:公开乐咕路径可访问但目标指数无数据
92
+
93
+ [乐咕000985.CSI页面](https://www.legulegu.com/stockdata/index-basic?indexCode=000985.CSI)当前实际200,标题“中证全指”、内容标“中证全指指数 · 000985.CSI”;`.SH`页面标题“中证全指(SH)”。这证明页面身份,并不能证明历史数据存在。[官网页面JS](https://www.legulegu.com/static/js/lg-charts-industry-chart.js)明确普通图表请求`/api/stockdata/index-basic?indexCode=...&freq=day&token=...`,主题图表省略freq;token是官网JS将当日`YYYY-MM-DD`做MD5产生的公开页面请求标识,另有正常CSRF/cookies链。探针只执行公开页面正常读取流程,未用登录凭据/伪造VIP或绕身份校验。
94
+
95
+ 实际API:`https://www.legulegu.com/api/stockdata/index-basic`,参数`indexCode=000985.CSI`或`000985.SH`,`freq=day/month`或省略,带正常页面CSRF/cookies、Referer及当日公开请求标识,均200但`data=[]`、`vip=false/user=false`。同链正控`930743.CSI`实测61条(2021-10-29至2026-10-12),包含`pb/addPb/middlePb`,所以不能把目标空数据归因于全站网络失败;也不能将生科指数PB套给中证全指。公开overview索引没有找到000985链接。本次仅证明“这些公开请求没有目标数据”,不能推断VIP是否有数据。
96
+
97
+ 原始目标空响应与正控放于`/tmp/stock-coverage-probes/legu-000985.CSI.json`、`legu-000985.SH.json`、`legu-930743.CSI-None.json`,不含请求访问值。无配置LIXINGER_TOKEN/TUSHARE_TOKEN时,中证全指多年PB仍应报告blocked/unknown;已验证CSI多年PE与仅20行PE/dividend文件不能填补PB。完整实时真实持仓也不等于PCF,任何新增来源必须独立核验口径。
98
+
99
+ ### HK官方通用已公告排期:主板/GEM董事会通知汇总表已取到
100
+
101
+ 无需ticker硬编码或用户凭据,公开GET:
102
+
103
+ - [Main Board董事会排期](https://www.hkex-is.hk/wwwroot/link/ebmn.htm)
104
+ - [GEM董事会排期](https://www.hkex-is.hk/wwwroot/link/ebmngem.htm)
105
+
106
+ HKEX[官方说明](https://www.hkex.com.hk/News/News-Release/2011/110902news?sc_lang=en)明确`www.hkex-is.hk`为额外公告板,官方[投资者FAQ](https://www.hkex.com.hk/-/media/HKEX-Market/Listing/Rules-and-Guidance/eSubmission-System/Listed-Company-Information-Dissemination-and-Related-Trading-Arrangements/faqinv.pdf)说明可在Exchange Reports/Board Meeting Notifications查看上市公司排期。这是官方汇总证据,并非Yahoo供应商预计。
107
+
108
+ 当前两页实际200,更新时间`Date : 09/10/2026`。HTML最后一张表有6列:`BM Date / 空列 / Stock Short Name / Code / Purpose / Period`。`pd.read_html(StringIO(html),keep_default_na=False)[-1]`实测Main `(43,6)`、GEM `(3,6)`,前两行是表头和虚线,实际41/1记录;代码在本次解析为字符串`388/700/8307`,仍应按字符串去空格再zfill(5),不接受`388.0`。
109
+
110
+ 通用处理:按明确`%d/%m/%Y`解析BM Date;保留Purpose、Period原文,只有结果用途(如RESULTS、3RD QUARTER RES、FIN RES/DIV、INT RES/DIV)进入财报排期,纯`3RD INT DIV`不能当业绩事件,`QUARTERLY REVENUE`也不能凭名字升格为财报。Period含`9-MTH-ENDED30/09/26`或`Y.E.31/07/26`时可独立提取明确期末`%d/%m/%y`;只有`THIRD QUARTER 2026`则保留原文、不从用户requestedquarter伪造actual报告期。无Period保持unknown。
111
+
112
+ 例证:表内已公布`00388 HKEX`会议2026-11-06、用途RESULTS、期末2026-09-30;`00700 TENCENT`会议2026-11-18、用途3RD QUARTER RES/DIV、期末2026-09-30;`08307 MEDICSKIN`会议2026-11-24、RESULTS/INT DIV、期末2026-09-30;此外含大量其他证券。前文HKEX发行人页面TBC是当时检索的旧页面状态,此更新汇总表提供了其精确日期官方排期证据。
113
+
114
+ 输出应标`scheduled_board_meeting`与`confirmation=official_exchange_schedule`、`scheduled_date`及独立`report_date`;`actual_disclosure_date`仍unknown。这些表明确“may not be exhaustive”“以发行人公告为准”,多日会议只显示首日。因此可补足官方已公告排期的通用来源,但不承诺全部港股覆盖,不把不在列表当无排期,不把会议日期自动当实际披露日期,也不声称历史完整列表。实际公布日期仍需对应业绩公告。供应商回退若保留必须单独标provider_estimate,并不得覆盖本官方证据。
115
+
116
+ 原始完整HTML:`/tmp/stock-coverage-probes/hk-board-main.html`、`hk-board-gem.html`。原始报告含人民币柜台(如80388/80700),它们是明确表中证券代码,不能无证据与主柜台混成两个独立发行人。
117
+
118
+ ## 后续实测:定期披露股票表
119
+
120
+ 2026-10-12 实测东财 FundArchivesDatas.aspx type=jjcc,只有显式 year/month 才取得目标报告较完整股票表,year留空即使topline10000仍只有最新季度10条。year=2026,month=6,topline=10000实测510300为339条、159915为121条、513100为102条,报告日均2026-06-30。源列持股数为万股、市值为万元(跨境列万元人民币),规范化分别乘10000;原始证券代码按字符串保留。未以股票表推断完整全资产,未用PCF证券数量或指数名单替代实际组合,未声称实时持仓。源:[基金股票持仓](https://fundf10.eastmoney.com/ccmx_510300.html)、[AKShare持仓实现](https://github.com/akfamily/akshare/blob/main/akshare/fund/fund_portfolio_em.py)。
121
+
122
+ PR #47 b9f30b8 的CI已全部通过:Python3.10/3.11、三系统compat、四真实宿主、网络和LLM e2e均成功。后续新增实现仍需在新提交上重跑,不能沿用旧提交CI结果。