stock-analysis-plugin 0.2.4__tar.gz → 0.2.6__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 (194) hide show
  1. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/.github/workflows/ci.yml +3 -0
  2. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/AGENTS.md +4 -4
  3. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/PKG-INFO +115 -16
  4. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/README.md +105 -14
  5. stock_analysis_plugin-0.2.6/docs/research/issue-44-coverage-sources.md +122 -0
  6. stock_analysis_plugin-0.2.6/docs/research/issue-51-reverse-holdings.md +30 -0
  7. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/dsh/index.ts +258 -14
  8. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/dsh/package.json +1 -1
  9. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/hermes/plugin.yaml +9 -0
  10. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/hermes/schemas.py +171 -10
  11. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/hermes/tools.py +109 -6
  12. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/openclaw/index.ts +158 -14
  13. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/openclaw/openclaw.plugin.json +10 -1
  14. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/openclaw/package.json +1 -1
  15. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/package-lock.json +2 -2
  16. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/package.json +1 -1
  17. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/pi/index.ts +290 -14
  18. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/pyproject.toml +10 -2
  19. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/schemas/report_schema.json +3 -3
  20. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/scripts/setup-python.mjs +6 -6
  21. stock_analysis_plugin-0.2.6/skills/bull-trend/SKILL.md +81 -0
  22. stock_analysis_plugin-0.2.6/skills/bull-trend/references/fat-tails.md +91 -0
  23. stock_analysis_plugin-0.2.6/skills/bull-trend/scripts/tail_analysis.py +132 -0
  24. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/event-driven/SKILL.md +8 -0
  25. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/growth-quality/SKILL.md +8 -0
  26. stock_analysis_plugin-0.2.6/skills/stock-analysis/SKILL.md +114 -0
  27. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/stock-screener/SKILL.md +20 -0
  28. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/strategy-backtest/SKILL.md +6 -0
  29. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/wisburg-research/SKILL.md +2 -0
  30. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/templates/stock_analysis/brief.md.j2 +4 -1
  31. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/templates/stock_analysis/full.md.j2 +6 -3
  32. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/conftest.py +10 -0
  33. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_dsh_e2e.ts +12 -0
  34. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_openclaw_e2e.ts +12 -0
  35. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_provider_network.py +28 -3
  36. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_alert_rules.py +47 -0
  37. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_backtest.py +42 -6
  38. stock_analysis_plugin-0.2.6/tests/test_data_cache.py +47 -0
  39. stock_analysis_plugin-0.2.6/tests/test_disclosures.py +93 -0
  40. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_dsh_integration.ts +54 -4
  41. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_gather.py +61 -19
  42. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_hermes_integration.py +148 -1
  43. stock_analysis_plugin-0.2.6/tests/test_hk_lixinger.py +211 -0
  44. stock_analysis_plugin-0.2.6/tests/test_kline_adjustment.py +194 -0
  45. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_market_regime.py +6 -0
  46. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_market_review.py +8 -0
  47. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_openclaw_integration.ts +55 -3
  48. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_pi_integration.ts +61 -1
  49. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_position_context.py +32 -0
  50. stock_analysis_plugin-0.2.6/tests/test_provider_network_helpers.py +30 -0
  51. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_report_renderer.py +24 -0
  52. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_risk_screening.py +63 -1
  53. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_screener.py +118 -0
  54. stock_analysis_plugin-0.2.6/tests/test_sec_edgar.py +384 -0
  55. stock_analysis_plugin-0.2.6/tests/test_sec_holders.py +237 -0
  56. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_setup_python.mjs +3 -2
  57. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_signal_tracker.py +154 -11
  58. stock_analysis_plugin-0.2.6/tests/test_stock_data.py +307 -0
  59. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_stock_data_failover.py +208 -71
  60. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_stock_data_margin.py +14 -0
  61. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_subproc.py +25 -0
  62. stock_analysis_plugin-0.2.6/tests/test_tail_analysis_skill.py +106 -0
  63. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_technical.py +4 -1
  64. stock_analysis_plugin-0.2.6/tests/test_value_data.py +974 -0
  65. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_watchlist.py +18 -3
  66. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_watchlist_context.py +21 -0
  67. stock_analysis_plugin-0.2.6/tools/_cache.py +61 -0
  68. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/alert_rules.py +32 -4
  69. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/backtest.py +22 -4
  70. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/capabilities.py +12 -0
  71. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/diagnostics.py +6 -0
  72. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/gather.py +20 -10
  73. stock_analysis_plugin-0.2.6/tools/lixinger.py +100 -0
  74. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/market_regime.py +7 -3
  75. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/market_review.py +7 -6
  76. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/position_context.py +20 -2
  77. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/report_renderer.py +2 -0
  78. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/risk_screening.py +45 -17
  79. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/screener.py +64 -4
  80. stock_analysis_plugin-0.2.6/tools/sec_edgar.py +346 -0
  81. stock_analysis_plugin-0.2.6/tools/sec_holders.py +263 -0
  82. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/signal_tracker.py +142 -19
  83. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/stock_data.py +321 -116
  84. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/technical.py +16 -2
  85. stock_analysis_plugin-0.2.6/tools/value_data.py +1527 -0
  86. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/watchlist.py +24 -1
  87. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/watchlist_context.py +7 -3
  88. stock_analysis_plugin-0.2.4/skills/bull-trend/SKILL.md +0 -57
  89. stock_analysis_plugin-0.2.4/skills/stock-analysis/SKILL.md +0 -86
  90. stock_analysis_plugin-0.2.4/tests/test_stock_data.py +0 -147
  91. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/.github/release.yml +0 -0
  92. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/.github/workflows/autofix.yml +0 -0
  93. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/.github/workflows/publish.yml +0 -0
  94. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/.gitignore +0 -0
  95. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/.npmignore +0 -0
  96. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/CLAUDE.md +0 -0
  97. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/LICENSE +0 -0
  98. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/docs/hermes-integration.en.md +0 -0
  99. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/docs/hermes-integration.md +0 -0
  100. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/docs/openclaw-integration.md +0 -0
  101. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/docs/pi-integration.en.md +0 -0
  102. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/docs/pi-integration.md +0 -0
  103. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/dsh/README.md +0 -0
  104. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/dsh/cordis.patch.yml +0 -0
  105. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/hermes/__init__.py +0 -0
  106. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/openclaw/.npmignore +0 -0
  107. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/openclaw/README.md +0 -0
  108. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/requirements-dev.txt +0 -0
  109. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/ruff.toml +0 -0
  110. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/schemas/market_review_schema.json +0 -0
  111. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/scripts/ci-resolve-llm-host.mjs +0 -0
  112. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/scripts/sync-version.sh +0 -0
  113. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/scripts/venv-python.mjs +0 -0
  114. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/bottom-volume/SKILL.md +0 -0
  115. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/bottom-volume/scripts/gather.py +0 -0
  116. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/box-oscillation/SKILL.md +0 -0
  117. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/box-oscillation/scripts/gather.py +0 -0
  118. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/bull-trend/scripts/gather.py +0 -0
  119. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/chan-theory/SKILL.md +0 -0
  120. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/chan-theory/scripts/gather.py +0 -0
  121. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/dragon-head/SKILL.md +0 -0
  122. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/dragon-head/scripts/gather.py +0 -0
  123. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/emotion-cycle/SKILL.md +0 -0
  124. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/emotion-cycle/scripts/gather.py +0 -0
  125. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/event-driven/scripts/gather.py +0 -0
  126. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/expectation-repricing/SKILL.md +0 -0
  127. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/expectation-repricing/scripts/gather.py +0 -0
  128. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/growth-quality/scripts/gather.py +0 -0
  129. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/hot-theme/SKILL.md +0 -0
  130. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/hot-theme/scripts/gather.py +0 -0
  131. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/ma-crossover/SKILL.md +0 -0
  132. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/ma-crossover/scripts/gather.py +0 -0
  133. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/market-review/SKILL.md +0 -0
  134. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/market-review/scripts/gather.py +0 -0
  135. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/one-yang-three-yin/SKILL.md +0 -0
  136. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/one-yang-three-yin/scripts/gather.py +0 -0
  137. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/shrink-pullback/SKILL.md +0 -0
  138. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/shrink-pullback/scripts/gather.py +0 -0
  139. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/stock-analysis/references/short-term-trading.md +0 -0
  140. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/stock-analysis/scripts/gather.py +0 -0
  141. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/stock-screener/scripts/gather.py +0 -0
  142. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/strategy-backtest/scripts/gather.py +0 -0
  143. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/volume-breakout/SKILL.md +0 -0
  144. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/volume-breakout/scripts/gather.py +0 -0
  145. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/wave-theory/SKILL.md +0 -0
  146. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/skills/wave-theory/scripts/gather.py +0 -0
  147. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/bottom_volume.yaml +0 -0
  148. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/box_oscillation.yaml +0 -0
  149. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/bull_trend.yaml +0 -0
  150. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/dragon_head.yaml +0 -0
  151. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/emotion_cycle.yaml +0 -0
  152. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/ma_crossover.yaml +0 -0
  153. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/rsi_oversold.yaml +0 -0
  154. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/shrink_pullback.yaml +0 -0
  155. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/strategies/examples/volume_breakout.yaml +0 -0
  156. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/templates/_macros.j2 +0 -0
  157. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/templates/market_review/full.md.j2 +0 -0
  158. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/__init__.py +0 -0
  159. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/_stubs/dsh-tools.ts +0 -0
  160. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/_stubs/openclaw-sdk.ts +0 -0
  161. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/_stubs/typebox.ts +0 -0
  162. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/dsh_tool_spy.mjs +0 -0
  163. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/host_smoke.mjs +0 -0
  164. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_hermes_llm.py +0 -0
  165. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_host_to_python.py +0 -0
  166. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_pi_e2e.ts +0 -0
  167. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/e2e/test_pi_llm.ts +0 -0
  168. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_anomaly_detect.py +0 -0
  169. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_backtest_advanced.py +0 -0
  170. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_capabilities.py +0 -0
  171. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_diagnostics.py +0 -0
  172. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_dsh_sdk_compat.ts +0 -0
  173. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_import_parser.py +0 -0
  174. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_name_resolver.py +0 -0
  175. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_pattern.py +0 -0
  176. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_search_intel.py +0 -0
  177. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_sentiment.py +0 -0
  178. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_skill_workflows.py +0 -0
  179. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_stock_data_short_term.py +0 -0
  180. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_trading_calendar.py +0 -0
  181. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tests/test_volume_analysis.py +0 -0
  182. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/__init__.py +0 -0
  183. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/_subproc.py +0 -0
  184. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/anomaly_detect.py +0 -0
  185. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/import_parser.py +0 -0
  186. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/name_resolver.py +0 -0
  187. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/pattern.py +0 -0
  188. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/requirements.txt +0 -0
  189. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/search_intel.py +0 -0
  190. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/trading_calendar.py +0 -0
  191. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tools/volume_analysis.py +0 -0
  192. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/tsconfig.json +0 -0
  193. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/typings/openclaw/index.d.ts +0 -0
  194. {stock_analysis_plugin-0.2.4 → stock_analysis_plugin-0.2.6}/typings/pi-agent/index.d.ts +0 -0
@@ -153,6 +153,9 @@ jobs:
153
153
  - name: Run host↔python round-trip tests
154
154
  run: pytest tests/e2e/test_host_to_python.py -v
155
155
 
156
+ - name: Signal store and analysis regressions
157
+ run: pytest tests/test_signal_tracker.py tests/test_gather.py tests/test_watchlist.py tests/test_watchlist_context.py -q
158
+
156
159
  - name: Pi host real subprocess round-trip
157
160
  run: npx tsx tests/e2e/test_pi_e2e.ts
158
161
 
@@ -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` ×60, 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` ×60). Bundled with esbuild.
13
+ - `dsh/` — dsh bundle (`package.json` `dsh.bundle` + `cordis.patch.yml` + `index.ts` cordis `apply(ctx)` with `defineTool` ×60 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* 60 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.6
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
@@ -23,12 +23,20 @@ Classifier: Topic :: Scientific/Engineering :: Information Analysis
23
23
  Requires-Python: >=3.10
24
24
  Requires-Dist: akshare>=1.14.0; python_version < '3.11'
25
25
  Requires-Dist: akshare>=1.18.97; python_version >= '3.11'
26
+ Requires-Dist: baostock>=0.8.8
27
+ Requires-Dist: efinance>=0.5.0
26
28
  Requires-Dist: exchange-calendars>=4.5.0
29
+ Requires-Dist: finnhub-python>=2.4.0
27
30
  Requires-Dist: jinja2>=3.1.0
31
+ Requires-Dist: longport>=1.0.0
32
+ Requires-Dist: newspaper4k>=0.9.0
28
33
  Requires-Dist: numpy>=1.24.0
29
34
  Requires-Dist: pandas>=2.0.0
35
+ Requires-Dist: pypinyin>=0.50.0
36
+ Requires-Dist: pytdx>=1.72
30
37
  Requires-Dist: pyyaml>=6.0
31
- Requires-Dist: requests>=2.28.0
38
+ Requires-Dist: requests>=2.31.0
39
+ Requires-Dist: yfinance>=0.2.36
32
40
  Description-Content-Type: text/markdown
33
41
 
34
42
  # stock-analysis-plugin
@@ -65,7 +73,7 @@ A 股 / 港股 / 美股 / 日股 / 韩股 / 台股综合分析、多因子选股
65
73
 
66
74
  ## 功能概览
67
75
 
68
- - **51 个工具** — 行情数据、技术分析、K 线形态、资金流向、财务指标、新闻舆情、风险筛查、市场状态等
76
+ - **60 个工具** — 行情数据、技术分析、K 线形态、资金流向、估值历史、财报日历、股东/ETF/股息、新闻舆情、风险筛查、市场状态等
69
77
  - **20 个 Skills** — 综合分析、全市场选股、策略回测 + 17 个策略方法论(缠论、波浪、龙头、情绪周期等)
70
78
  - **策略回测引擎** — YAML DSL 定义策略,参数化条件组合,自动诊断,按需进行有限轮参数优化
71
79
  - **多数据源 Failover** — 11 个数据源自动容灾切换(akshare / tushare / efinance / 腾讯行情 / 新浪行情 / pytdx / baostock / yfinance / finnhub / longbridge / alphavantage),A 股链路带粘性优选(最近成功的数据源下次优先尝试)
@@ -126,7 +134,7 @@ register(ctx)
126
134
  openclaw plugins install clawhub:@weaxs/openclaw-stock-analysis
127
135
  ```
128
136
 
129
- OpenClaw Gateway 启动后自动加载并注册 51 个 tool。安装时 postinstall 会自动建 `.venv` 并装好 Python 依赖(前提:本机有 `python3 >= 3.10`)。
137
+ OpenClaw Gateway 启动后自动加载并注册 60 个 tool。安装时 postinstall 会自动建 `.venv` 并装好 Python 依赖(前提:本机有 `python3 >= 3.10`)。
130
138
 
131
139
  详见 [OpenClaw 接入指南](docs/openclaw-integration.md),或 plugin 自身说明 [`openclaw/README.md`](openclaw/README.md)。
132
140
 
@@ -137,7 +145,7 @@ dsh plugin --profile <你的profile> add @weaxs/dsh-stock-analysis
137
145
  dsh --profile <你的profile>
138
146
  ```
139
147
 
140
- 作为 dsh bundle 安装:`dsh plugin add` 会把 `cordis.patch.yml` 叠加进 profile 组合,注册 51 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
148
+ 作为 dsh bundle 安装:`dsh plugin add` 会把 `cordis.patch.yml` 叠加进 profile 组合,注册 60 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
141
149
 
142
150
  详见 [`dsh/README.md`](dsh/README.md)。
143
151
 
@@ -160,7 +168,7 @@ pip install -r tools/requirements.txt
160
168
  | pytdx | A 股 TDX 行情(免费兜底源) |
161
169
  | longport | 港股 / 美股 Longbridge SDK |
162
170
 
163
- > A 股行情另有**腾讯(qt.gtimg.cn)/ 新浪(hq.sinajs.cn)**两个免鉴权兜底源,不依赖任何 Python 包(直接 HTTP 调用),用于东财域名不可达的网络环境(境外主机、企业出网限制等)。
171
+ > A 股行情另有**腾讯(qt.gtimg.cn)/ 新浪(hq.sinajs.cn)**两个免鉴权兜底源,直接 HTTP 调用,用于东财域名不可达的网络环境(境外主机、企业出网限制等)。港股实时行情也使用腾讯作为 yfinance 之后的免 key 备用源。
164
172
 
165
173
  ### 环境变量
166
174
 
@@ -180,6 +188,8 @@ pip install -r tools/requirements.txt
180
188
 
181
189
  | 环境变量 | 用途 |
182
190
  |---------|------|
191
+ | `LIXINGER_TOKEN` | 理杏仁可选数据源:指数 PB 与港股非金融公司财务/每日估值(需对应权限) |
192
+ | `SEC_USER_AGENT` | SEC EDGAR 身份声明:应用名称与真实联系邮箱,13F/Form 4 必需 |
183
193
  | `TAVILY_API_KEY` | Tavily 搜索 |
184
194
  | `BRAVE_API_KEY` | Brave 搜索 |
185
195
  | `SERPAPI_KEY` | SerpAPI |
@@ -269,7 +279,16 @@ Agent 会自动调用行情 → 技术面 → 基本面 → 资金面 → 消息
269
279
 
270
280
  | 工具 | 说明 |
271
281
  |------|------|
272
- | `get_kline` | K 线数据(OHLCV),支持日/周/月线 |
282
+ | `get_announcements` | A 股巨潮公告查询:类别/日期范围/标题/原文 PDF 链接 |
283
+ | `get_us_holdings` | SEC 机构组合 / 发行人 CIK 反查机构:精确 CUSIP 映射、季度数据与修订处理(需 SEC_USER_AGENT) |
284
+ | `get_insider_trades` | SEC 股票 ticker/发行人 CIK 的 Form 4 内部人交易、代码和脚注 |
285
+ | `get_valuation_history` | A/HK PE-TTM/PB 历史、正值分位与估值 Band,实际采样窗口 |
286
+ | `get_index_valuation` | 中国指数 PE/PB 历史水位;中证官方多年滚动 PE;可选理杏仁补充 PB |
287
+ | `get_earnings_calendar` | A 股报告期披露与业绩预告;HK 已公告业绩审批董事会排期/供应商备选日期 |
288
+ | `get_shareholder_structure` | A 股股东户数/十大流通股东变化/报告期北向名义持股;HK 南向持股 |
289
+ | `get_etf_details` | A 股 ETF 净值折溢价、规模变动、披露持仓、可选基准成分与跟踪误差 |
290
+ | `get_dividends` | A/HK 历史分红/除息日历/已实现 TTM 股息与连续年数;A/HK 报告期/年度排行 |
291
+ | `get_kline` | K 线数据(OHLCV),支持日/周/月线;A 股股票/ETF 前复权,每条记录 `adjusted=qfq`,指数 `adjusted=none` |
273
292
  | `get_quote` | 实时行情快照(非交易时段返回最近交易日收盘价并以 as_of/stale 标注;ETF 的 premium_discount_rate 为正=溢价、负=折价) |
274
293
  | `get_capital_flow` | 资金流向(仅 A 股) |
275
294
  | `get_news` | 个股相关新闻 |
@@ -346,6 +365,14 @@ Agent 会自动调用行情 → 技术面 → 基本面 → 资金面 → 消息
346
365
  | `render_stock_report` | 将结构化个股报告渲染为 Markdown |
347
366
  | `render_market_report` | 将结构化市场复盘渲染为 Markdown(save=true 时归档到本地 JSONL) |
348
367
 
368
+ 批量自选股分析和摘要的 `success` 表示至少获取了有效行情价格、K 线收盘价或技术评分;全部关键数据失败时计入 `failed`,部分结果仍保留。采集脚本复用返回的 K 线计算技术指标,并按股票所属市场查询大盘状态;日/韩/台市场状态暂不可用,非 A 股板块榜单也暂不可用,均会明确返回错误。
369
+
370
+ 信号记录支持同一存储文件的多进程读写;评估期间新增的信号会保留。价格必须为正的有限数值,持有期限为正整数,日期格式为 YYYY-MM-DD。存储文件含损坏 JSON 行或无效信号时,记录、评估和汇总返回错误,原文件保持原样。
371
+
372
+ 信号评估仅在历史 K 线覆盖记录日时结算,缺少历史窗口则返回 `skipped_no_data` 并保持未结算。风险筛查返回 `data_complete` 和 `warnings`;数据不足时评级可为 `unknown`,`risk_score`、`veto_buy` 可为 null。告警的 `evaluated` 条目含 `error` 时表示无法检查,不能将未触发理解为已通过检查。
373
+
374
+ 选股的 `filters_applied` 只列实际执行的条件,显式条件缺少数据时报错。回测的 `period` 是实际数据期间,`requested_period` 保留请求期间,`warnings` 提示覆盖差异;买入预算包含佣金,年化收益和回撤按实际数据及初始资金计算。
375
+
349
376
  ## 策略回测 DSL
350
377
 
351
378
  策略以 YAML 格式定义,支持参数化和条件组合:
@@ -414,22 +441,57 @@ position:
414
441
 
415
442
  ## 市场路由规则
416
443
 
417
- | 代码格式 | 示例 | 市场 | 数据源 Failover 链 |
444
+ | 代码格式 | 示例 | 市场 | 行情报价 Failover 链(K 线差异见下方) |
418
445
  |----------|------|------|---------------------|
419
446
  | 6 位纯数字 | `600519`, `000001`, `300750` | A 股 | akshare → tushare → efinance → 腾讯 → 新浪 → pytdx → baostock |
420
447
  | 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) |
422
- | `.HK` 结尾 | `00700.HK`, `09988.HK` | 港股 | yfinance → finnhub → longbridge |
448
+ | 带交易所前缀(`sh`/`sz`/`bj` + 6 位数字) | `sh000001`(上证指数), `sz399006`(创业板指) | A 股(显式指定,含指数) | 腾讯 → 新浪 |
449
+ | `.HK` 结尾 | `00700.HK`, `09988.HK` | 港股 | yfinance → 腾讯 → finnhub → longbridge |
423
450
  | 英文字母 | `AAPL`, `GOOGL`, `TSLA` | 美股 | yfinance → finnhub → longbridge → alphavantage |
424
451
  | `.T` 结尾 | `7203.T` | 日股 | yfinance |
425
- | `.KS` / `.KQ` 结尾 | `005930.KS`, `035720.KQ` | 韩股 | yfinance |
452
+ | `.KS` / `.KQ` 结尾 | `005930.KS`, `036020.KQ` | 韩股 | yfinance |
426
453
  | `.TW` / `.TWO` 结尾 | `2330.TW`, `6510.TWO` | 台股 | yfinance |
427
454
 
428
455
  > 各数据源按优先级自动尝试,前一个失败后自动切换到下一个。未配置相关 env var 的数据源会被跳过。
456
+ > 港股腾讯备用源使用 `r_hk` 通道(`hk` 通道延迟约 15 分钟),仅用于实时报价,K 线仍走 yfinance → finnhub → longbridge。支持 `00700.HK` / `0700.HK` / `700.hk`,成交量单位为股,成交额及市值为港元;PB、换手率、量比在此备用源中返回 null,不套用 A 股字段。
429
457
  > 裸 6 位代码一律按**个股**处理(`000001` 是平安银行);指数需带交易所前缀(`sh000001` = 上证指数),显式前缀代码直接走腾讯/新浪(东财源只认裸代码)。
458
+ > **A 股 K 线口径**:股票/ETF 仅接受前复权数据,链路为 akshare → tushare(仅股票)→ efinance → 腾讯(仅 qfq 数据)→ baostock;带前缀的股票/ETF 先去前缀再走同一链路。新浪和 pytdx 的未复权 K 线不参与股票/ETF 容灾。显式指数 `sh000xxx` / `sz399xxx` 保留原始点位,走腾讯 → 新浪 → baostock。上述路由表的完整链路仍适用于实时行情。
459
+ > 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
460
  > **粘性优选**:A 股链路(K 线 / 行情 / 市场快照 / 板块成分)会记住最近一次成功的数据源(缓存在系统临时目录,24h 有效),下次调用优先从它开始;若它已失效则自动顺延并更新记录。港美股链路不做粘性——一次 yfinance 瞬时失败不应让后续全天的 quote 降质。
431
461
  > 日/韩/台股仅 yfinance 一个数据源(免费数据延迟约 15 分钟);港股 / 美股 / 日股 / 韩股 / 台股的 ETF 与其所在市场股票走相同链路。
432
462
 
463
+
464
+ ## 低频价投与增量数据
465
+
466
+ ```bash
467
+ python tools/value_data.py valuation_history 600519 --years 5
468
+ python tools/stock_data.py financials 600519 --annual --periods 10
469
+ python tools/value_data.py earnings_calendar --report-date 2026-09-30 --symbol 600519
470
+ python tools/value_data.py shareholder_structure 600519 --report-date 2026-06-30
471
+ python tools/value_data.py shareholder_structure 0700.HK
472
+ python tools/value_data.py index_valuation 000300 --years 5
473
+ python tools/value_data.py etf_details 510300 --benchmark sh000300 --days 60
474
+ python tools/value_data.py etf_details 510300 --include-full-holdings
475
+ python tools/stock_data.py margin_trading 600519 --days 10 --include-ratio
476
+ python tools/value_data.py dividends --symbol 600519
477
+ python tools/value_data.py dividends --symbol 0700.HK --mode calendar
478
+ python tools/value_data.py dividends --mode ranking --report-date 2025-12-31
479
+ python tools/value_data.py dividends --mode ranking --market HK --report-date 2025-12-31
480
+ python tools/value_data.py earnings_calendar --symbol 0700.HK
481
+ ```
482
+
483
+ 财报、基本信息及估值/股东/ETF/分红等慢变数据缓存到 `~/.stock-analysis/cache`,TTL 一天;板块成分/映射一周。行情报价不缓存。缓存文件原子替换,过期/损坏重拉,错误和显式部分失败不缓存;不以过期数据伪装最新数据。原有临时目录的粘性路由和反向成分缓存保留。
484
+
485
+ 估值使用可得数据的正值样本分位(`<=当前值`),返回 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 按源实际可得年数返回,不补造缺失比率。
486
+
487
+ 股东数据保留报告期、公告日或港交所披露日: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`。日期转为香港日期,公告表也不承诺覆盖所有港股。
488
+
489
+ ETF 使用披露资产规模历史(元)与披露持仓,保留持仓原始证券代码,不冒充实时完整申赎篮子;新增 `basket` 返回沪深交易所发布的完整当日 PCF(跨境代码原样保留),包含申赎单位、每篮子证券数量、现金替代规则与比例;校验基金代码、实际日期和全部组件数量,失败只提示不可用,不冒充完整。PCF 是申赎对价,不是实际持仓,证券数量也不是净值权重。`include_full_holdings=true` 时另取最近可得半年度/年度披露股票表,显式指定年份/月并请求较高行数上限,包含股票数量(股)、市值(人民币元)和实际报告期;返回全部收到的表格行,但不声称覆盖债券/现金等全资产或实时持仓,也不以 PCF 数量验证实际持仓。默认不取数百行明细。提供 `benchmark` 可另查基准指数成分。净值折溢价仅在行情/净值日期相同才计算,IOPV 折溢价另列。跟踪误差使用相同连续交易日区间的基金日净值增长与基准收盘收益差,取样本标准差乘 `sqrt(252)`,不填补缺失日期、不猜测基准。两融占比只匹配同一天的人民币元成交额,缺失则 null。
490
+
491
+ 股息历史将预案与已实施分红分开,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填充。
492
+
493
+ 数据源参考:[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)。
494
+
433
495
  ## 独立 CLI 使用
434
496
 
435
497
  Python 工具可脱离 Agent 独立使用,所有输出为 JSON:
@@ -487,26 +549,28 @@ GitHub Actions 的 `e2e-host` 使用 Pi、Hermes、OpenClaw、dsh 的真实运
487
549
  ```
488
550
  stock-analysis/
489
551
  ├── pi/ # Pi Agent Extension
490
- │ └── index.ts # 注册 51 个工具 + 20 个 skill
552
+ │ └── index.ts # 注册 60 个工具 + 20 个 skill
491
553
  ├── hermes/ # Hermes Agent Plugin
492
554
  │ ├── plugin.yaml # 插件清单
493
555
  │ ├── __init__.py # register(ctx) 入口
494
556
  │ ├── schemas.py # 工具 JSON Schema 定义
495
- │ └── tools.py # 51 个 handler → subprocess 调 CLI
557
+ │ └── tools.py # 60 个 handler → subprocess 调 CLI
496
558
  ├── openclaw/ # OpenClaw Plugin
497
559
  │ ├── openclaw.plugin.json # manifest(contracts.tools)
498
560
  │ ├── package.json # 含 openclaw 块(pluginApi/SDK 版本)
499
- │ └── index.ts # definePluginEntry + registerTool ×51
561
+ │ └── index.ts # definePluginEntry + registerTool ×60
500
562
  ├── dsh/ # DeepSeek Harness (dsh) Plugin
501
563
  │ ├── cordis.patch.yml # bundle patch(insert 插件入口)
502
564
  │ ├── package.json # 含 dsh.bundle 块(bundle manifest)
503
- │ └── index.ts # cordis apply(ctx) + defineTool ×51
565
+ │ └── index.ts # cordis apply(ctx) + defineTool ×60
504
566
  │
505
- ├── tools/ # 共享 Python CLI 工具(23 个脚本)
567
+ ├── tools/ # 共享 Python CLI 工具
506
568
  │ ├── stock_data.py # 行情 / 资金流 / 新闻 / 财务 / 短线情绪
507
569
  │ ├── signal_tracker.py # AI 买卖建议回测闭环(本地 JSONL 存储)
508
570
  │ ├── technical.py # 技术指标分析
509
571
  │ ├── pattern.py # K 线形态识别
572
+ │ ├── value_data.py # 估值/财报日历/股东/ETF/股息
573
+ │ ├── _cache.py # 用户目录 TTL 缓存
510
574
  │ ├── screener.py # 全市场多因子筛选(含市场情绪调节,--l2 量化增强)
511
575
  │ ├── backtest.py # 策略回测引擎
512
576
  │ ├── volume_analysis.py # 量价分析
@@ -600,3 +664,38 @@ CLI 使用:`python tools/screener.py screen --config my_filter.yaml --top 30`
600
664
  ## License
601
665
 
602
666
  MIT
667
+
668
+ ### 公告与港美股研究数据(#49–#51)
669
+
670
+ ```bash
671
+ python3 tools/value_data.py announcements 600519 --category forecast --start-date 2026-01-01 --end-date 2026-10-13 --top 50
672
+ python3 tools/stock_data.py financials 0700.HK --annual --periods 10
673
+ python3 tools/value_data.py valuation_history 0700.HK --years 10
674
+ # SEC_USER_AGENT 必须配置为应用名称 + 你的真实联系邮箱
675
+ python3 tools/sec_edgar.py holdings 0001067983
676
+ python3 tools/sec_edgar.py insider_trades AAPL --days 90 --top 10
677
+ ```
678
+
679
+ 公告类别为 `all/forecast/express/annual/interim/quarterly/reduction/issuance/inquiry/dividend`。默认最近 90 天,最多 500 条;通过巨潮官方股票目录取得 orgId,沪深京统一使用官方 `szse` 查询栏目。业绩快报和问询使用标题关键词查询。第一版返回 PDF 原文链接,不引入 PDF 解析依赖;`total/truncated` 表示供应商匹配数量及截断,查询无结果与请求失败分开。
680
+
681
+ 港股使用既有 `LIXINGER_TOKEN`,需具备港股接口权限。新增来源覆盖理杏仁非金融公司财务和每日估值,最多十年;金融公司或无权限时回退现有 Yahoo/东财财务和百度估值,返回实际期数和不足提示。财务按 `annual_report` 识别年报,保留财年末、披露日和币种,金额为报告币种,历史比率为百分数;顶层 `roe/profit_margin` 延续 Yahoo 小数比例。理杏仁财报用于增强历史,同时按整组保留可用的 Yahoo 顶层快照,`currency` 是 Yahoo 的财报币种,`market_cap_currency` 是市值币种,`snapshot_source` 标明来源,缺失值不混入其他报告期或币种的历史数字;历史币种和报告日期在 `periods` 每行保留,Yahoo 未提供明确报告日期时顶层 `report_date=null`。快照失败时 `snapshot_available=false`,财报与历史仍返回。会计口径不强行转换为 A 股,估值分位沿用正值样本算法,不拼接不同来源。
682
+
683
+ SEC 配置 `SEC_USER_AGENT`,包含应用名称与真实联系邮箱,仅通过环境变量提供。单进程最多每秒 2 次请求(多个并行进程需控制账户/IP 总量不超过 SEC 的每秒 10 次),并缓存 ticker/CIK、申报元数据和 XML 解析结果。13F 返回机构最近季度的原始申报,不是实时完整组合;通常在季度后 45 天内披露(节假日顺延),实际数据年龄以季度末为准,2023-01-03 起金额单位为美元,更早申报为千美元。修订文件另列原文链接,避免错误合并补充与重述;发行人 CIK 反查现已通过 `mode=issuer` 支持:从结构化 Schedule 13D/G 校验发行人 CIK、提取 CUSIP,再扫描官方最新已发布 13F 批量窗口。`auto` 默认有当前或已检索历史 13F 时查机构,否则查发行人;Berkshire 等兼具两种身份时显式选择 `issuer`。修订按 `RESTATEMENT` 替换与 `NEW HOLDINGS` 补充重建;无法判断的修订或缺少基础版时总量为 null,并给出 `unresolved_manager_count`。
684
+
685
+ Form 4 的 `days` 是申报日期窗口,`top=1..20` 限制文件数,返回全部已解析交易。保留多人联报、衍生品、交易代码、脚注、直接/间接持有和修订信息;仅 P/S 标为买/卖,其余行为不推断方向,价格未披露为 null。读取 `truncated/warnings`,原件与修订不要重复计数。风险组合工具 `screen_risk` 仍为 A 股专用。
686
+
687
+ 接口依据:[巨潮公告查询](https://www.cninfo.com.cn/new/commonUrl/pageOfSearch?url=disclosure/list/search)、[理杏仁港股财报](https://www.lixinger.com/api/open-api/html-doc/hk/company/fs/non_financial)、[理杏仁港股估值](https://www.lixinger.com/api/open-api/html-doc/hk/company/fundamental/non_financial)、[SEC API](https://www.sec.gov/search-filings/edgar-application-programming-interfaces)。
688
+
689
+ 股票 CIK 反查示例:
690
+
691
+ ```bash
692
+ python3 tools/sec_edgar.py holdings 0000320193 --mode issuer
693
+ # 原机构查询保持可用
694
+ python3 tools/sec_edgar.py holdings 0001067983 --mode manager
695
+ ```
696
+
697
+ 首次下载当前 SEC 包约 100 MB;ZIP 按周缓存,CUSIP 反查结果按天缓存,流式扫描不解压整个持仓表、不增加数据库依赖。返回 `report_date`(持仓日期)、`filing_window_end`(公开申报窗口截止)、`cusip_evidence`(原文映射依据),不把文件披露窗口当作持仓日期。`mapping_complete=false` 表示最近十份结构化 13D/G 可能未覆盖所有证券类别或 CUSIP 变更;缺映射直接报错,不做名称模糊匹配。`complete_for_mapped_cusips` 仅在该报告期没有未解决申报链时为 true,不代表实时全部股东。期权与本金持仓在 `positions` 保留,`shares` 合计只计无 PUT/CALL 的 SH 股票。不能将跨机构合计当作已去重的全市场持股。
698
+
699
+ 来源格式与实測依据见 [#51 数据研究](docs/research/issue-51-reverse-holdings.md)。
700
+
701
+ Hermes 的 `get_us_holdings` 子进程预算为 300 秒,允许首次下载批量包;其他 CLI 仍为 120 秒。机构查询优先寻找最新已知报告期的原始 13F:较新修订对应的原始版未找到时明确报错,历史分片仍未完全检索时返回 `history_truncated` 与警告。发行人 CUSIP 查询会跳过不可访问/无效 XML,继续核对后续原文;没有任何可验证映射时才报缺失。
@@ -32,7 +32,7 @@ A 股 / 港股 / 美股 / 日股 / 韩股 / 台股综合分析、多因子选股
32
32
 
33
33
  ## 功能概览
34
34
 
35
- - **51 个工具** — 行情数据、技术分析、K 线形态、资金流向、财务指标、新闻舆情、风险筛查、市场状态等
35
+ - **60 个工具** — 行情数据、技术分析、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 启动后自动加载并注册 60 个 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 组合,注册 60 个 tool + 20 个 skill。postinstall 自动建 `.venv`(pnpm 需在 profile 的 `pnpm-workspace.yaml` 里给本包配 `allowBuilds`,否则回退系统 `python3`)。
108
108
 
109
109
  详见 [`dsh/README.md`](dsh/README.md)。
110
110
 
@@ -127,7 +127,7 @@ pip install -r tools/requirements.txt
127
127
  | pytdx | A 股 TDX 行情(免费兜底源) |
128
128
  | longport | 港股 / 美股 Longbridge SDK |
129
129
 
130
- > A 股行情另有**腾讯(qt.gtimg.cn)/ 新浪(hq.sinajs.cn)**两个免鉴权兜底源,不依赖任何 Python 包(直接 HTTP 调用),用于东财域名不可达的网络环境(境外主机、企业出网限制等)。
130
+ > A 股行情另有**腾讯(qt.gtimg.cn)/ 新浪(hq.sinajs.cn)**两个免鉴权兜底源,直接 HTTP 调用,用于东财域名不可达的网络环境(境外主机、企业出网限制等)。港股实时行情也使用腾讯作为 yfinance 之后的免 key 备用源。
131
131
 
132
132
  ### 环境变量
133
133
 
@@ -147,6 +147,8 @@ pip install -r tools/requirements.txt
147
147
 
148
148
  | 环境变量 | 用途 |
149
149
  |---------|------|
150
+ | `LIXINGER_TOKEN` | 理杏仁可选数据源:指数 PB 与港股非金融公司财务/每日估值(需对应权限) |
151
+ | `SEC_USER_AGENT` | SEC EDGAR 身份声明:应用名称与真实联系邮箱,13F/Form 4 必需 |
150
152
  | `TAVILY_API_KEY` | Tavily 搜索 |
151
153
  | `BRAVE_API_KEY` | Brave 搜索 |
152
154
  | `SERPAPI_KEY` | SerpAPI |
@@ -236,7 +238,16 @@ Agent 会自动调用行情 → 技术面 → 基本面 → 资金面 → 消息
236
238
 
237
239
  | 工具 | 说明 |
238
240
  |------|------|
239
- | `get_kline` | K 线数据(OHLCV),支持日/周/月线 |
241
+ | `get_announcements` | A 股巨潮公告查询:类别/日期范围/标题/原文 PDF 链接 |
242
+ | `get_us_holdings` | SEC 机构组合 / 发行人 CIK 反查机构:精确 CUSIP 映射、季度数据与修订处理(需 SEC_USER_AGENT) |
243
+ | `get_insider_trades` | SEC 股票 ticker/发行人 CIK 的 Form 4 内部人交易、代码和脚注 |
244
+ | `get_valuation_history` | A/HK PE-TTM/PB 历史、正值分位与估值 Band,实际采样窗口 |
245
+ | `get_index_valuation` | 中国指数 PE/PB 历史水位;中证官方多年滚动 PE;可选理杏仁补充 PB |
246
+ | `get_earnings_calendar` | A 股报告期披露与业绩预告;HK 已公告业绩审批董事会排期/供应商备选日期 |
247
+ | `get_shareholder_structure` | A 股股东户数/十大流通股东变化/报告期北向名义持股;HK 南向持股 |
248
+ | `get_etf_details` | A 股 ETF 净值折溢价、规模变动、披露持仓、可选基准成分与跟踪误差 |
249
+ | `get_dividends` | A/HK 历史分红/除息日历/已实现 TTM 股息与连续年数;A/HK 报告期/年度排行 |
250
+ | `get_kline` | K 线数据(OHLCV),支持日/周/月线;A 股股票/ETF 前复权,每条记录 `adjusted=qfq`,指数 `adjusted=none` |
240
251
  | `get_quote` | 实时行情快照(非交易时段返回最近交易日收盘价并以 as_of/stale 标注;ETF 的 premium_discount_rate 为正=溢价、负=折价) |
241
252
  | `get_capital_flow` | 资金流向(仅 A 股) |
242
253
  | `get_news` | 个股相关新闻 |
@@ -313,6 +324,14 @@ Agent 会自动调用行情 → 技术面 → 基本面 → 资金面 → 消息
313
324
  | `render_stock_report` | 将结构化个股报告渲染为 Markdown |
314
325
  | `render_market_report` | 将结构化市场复盘渲染为 Markdown(save=true 时归档到本地 JSONL) |
315
326
 
327
+ 批量自选股分析和摘要的 `success` 表示至少获取了有效行情价格、K 线收盘价或技术评分;全部关键数据失败时计入 `failed`,部分结果仍保留。采集脚本复用返回的 K 线计算技术指标,并按股票所属市场查询大盘状态;日/韩/台市场状态暂不可用,非 A 股板块榜单也暂不可用,均会明确返回错误。
328
+
329
+ 信号记录支持同一存储文件的多进程读写;评估期间新增的信号会保留。价格必须为正的有限数值,持有期限为正整数,日期格式为 YYYY-MM-DD。存储文件含损坏 JSON 行或无效信号时,记录、评估和汇总返回错误,原文件保持原样。
330
+
331
+ 信号评估仅在历史 K 线覆盖记录日时结算,缺少历史窗口则返回 `skipped_no_data` 并保持未结算。风险筛查返回 `data_complete` 和 `warnings`;数据不足时评级可为 `unknown`,`risk_score`、`veto_buy` 可为 null。告警的 `evaluated` 条目含 `error` 时表示无法检查,不能将未触发理解为已通过检查。
332
+
333
+ 选股的 `filters_applied` 只列实际执行的条件,显式条件缺少数据时报错。回测的 `period` 是实际数据期间,`requested_period` 保留请求期间,`warnings` 提示覆盖差异;买入预算包含佣金,年化收益和回撤按实际数据及初始资金计算。
334
+
316
335
  ## 策略回测 DSL
317
336
 
318
337
  策略以 YAML 格式定义,支持参数化和条件组合:
@@ -381,22 +400,57 @@ position:
381
400
 
382
401
  ## 市场路由规则
383
402
 
384
- | 代码格式 | 示例 | 市场 | 数据源 Failover 链 |
403
+ | 代码格式 | 示例 | 市场 | 行情报价 Failover 链(K 线差异见下方) |
385
404
  |----------|------|------|---------------------|
386
405
  | 6 位纯数字 | `600519`, `000001`, `300750` | A 股 | akshare → tushare → efinance → 腾讯 → 新浪 → pytdx → baostock |
387
406
  | 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) |
389
- | `.HK` 结尾 | `00700.HK`, `09988.HK` | 港股 | yfinance → finnhub → longbridge |
407
+ | 带交易所前缀(`sh`/`sz`/`bj` + 6 位数字) | `sh000001`(上证指数), `sz399006`(创业板指) | A 股(显式指定,含指数) | 腾讯 → 新浪 |
408
+ | `.HK` 结尾 | `00700.HK`, `09988.HK` | 港股 | yfinance → 腾讯 → finnhub → longbridge |
390
409
  | 英文字母 | `AAPL`, `GOOGL`, `TSLA` | 美股 | yfinance → finnhub → longbridge → alphavantage |
391
410
  | `.T` 结尾 | `7203.T` | 日股 | yfinance |
392
- | `.KS` / `.KQ` 结尾 | `005930.KS`, `035720.KQ` | 韩股 | yfinance |
411
+ | `.KS` / `.KQ` 结尾 | `005930.KS`, `036020.KQ` | 韩股 | yfinance |
393
412
  | `.TW` / `.TWO` 结尾 | `2330.TW`, `6510.TWO` | 台股 | yfinance |
394
413
 
395
414
  > 各数据源按优先级自动尝试,前一个失败后自动切换到下一个。未配置相关 env var 的数据源会被跳过。
415
+ > 港股腾讯备用源使用 `r_hk` 通道(`hk` 通道延迟约 15 分钟),仅用于实时报价,K 线仍走 yfinance → finnhub → longbridge。支持 `00700.HK` / `0700.HK` / `700.hk`,成交量单位为股,成交额及市值为港元;PB、换手率、量比在此备用源中返回 null,不套用 A 股字段。
396
416
  > 裸 6 位代码一律按**个股**处理(`000001` 是平安银行);指数需带交易所前缀(`sh000001` = 上证指数),显式前缀代码直接走腾讯/新浪(东财源只认裸代码)。
417
+ > **A 股 K 线口径**:股票/ETF 仅接受前复权数据,链路为 akshare → tushare(仅股票)→ efinance → 腾讯(仅 qfq 数据)→ baostock;带前缀的股票/ETF 先去前缀再走同一链路。新浪和 pytdx 的未复权 K 线不参与股票/ETF 容灾。显式指数 `sh000xxx` / `sz399xxx` 保留原始点位,走腾讯 → 新浪 → baostock。上述路由表的完整链路仍适用于实时行情。
418
+ > 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
419
  > **粘性优选**:A 股链路(K 线 / 行情 / 市场快照 / 板块成分)会记住最近一次成功的数据源(缓存在系统临时目录,24h 有效),下次调用优先从它开始;若它已失效则自动顺延并更新记录。港美股链路不做粘性——一次 yfinance 瞬时失败不应让后续全天的 quote 降质。
398
420
  > 日/韩/台股仅 yfinance 一个数据源(免费数据延迟约 15 分钟);港股 / 美股 / 日股 / 韩股 / 台股的 ETF 与其所在市场股票走相同链路。
399
421
 
422
+
423
+ ## 低频价投与增量数据
424
+
425
+ ```bash
426
+ python tools/value_data.py valuation_history 600519 --years 5
427
+ python tools/stock_data.py financials 600519 --annual --periods 10
428
+ python tools/value_data.py earnings_calendar --report-date 2026-09-30 --symbol 600519
429
+ python tools/value_data.py shareholder_structure 600519 --report-date 2026-06-30
430
+ python tools/value_data.py shareholder_structure 0700.HK
431
+ python tools/value_data.py index_valuation 000300 --years 5
432
+ python tools/value_data.py etf_details 510300 --benchmark sh000300 --days 60
433
+ python tools/value_data.py etf_details 510300 --include-full-holdings
434
+ python tools/stock_data.py margin_trading 600519 --days 10 --include-ratio
435
+ python tools/value_data.py dividends --symbol 600519
436
+ python tools/value_data.py dividends --symbol 0700.HK --mode calendar
437
+ python tools/value_data.py dividends --mode ranking --report-date 2025-12-31
438
+ python tools/value_data.py dividends --mode ranking --market HK --report-date 2025-12-31
439
+ python tools/value_data.py earnings_calendar --symbol 0700.HK
440
+ ```
441
+
442
+ 财报、基本信息及估值/股东/ETF/分红等慢变数据缓存到 `~/.stock-analysis/cache`,TTL 一天;板块成分/映射一周。行情报价不缓存。缓存文件原子替换,过期/损坏重拉,错误和显式部分失败不缓存;不以过期数据伪装最新数据。原有临时目录的粘性路由和反向成分缓存保留。
443
+
444
+ 估值使用可得数据的正值样本分位(`<=当前值`),返回 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 按源实际可得年数返回,不补造缺失比率。
445
+
446
+ 股东数据保留报告期、公告日或港交所披露日: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`。日期转为香港日期,公告表也不承诺覆盖所有港股。
447
+
448
+ ETF 使用披露资产规模历史(元)与披露持仓,保留持仓原始证券代码,不冒充实时完整申赎篮子;新增 `basket` 返回沪深交易所发布的完整当日 PCF(跨境代码原样保留),包含申赎单位、每篮子证券数量、现金替代规则与比例;校验基金代码、实际日期和全部组件数量,失败只提示不可用,不冒充完整。PCF 是申赎对价,不是实际持仓,证券数量也不是净值权重。`include_full_holdings=true` 时另取最近可得半年度/年度披露股票表,显式指定年份/月并请求较高行数上限,包含股票数量(股)、市值(人民币元)和实际报告期;返回全部收到的表格行,但不声称覆盖债券/现金等全资产或实时持仓,也不以 PCF 数量验证实际持仓。默认不取数百行明细。提供 `benchmark` 可另查基准指数成分。净值折溢价仅在行情/净值日期相同才计算,IOPV 折溢价另列。跟踪误差使用相同连续交易日区间的基金日净值增长与基准收盘收益差,取样本标准差乘 `sqrt(252)`,不填补缺失日期、不猜测基准。两融占比只匹配同一天的人民币元成交额,缺失则 null。
449
+
450
+ 股息历史将预案与已实施分红分开,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填充。
451
+
452
+ 数据源参考:[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)。
453
+
400
454
  ## 独立 CLI 使用
401
455
 
402
456
  Python 工具可脱离 Agent 独立使用,所有输出为 JSON:
@@ -454,26 +508,28 @@ GitHub Actions 的 `e2e-host` 使用 Pi、Hermes、OpenClaw、dsh 的真实运
454
508
  ```
455
509
  stock-analysis/
456
510
  ├── pi/ # Pi Agent Extension
457
- │ └── index.ts # 注册 51 个工具 + 20 个 skill
511
+ │ └── index.ts # 注册 60 个工具 + 20 个 skill
458
512
  ├── hermes/ # Hermes Agent Plugin
459
513
  │ ├── plugin.yaml # 插件清单
460
514
  │ ├── __init__.py # register(ctx) 入口
461
515
  │ ├── schemas.py # 工具 JSON Schema 定义
462
- │ └── tools.py # 51 个 handler → subprocess 调 CLI
516
+ │ └── tools.py # 60 个 handler → subprocess 调 CLI
463
517
  ├── openclaw/ # OpenClaw Plugin
464
518
  │ ├── openclaw.plugin.json # manifest(contracts.tools)
465
519
  │ ├── package.json # 含 openclaw 块(pluginApi/SDK 版本)
466
- │ └── index.ts # definePluginEntry + registerTool ×51
520
+ │ └── index.ts # definePluginEntry + registerTool ×60
467
521
  ├── dsh/ # DeepSeek Harness (dsh) Plugin
468
522
  │ ├── cordis.patch.yml # bundle patch(insert 插件入口)
469
523
  │ ├── package.json # 含 dsh.bundle 块(bundle manifest)
470
- │ └── index.ts # cordis apply(ctx) + defineTool ×51
524
+ │ └── index.ts # cordis apply(ctx) + defineTool ×60
471
525
  │
472
- ├── tools/ # 共享 Python CLI 工具(23 个脚本)
526
+ ├── tools/ # 共享 Python CLI 工具
473
527
  │ ├── stock_data.py # 行情 / 资金流 / 新闻 / 财务 / 短线情绪
474
528
  │ ├── signal_tracker.py # AI 买卖建议回测闭环(本地 JSONL 存储)
475
529
  │ ├── technical.py # 技术指标分析
476
530
  │ ├── pattern.py # K 线形态识别
531
+ │ ├── value_data.py # 估值/财报日历/股东/ETF/股息
532
+ │ ├── _cache.py # 用户目录 TTL 缓存
477
533
  │ ├── screener.py # 全市场多因子筛选(含市场情绪调节,--l2 量化增强)
478
534
  │ ├── backtest.py # 策略回测引擎
479
535
  │ ├── volume_analysis.py # 量价分析
@@ -567,3 +623,38 @@ CLI 使用:`python tools/screener.py screen --config my_filter.yaml --top 30`
567
623
  ## License
568
624
 
569
625
  MIT
626
+
627
+ ### 公告与港美股研究数据(#49–#51)
628
+
629
+ ```bash
630
+ python3 tools/value_data.py announcements 600519 --category forecast --start-date 2026-01-01 --end-date 2026-10-13 --top 50
631
+ python3 tools/stock_data.py financials 0700.HK --annual --periods 10
632
+ python3 tools/value_data.py valuation_history 0700.HK --years 10
633
+ # SEC_USER_AGENT 必须配置为应用名称 + 你的真实联系邮箱
634
+ python3 tools/sec_edgar.py holdings 0001067983
635
+ python3 tools/sec_edgar.py insider_trades AAPL --days 90 --top 10
636
+ ```
637
+
638
+ 公告类别为 `all/forecast/express/annual/interim/quarterly/reduction/issuance/inquiry/dividend`。默认最近 90 天,最多 500 条;通过巨潮官方股票目录取得 orgId,沪深京统一使用官方 `szse` 查询栏目。业绩快报和问询使用标题关键词查询。第一版返回 PDF 原文链接,不引入 PDF 解析依赖;`total/truncated` 表示供应商匹配数量及截断,查询无结果与请求失败分开。
639
+
640
+ 港股使用既有 `LIXINGER_TOKEN`,需具备港股接口权限。新增来源覆盖理杏仁非金融公司财务和每日估值,最多十年;金融公司或无权限时回退现有 Yahoo/东财财务和百度估值,返回实际期数和不足提示。财务按 `annual_report` 识别年报,保留财年末、披露日和币种,金额为报告币种,历史比率为百分数;顶层 `roe/profit_margin` 延续 Yahoo 小数比例。理杏仁财报用于增强历史,同时按整组保留可用的 Yahoo 顶层快照,`currency` 是 Yahoo 的财报币种,`market_cap_currency` 是市值币种,`snapshot_source` 标明来源,缺失值不混入其他报告期或币种的历史数字;历史币种和报告日期在 `periods` 每行保留,Yahoo 未提供明确报告日期时顶层 `report_date=null`。快照失败时 `snapshot_available=false`,财报与历史仍返回。会计口径不强行转换为 A 股,估值分位沿用正值样本算法,不拼接不同来源。
641
+
642
+ SEC 配置 `SEC_USER_AGENT`,包含应用名称与真实联系邮箱,仅通过环境变量提供。单进程最多每秒 2 次请求(多个并行进程需控制账户/IP 总量不超过 SEC 的每秒 10 次),并缓存 ticker/CIK、申报元数据和 XML 解析结果。13F 返回机构最近季度的原始申报,不是实时完整组合;通常在季度后 45 天内披露(节假日顺延),实际数据年龄以季度末为准,2023-01-03 起金额单位为美元,更早申报为千美元。修订文件另列原文链接,避免错误合并补充与重述;发行人 CIK 反查现已通过 `mode=issuer` 支持:从结构化 Schedule 13D/G 校验发行人 CIK、提取 CUSIP,再扫描官方最新已发布 13F 批量窗口。`auto` 默认有当前或已检索历史 13F 时查机构,否则查发行人;Berkshire 等兼具两种身份时显式选择 `issuer`。修订按 `RESTATEMENT` 替换与 `NEW HOLDINGS` 补充重建;无法判断的修订或缺少基础版时总量为 null,并给出 `unresolved_manager_count`。
643
+
644
+ Form 4 的 `days` 是申报日期窗口,`top=1..20` 限制文件数,返回全部已解析交易。保留多人联报、衍生品、交易代码、脚注、直接/间接持有和修订信息;仅 P/S 标为买/卖,其余行为不推断方向,价格未披露为 null。读取 `truncated/warnings`,原件与修订不要重复计数。风险组合工具 `screen_risk` 仍为 A 股专用。
645
+
646
+ 接口依据:[巨潮公告查询](https://www.cninfo.com.cn/new/commonUrl/pageOfSearch?url=disclosure/list/search)、[理杏仁港股财报](https://www.lixinger.com/api/open-api/html-doc/hk/company/fs/non_financial)、[理杏仁港股估值](https://www.lixinger.com/api/open-api/html-doc/hk/company/fundamental/non_financial)、[SEC API](https://www.sec.gov/search-filings/edgar-application-programming-interfaces)。
647
+
648
+ 股票 CIK 反查示例:
649
+
650
+ ```bash
651
+ python3 tools/sec_edgar.py holdings 0000320193 --mode issuer
652
+ # 原机构查询保持可用
653
+ python3 tools/sec_edgar.py holdings 0001067983 --mode manager
654
+ ```
655
+
656
+ 首次下载当前 SEC 包约 100 MB;ZIP 按周缓存,CUSIP 反查结果按天缓存,流式扫描不解压整个持仓表、不增加数据库依赖。返回 `report_date`(持仓日期)、`filing_window_end`(公开申报窗口截止)、`cusip_evidence`(原文映射依据),不把文件披露窗口当作持仓日期。`mapping_complete=false` 表示最近十份结构化 13D/G 可能未覆盖所有证券类别或 CUSIP 变更;缺映射直接报错,不做名称模糊匹配。`complete_for_mapped_cusips` 仅在该报告期没有未解决申报链时为 true,不代表实时全部股东。期权与本金持仓在 `positions` 保留,`shares` 合计只计无 PUT/CALL 的 SH 股票。不能将跨机构合计当作已去重的全市场持股。
657
+
658
+ 来源格式与实測依据见 [#51 数据研究](docs/research/issue-51-reverse-holdings.md)。
659
+
660
+ Hermes 的 `get_us_holdings` 子进程预算为 300 秒,允许首次下载批量包;其他 CLI 仍为 120 秒。机构查询优先寻找最新已知报告期的原始 13F:较新修订对应的原始版未找到时明确报错,历史分片仍未完全检索时返回 `history_truncated` 与警告。发行人 CUSIP 查询会跳过不可访问/无效 XML,继续核对后续原文;没有任何可验证映射时才报缺失。