tickflow-assist 0.2.0

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 (246) hide show
  1. package/README.md +151 -0
  2. package/day_future.txt +8797 -0
  3. package/dist/analysis/orchestrators/composite-analysis.orchestrator.d.ts +35 -0
  4. package/dist/analysis/orchestrators/composite-analysis.orchestrator.js +232 -0
  5. package/dist/analysis/parsers/json-block.parser.d.ts +1 -0
  6. package/dist/analysis/parsers/json-block.parser.js +13 -0
  7. package/dist/analysis/parsers/key-levels.parser.d.ts +5 -0
  8. package/dist/analysis/parsers/key-levels.parser.js +61 -0
  9. package/dist/analysis/parsers/post-close-review.parser.d.ts +2 -0
  10. package/dist/analysis/parsers/post-close-review.parser.js +79 -0
  11. package/dist/analysis/parsers/watchlist-profile.parser.d.ts +6 -0
  12. package/dist/analysis/parsers/watchlist-profile.parser.js +93 -0
  13. package/dist/analysis/providers/financial-analysis.provider.d.ts +12 -0
  14. package/dist/analysis/providers/financial-analysis.provider.js +85 -0
  15. package/dist/analysis/providers/market-analysis.provider.d.ts +27 -0
  16. package/dist/analysis/providers/market-analysis.provider.js +187 -0
  17. package/dist/analysis/providers/news-analysis.provider.d.ts +9 -0
  18. package/dist/analysis/providers/news-analysis.provider.js +60 -0
  19. package/dist/analysis/tasks/analysis-step-task.d.ts +11 -0
  20. package/dist/analysis/tasks/analysis-step-task.js +1 -0
  21. package/dist/analysis/tasks/analysis-task.d.ts +13 -0
  22. package/dist/analysis/tasks/analysis-task.js +1 -0
  23. package/dist/analysis/tasks/composite-stock-analysis.task.d.ts +17 -0
  24. package/dist/analysis/tasks/composite-stock-analysis.task.js +47 -0
  25. package/dist/analysis/tasks/financial-fundamental-lite.task.d.ts +10 -0
  26. package/dist/analysis/tasks/financial-fundamental-lite.task.js +21 -0
  27. package/dist/analysis/tasks/financial-fundamental.task.d.ts +12 -0
  28. package/dist/analysis/tasks/financial-fundamental.task.js +64 -0
  29. package/dist/analysis/tasks/kline-technical-signal.task.d.ts +10 -0
  30. package/dist/analysis/tasks/kline-technical-signal.task.js +41 -0
  31. package/dist/analysis/tasks/kline-technical.task.d.ts +32 -0
  32. package/dist/analysis/tasks/kline-technical.task.js +61 -0
  33. package/dist/analysis/tasks/news-catalyst.task.d.ts +11 -0
  34. package/dist/analysis/tasks/news-catalyst.task.js +62 -0
  35. package/dist/analysis/tasks/post-close-review.task.d.ts +12 -0
  36. package/dist/analysis/tasks/post-close-review.task.js +35 -0
  37. package/dist/analysis/types/composite-analysis.d.ts +123 -0
  38. package/dist/analysis/types/composite-analysis.js +1 -0
  39. package/dist/background/daily-update.worker.d.ts +50 -0
  40. package/dist/background/daily-update.worker.js +546 -0
  41. package/dist/background/realtime-monitor.worker.d.ts +8 -0
  42. package/dist/background/realtime-monitor.worker.js +28 -0
  43. package/dist/bootstrap.d.ts +45 -0
  44. package/dist/bootstrap.js +214 -0
  45. package/dist/config/normalize.d.ts +4 -0
  46. package/dist/config/normalize.js +99 -0
  47. package/dist/config/schema.d.ts +23 -0
  48. package/dist/config/schema.js +18 -0
  49. package/dist/config/tickflow-access.d.ts +4 -0
  50. package/dist/config/tickflow-access.js +28 -0
  51. package/dist/constants/market-indexes.d.ts +5 -0
  52. package/dist/constants/market-indexes.js +4 -0
  53. package/dist/dev/run-daily-update-loop.d.ts +1 -0
  54. package/dist/dev/run-daily-update-loop.js +48 -0
  55. package/dist/dev/run-monitor-loop.d.ts +1 -0
  56. package/dist/dev/run-monitor-loop.js +60 -0
  57. package/dist/dev/run-tool.d.ts +1 -0
  58. package/dist/dev/run-tool.js +49 -0
  59. package/dist/dev/tickflow-assist-cli.d.ts +2 -0
  60. package/dist/dev/tickflow-assist-cli.js +525 -0
  61. package/dist/dev/validate-mx-search.d.ts +1 -0
  62. package/dist/dev/validate-mx-search.js +212 -0
  63. package/dist/plugin-commands.d.ts +3 -0
  64. package/dist/plugin-commands.js +229 -0
  65. package/dist/plugin.d.ts +8 -0
  66. package/dist/plugin.js +151 -0
  67. package/dist/prompts/analysis/common-system-prompt.d.ts +1 -0
  68. package/dist/prompts/analysis/common-system-prompt.js +44 -0
  69. package/dist/prompts/analysis/composite-analysis-user-prompt.d.ts +11 -0
  70. package/dist/prompts/analysis/composite-analysis-user-prompt.js +102 -0
  71. package/dist/prompts/analysis/financial-analysis-user-prompt.d.ts +7 -0
  72. package/dist/prompts/analysis/financial-analysis-user-prompt.js +106 -0
  73. package/dist/prompts/analysis/financial-lite-analysis-user-prompt.d.ts +7 -0
  74. package/dist/prompts/analysis/financial-lite-analysis-user-prompt.js +59 -0
  75. package/dist/prompts/analysis/index.d.ts +8 -0
  76. package/dist/prompts/analysis/index.js +8 -0
  77. package/dist/prompts/analysis/kline-analysis-user-prompt.d.ts +13 -0
  78. package/dist/prompts/analysis/kline-analysis-user-prompt.js +215 -0
  79. package/dist/prompts/analysis/news-analysis-user-prompt.d.ts +8 -0
  80. package/dist/prompts/analysis/news-analysis-user-prompt.js +57 -0
  81. package/dist/prompts/analysis/post-close-review-user-prompt.d.ts +3 -0
  82. package/dist/prompts/analysis/post-close-review-user-prompt.js +129 -0
  83. package/dist/prompts/analysis/watchlist-profile-extraction-prompt.d.ts +7 -0
  84. package/dist/prompts/analysis/watchlist-profile-extraction-prompt.js +52 -0
  85. package/dist/prompts/analysis-system-prompt.d.ts +1 -0
  86. package/dist/prompts/analysis-system-prompt.js +1 -0
  87. package/dist/prompts/analysis-user-prompt.d.ts +1 -0
  88. package/dist/prompts/analysis-user-prompt.js +1 -0
  89. package/dist/runtime/daily-update-process.d.ts +3 -0
  90. package/dist/runtime/daily-update-process.js +24 -0
  91. package/dist/runtime/monitor-process.d.ts +3 -0
  92. package/dist/runtime/monitor-process.js +24 -0
  93. package/dist/runtime/plugin-api.d.ts +22 -0
  94. package/dist/runtime/plugin-api.js +2 -0
  95. package/dist/runtime/process-config.d.ts +8 -0
  96. package/dist/runtime/process-config.js +35 -0
  97. package/dist/services/alert-service.d.ts +45 -0
  98. package/dist/services/alert-service.js +198 -0
  99. package/dist/services/analysis-service.d.ts +20 -0
  100. package/dist/services/analysis-service.js +73 -0
  101. package/dist/services/analysis-view-service.d.ts +23 -0
  102. package/dist/services/analysis-view-service.js +343 -0
  103. package/dist/services/financial-lite-service.d.ts +23 -0
  104. package/dist/services/financial-lite-service.js +201 -0
  105. package/dist/services/financial-service.d.ts +20 -0
  106. package/dist/services/financial-service.js +47 -0
  107. package/dist/services/indicator-service.d.ts +9 -0
  108. package/dist/services/indicator-service.js +67 -0
  109. package/dist/services/instrument-service.d.ts +6 -0
  110. package/dist/services/instrument-service.js +21 -0
  111. package/dist/services/key-level-service.d.ts +2 -0
  112. package/dist/services/key-level-service.js +2 -0
  113. package/dist/services/key-levels-backtest-service.d.ts +71 -0
  114. package/dist/services/key-levels-backtest-service.js +427 -0
  115. package/dist/services/kline-service.d.ts +19 -0
  116. package/dist/services/kline-service.js +91 -0
  117. package/dist/services/monitor-service.d.ts +44 -0
  118. package/dist/services/monitor-service.js +598 -0
  119. package/dist/services/mx-search-service.d.ts +22 -0
  120. package/dist/services/mx-search-service.js +286 -0
  121. package/dist/services/post-close-review-service.d.ts +31 -0
  122. package/dist/services/post-close-review-service.js +402 -0
  123. package/dist/services/quote-service.d.ts +7 -0
  124. package/dist/services/quote-service.js +9 -0
  125. package/dist/services/review-memory-service.d.ts +7 -0
  126. package/dist/services/review-memory-service.js +76 -0
  127. package/dist/services/tickflow-client.d.ts +43 -0
  128. package/dist/services/tickflow-client.js +126 -0
  129. package/dist/services/trading-calendar-service.d.ts +20 -0
  130. package/dist/services/trading-calendar-service.js +102 -0
  131. package/dist/services/update-service.d.ts +21 -0
  132. package/dist/services/update-service.js +130 -0
  133. package/dist/services/watchlist-profile-service.d.ts +20 -0
  134. package/dist/services/watchlist-profile-service.js +76 -0
  135. package/dist/services/watchlist-service.d.ts +43 -0
  136. package/dist/services/watchlist-service.js +204 -0
  137. package/dist/storage/db.d.ts +23 -0
  138. package/dist/storage/db.js +70 -0
  139. package/dist/storage/repositories/alert-log-repo.d.ts +15 -0
  140. package/dist/storage/repositories/alert-log-repo.js +54 -0
  141. package/dist/storage/repositories/analysis-log-repo.d.ts +8 -0
  142. package/dist/storage/repositories/analysis-log-repo.js +48 -0
  143. package/dist/storage/repositories/composite-analysis-repo.d.ts +9 -0
  144. package/dist/storage/repositories/composite-analysis-repo.js +116 -0
  145. package/dist/storage/repositories/financial-analysis-repo.d.ts +9 -0
  146. package/dist/storage/repositories/financial-analysis-repo.js +107 -0
  147. package/dist/storage/repositories/indicators-repo.d.ts +8 -0
  148. package/dist/storage/repositories/indicators-repo.js +98 -0
  149. package/dist/storage/repositories/intraday-klines-repo.d.ts +9 -0
  150. package/dist/storage/repositories/intraday-klines-repo.js +102 -0
  151. package/dist/storage/repositories/key-levels-history-repo.d.ts +9 -0
  152. package/dist/storage/repositories/key-levels-history-repo.js +91 -0
  153. package/dist/storage/repositories/key-levels-repo.d.ts +9 -0
  154. package/dist/storage/repositories/key-levels-repo.js +83 -0
  155. package/dist/storage/repositories/klines-repo.d.ts +8 -0
  156. package/dist/storage/repositories/klines-repo.js +60 -0
  157. package/dist/storage/repositories/news-analysis-repo.d.ts +9 -0
  158. package/dist/storage/repositories/news-analysis-repo.js +107 -0
  159. package/dist/storage/repositories/technical-analysis-repo.d.ts +9 -0
  160. package/dist/storage/repositories/technical-analysis-repo.js +80 -0
  161. package/dist/storage/repositories/watchlist-repo.d.ts +10 -0
  162. package/dist/storage/repositories/watchlist-repo.js +124 -0
  163. package/dist/storage/schemas.d.ts +13 -0
  164. package/dist/storage/schemas.js +177 -0
  165. package/dist/tools/add-stock.tool.d.ts +13 -0
  166. package/dist/tools/add-stock.tool.js +123 -0
  167. package/dist/tools/analyze.tool.d.ts +8 -0
  168. package/dist/tools/analyze.tool.js +24 -0
  169. package/dist/tools/backtest-key-levels.tool.d.ts +8 -0
  170. package/dist/tools/backtest-key-levels.tool.js +43 -0
  171. package/dist/tools/daily-update-status.tool.d.ts +6 -0
  172. package/dist/tools/daily-update-status.tool.js +9 -0
  173. package/dist/tools/fetch-financials.tool.d.ts +8 -0
  174. package/dist/tools/fetch-financials.tool.js +224 -0
  175. package/dist/tools/fetch-intraday-klines.tool.d.ts +11 -0
  176. package/dist/tools/fetch-intraday-klines.tool.js +58 -0
  177. package/dist/tools/fetch-klines.tool.d.ts +11 -0
  178. package/dist/tools/fetch-klines.tool.js +61 -0
  179. package/dist/tools/list-watchlist.tool.d.ts +6 -0
  180. package/dist/tools/list-watchlist.tool.js +22 -0
  181. package/dist/tools/monitor-status.tool.d.ts +6 -0
  182. package/dist/tools/monitor-status.tool.js +9 -0
  183. package/dist/tools/mx-search.tool.d.ts +8 -0
  184. package/dist/tools/mx-search.tool.js +77 -0
  185. package/dist/tools/mx-select-stock.tool.d.ts +8 -0
  186. package/dist/tools/mx-select-stock.tool.js +118 -0
  187. package/dist/tools/query-database.tool.d.ts +8 -0
  188. package/dist/tools/query-database.tool.js +283 -0
  189. package/dist/tools/refresh-watchlist-names.tool.d.ts +7 -0
  190. package/dist/tools/refresh-watchlist-names.tool.js +17 -0
  191. package/dist/tools/refresh-watchlist-profiles.tool.d.ts +9 -0
  192. package/dist/tools/refresh-watchlist-profiles.tool.js +67 -0
  193. package/dist/tools/remove-stock.tool.d.ts +9 -0
  194. package/dist/tools/remove-stock.tool.js +27 -0
  195. package/dist/tools/start-daily-update.tool.d.ts +10 -0
  196. package/dist/tools/start-daily-update.tool.js +23 -0
  197. package/dist/tools/start-monitor.tool.d.ts +9 -0
  198. package/dist/tools/start-monitor.tool.js +52 -0
  199. package/dist/tools/stop-daily-update.tool.d.ts +9 -0
  200. package/dist/tools/stop-daily-update.tool.js +20 -0
  201. package/dist/tools/stop-monitor.tool.d.ts +9 -0
  202. package/dist/tools/stop-monitor.tool.js +44 -0
  203. package/dist/tools/test-alert.tool.d.ts +7 -0
  204. package/dist/tools/test-alert.tool.js +21 -0
  205. package/dist/tools/update-all.tool.d.ts +9 -0
  206. package/dist/tools/update-all.tool.js +17 -0
  207. package/dist/tools/view-analysis.tool.d.ts +8 -0
  208. package/dist/tools/view-analysis.tool.js +95 -0
  209. package/dist/types/daily-update.d.ts +26 -0
  210. package/dist/types/daily-update.js +1 -0
  211. package/dist/types/domain.d.ts +140 -0
  212. package/dist/types/domain.js +1 -0
  213. package/dist/types/indicator.d.ts +43 -0
  214. package/dist/types/indicator.js +1 -0
  215. package/dist/types/monitor.d.ts +17 -0
  216. package/dist/types/monitor.js +1 -0
  217. package/dist/types/mx-search.d.ts +14 -0
  218. package/dist/types/mx-search.js +1 -0
  219. package/dist/types/mx-select-stock.d.ts +28 -0
  220. package/dist/types/mx-select-stock.js +1 -0
  221. package/dist/types/tickflow.d.ts +133 -0
  222. package/dist/types/tickflow.js +1 -0
  223. package/dist/utils/abortable-sleep.d.ts +1 -0
  224. package/dist/utils/abortable-sleep.js +20 -0
  225. package/dist/utils/china-time.d.ts +3 -0
  226. package/dist/utils/china-time.js +18 -0
  227. package/dist/utils/cost-price.d.ts +3 -0
  228. package/dist/utils/cost-price.js +18 -0
  229. package/dist/utils/format.d.ts +1 -0
  230. package/dist/utils/format.js +3 -0
  231. package/dist/utils/process.d.ts +5 -0
  232. package/dist/utils/process.js +1 -0
  233. package/dist/utils/symbol.d.ts +1 -0
  234. package/dist/utils/symbol.js +13 -0
  235. package/docs/installation.md +391 -0
  236. package/docs/usage.md +244 -0
  237. package/openclaw.plugin.json +116 -0
  238. package/package.json +57 -0
  239. package/python/indicator_runner.py +31 -0
  240. package/python/indicators.py +148 -0
  241. package/python/pyproject.toml +9 -0
  242. package/python/requirements.txt +3 -0
  243. package/python/uv.lock +366 -0
  244. package/skills/database-query/SKILL.md +58 -0
  245. package/skills/stock-analysis/SKILL.md +106 -0
  246. package/skills/usage-help/SKILL.md +102 -0
@@ -0,0 +1,177 @@
1
+ import { Field, Float64, Int64, Schema, Utf8 } from "apache-arrow";
2
+ export const watchlistSchema = new Schema([
3
+ new Field("symbol", new Utf8(), false),
4
+ new Field("name", new Utf8(), true),
5
+ new Field("costPrice", new Float64(), false),
6
+ new Field("addedAt", new Utf8(), false),
7
+ new Field("sector", new Utf8(), true),
8
+ new Field("themes", new Utf8(), true),
9
+ new Field("themeQuery", new Utf8(), true),
10
+ new Field("themeUpdatedAt", new Utf8(), true),
11
+ ]);
12
+ export const klinesDailySchema = new Schema([
13
+ new Field("symbol", new Utf8(), false),
14
+ new Field("trade_date", new Utf8(), false),
15
+ new Field("timestamp", new Int64(), false),
16
+ new Field("open", new Float64(), false),
17
+ new Field("high", new Float64(), false),
18
+ new Field("low", new Float64(), false),
19
+ new Field("close", new Float64(), false),
20
+ new Field("volume", new Float64(), false),
21
+ new Field("amount", new Float64(), false),
22
+ new Field("prev_close", new Float64(), true),
23
+ ]);
24
+ export const klinesIntradaySchema = new Schema([
25
+ new Field("symbol", new Utf8(), false),
26
+ new Field("period", new Utf8(), false),
27
+ new Field("trade_date", new Utf8(), false),
28
+ new Field("trade_time", new Utf8(), false),
29
+ new Field("timestamp", new Int64(), false),
30
+ new Field("open", new Float64(), false),
31
+ new Field("high", new Float64(), false),
32
+ new Field("low", new Float64(), false),
33
+ new Field("close", new Float64(), false),
34
+ new Field("volume", new Float64(), false),
35
+ new Field("amount", new Float64(), false),
36
+ new Field("prev_close", new Float64(), true),
37
+ new Field("open_interest", new Float64(), true),
38
+ new Field("settlement_price", new Float64(), true),
39
+ ]);
40
+ export const indicatorsSchema = new Schema([
41
+ new Field("symbol", new Utf8(), false),
42
+ new Field("trade_date", new Utf8(), false),
43
+ new Field("ma5", new Float64(), true),
44
+ new Field("ma10", new Float64(), true),
45
+ new Field("ma20", new Float64(), true),
46
+ new Field("ma60", new Float64(), true),
47
+ new Field("macd", new Float64(), true),
48
+ new Field("macd_signal", new Float64(), true),
49
+ new Field("macd_hist", new Float64(), true),
50
+ new Field("kdj_k", new Float64(), true),
51
+ new Field("kdj_d", new Float64(), true),
52
+ new Field("kdj_j", new Float64(), true),
53
+ new Field("rsi_6", new Float64(), true),
54
+ new Field("rsi_12", new Float64(), true),
55
+ new Field("rsi_24", new Float64(), true),
56
+ new Field("cci", new Float64(), true),
57
+ new Field("bias_6", new Float64(), true),
58
+ new Field("bias_12", new Float64(), true),
59
+ new Field("bias_24", new Float64(), true),
60
+ new Field("plus_di", new Float64(), true),
61
+ new Field("minus_di", new Float64(), true),
62
+ new Field("adx", new Float64(), true),
63
+ new Field("boll_upper", new Float64(), true),
64
+ new Field("boll_mid", new Float64(), true),
65
+ new Field("boll_lower", new Float64(), true),
66
+ ]);
67
+ export const keyLevelsSchema = new Schema([
68
+ new Field("symbol", new Utf8(), false),
69
+ new Field("analysis_date", new Utf8(), false),
70
+ new Field("current_price", new Float64(), false),
71
+ new Field("stop_loss", new Float64(), true),
72
+ new Field("breakthrough", new Float64(), true),
73
+ new Field("support", new Float64(), true),
74
+ new Field("cost_level", new Float64(), true),
75
+ new Field("resistance", new Float64(), true),
76
+ new Field("take_profit", new Float64(), true),
77
+ new Field("gap", new Float64(), true),
78
+ new Field("target", new Float64(), true),
79
+ new Field("round_number", new Float64(), true),
80
+ new Field("analysis_text", new Utf8(), false),
81
+ new Field("score", new Int64(), false),
82
+ ]);
83
+ export const keyLevelsHistorySchema = new Schema([
84
+ new Field("symbol", new Utf8(), false),
85
+ new Field("analysis_date", new Utf8(), false),
86
+ new Field("activated_at", new Utf8(), false),
87
+ new Field("profile", new Utf8(), false),
88
+ new Field("current_price", new Float64(), false),
89
+ new Field("stop_loss", new Float64(), true),
90
+ new Field("breakthrough", new Float64(), true),
91
+ new Field("support", new Float64(), true),
92
+ new Field("cost_level", new Float64(), true),
93
+ new Field("resistance", new Float64(), true),
94
+ new Field("take_profit", new Float64(), true),
95
+ new Field("gap", new Float64(), true),
96
+ new Field("target", new Float64(), true),
97
+ new Field("round_number", new Float64(), true),
98
+ new Field("analysis_text", new Utf8(), false),
99
+ new Field("score", new Int64(), true),
100
+ ]);
101
+ export const analysisLogSchema = new Schema([
102
+ new Field("symbol", new Utf8(), false),
103
+ new Field("analysis_date", new Utf8(), false),
104
+ new Field("analysis_text", new Utf8(), false),
105
+ new Field("structured_ok", new Int64(), false),
106
+ ]);
107
+ export const technicalAnalysisSchema = new Schema([
108
+ new Field("symbol", new Utf8(), false),
109
+ new Field("analysis_date", new Utf8(), false),
110
+ new Field("analysis_text", new Utf8(), false),
111
+ new Field("structured_ok", new Int64(), false),
112
+ new Field("current_price", new Float64(), true),
113
+ new Field("stop_loss", new Float64(), true),
114
+ new Field("breakthrough", new Float64(), true),
115
+ new Field("support", new Float64(), true),
116
+ new Field("cost_level", new Float64(), true),
117
+ new Field("resistance", new Float64(), true),
118
+ new Field("take_profit", new Float64(), true),
119
+ new Field("gap", new Float64(), true),
120
+ new Field("target", new Float64(), true),
121
+ new Field("round_number", new Float64(), true),
122
+ new Field("score", new Int64(), true),
123
+ ]);
124
+ export const financialAnalysisSchema = new Schema([
125
+ new Field("symbol", new Utf8(), false),
126
+ new Field("analysis_date", new Utf8(), false),
127
+ new Field("analysis_text", new Utf8(), false),
128
+ new Field("score", new Int64(), true),
129
+ new Field("bias", new Utf8(), false),
130
+ new Field("strengths_json", new Utf8(), false),
131
+ new Field("risks_json", new Utf8(), false),
132
+ new Field("watch_items_json", new Utf8(), false),
133
+ new Field("evidence_json", new Utf8(), false),
134
+ ]);
135
+ export const newsAnalysisSchema = new Schema([
136
+ new Field("symbol", new Utf8(), false),
137
+ new Field("analysis_date", new Utf8(), false),
138
+ new Field("query", new Utf8(), false),
139
+ new Field("analysis_text", new Utf8(), false),
140
+ new Field("score", new Int64(), true),
141
+ new Field("bias", new Utf8(), false),
142
+ new Field("catalysts_json", new Utf8(), false),
143
+ new Field("risks_json", new Utf8(), false),
144
+ new Field("watch_items_json", new Utf8(), false),
145
+ new Field("source_count", new Int64(), false),
146
+ new Field("evidence_json", new Utf8(), false),
147
+ ]);
148
+ export const compositeAnalysisSchema = new Schema([
149
+ new Field("symbol", new Utf8(), false),
150
+ new Field("analysis_date", new Utf8(), false),
151
+ new Field("analysis_text", new Utf8(), false),
152
+ new Field("structured_ok", new Int64(), false),
153
+ new Field("current_price", new Float64(), true),
154
+ new Field("stop_loss", new Float64(), true),
155
+ new Field("breakthrough", new Float64(), true),
156
+ new Field("support", new Float64(), true),
157
+ new Field("cost_level", new Float64(), true),
158
+ new Field("resistance", new Float64(), true),
159
+ new Field("take_profit", new Float64(), true),
160
+ new Field("gap", new Float64(), true),
161
+ new Field("target", new Float64(), true),
162
+ new Field("round_number", new Float64(), true),
163
+ new Field("score", new Int64(), true),
164
+ new Field("technical_score", new Int64(), true),
165
+ new Field("financial_score", new Int64(), true),
166
+ new Field("news_score", new Int64(), true),
167
+ new Field("financial_bias", new Utf8(), false),
168
+ new Field("news_bias", new Utf8(), false),
169
+ new Field("evidence_json", new Utf8(), false),
170
+ ]);
171
+ export const alertLogSchema = new Schema([
172
+ new Field("symbol", new Utf8(), false),
173
+ new Field("alert_date", new Utf8(), false),
174
+ new Field("rule_name", new Utf8(), false),
175
+ new Field("message", new Utf8(), false),
176
+ new Field("triggered_at", new Utf8(), false),
177
+ ]);
@@ -0,0 +1,13 @@
1
+ import { WatchlistService } from "../services/watchlist-service.js";
2
+ import { KlineService } from "../services/kline-service.js";
3
+ import { KlinesRepository } from "../storage/repositories/klines-repo.js";
4
+ import { IndicatorService } from "../services/indicator-service.js";
5
+ import { IndicatorsRepository } from "../storage/repositories/indicators-repo.js";
6
+ export declare function addStockTool(watchlistService: WatchlistService, klineService: KlineService, klinesRepository: KlinesRepository, indicatorService: IndicatorService, indicatorsRepository: IndicatorsRepository): {
7
+ name: string;
8
+ description: string;
9
+ optional: boolean;
10
+ run({ rawInput }: {
11
+ rawInput?: unknown;
12
+ }): Promise<string>;
13
+ };
@@ -0,0 +1,123 @@
1
+ import { formatCostPrice } from "../utils/cost-price.js";
2
+ const DEFAULT_ADD_STOCK_KLINE_COUNT = 90;
3
+ function parseInput(rawInput) {
4
+ if (typeof rawInput === "object" && rawInput !== null) {
5
+ const input = rawInput;
6
+ const symbol = String(input.symbol ?? "").trim();
7
+ const costPrice = parseOptionalPositiveNumber(input.costPrice);
8
+ const count = parseOptionalPositiveNumber(input.klineCount ?? input.count);
9
+ if (!symbol) {
10
+ throw new Error("add-stock requires { symbol }");
11
+ }
12
+ return { symbol, costPrice, count };
13
+ }
14
+ if (typeof rawInput === "string") {
15
+ const parts = rawInput.trim().split(/\s+/, 3).filter(Boolean);
16
+ if (parts.length >= 1) {
17
+ const symbol = parts[0] ?? "";
18
+ const costPrice = parts[1] == null ? undefined : parseOptionalPositiveNumber(parts[1]);
19
+ const count = parts[2] == null ? undefined : parseOptionalPositiveNumber(parts[2]);
20
+ if (symbol) {
21
+ return { symbol, costPrice, count };
22
+ }
23
+ }
24
+ }
25
+ throw new Error("invalid add-stock input");
26
+ }
27
+ function parseOptionalPositiveNumber(value) {
28
+ if (value == null || String(value).trim() === "") {
29
+ return undefined;
30
+ }
31
+ const numeric = Number(value);
32
+ if (!Number.isFinite(numeric) || numeric <= 0) {
33
+ throw new Error("number must be greater than 0");
34
+ }
35
+ return numeric;
36
+ }
37
+ export function addStockTool(watchlistService, klineService, klinesRepository, indicatorService, indicatorsRepository) {
38
+ return {
39
+ name: "add_stock",
40
+ description: "Add a symbol to the watchlist with optional cost price, then fetch daily K-lines and indicators.",
41
+ optional: true,
42
+ async run({ rawInput }) {
43
+ let input;
44
+ try {
45
+ input = parseInput(rawInput);
46
+ }
47
+ catch (error) {
48
+ return formatAddStockFailure(null, error);
49
+ }
50
+ const { symbol, costPrice, count } = input;
51
+ const klineCount = count ?? DEFAULT_ADD_STOCK_KLINE_COUNT;
52
+ let addResult;
53
+ try {
54
+ addResult = await watchlistService.add(symbol, costPrice ?? null);
55
+ }
56
+ catch (error) {
57
+ return formatAddStockFailure(symbol, error);
58
+ }
59
+ const { item, profileError } = addResult;
60
+ try {
61
+ const rows = await klineService.fetchKlines(item.symbol, {
62
+ count: klineCount,
63
+ adjust: "forward",
64
+ });
65
+ if (rows.length === 0) {
66
+ return [
67
+ ...buildAddStockPrefix(item, profileError),
68
+ `⚠️ 已尝试拉取 ${klineCount} 天日K,但返回数据为空`,
69
+ ].filter(Boolean).join("\n");
70
+ }
71
+ await klinesRepository.saveAll(item.symbol, rows);
72
+ const indicators = await indicatorService.calculate(rows);
73
+ await indicatorsRepository.saveAll(item.symbol, indicators);
74
+ const first = rows[0];
75
+ const last = rows[rows.length - 1];
76
+ return [
77
+ ...buildAddStockPrefix(item, profileError),
78
+ `📊 已自动获取日K: ${rows.length} 根`,
79
+ `区间: ${first.trade_date} ~ ${last.trade_date}`,
80
+ `最新收盘: ${last.close.toFixed(2)}`,
81
+ `🔧 技术指标已计算并写入数据库`,
82
+ ].filter(Boolean).join("\n");
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ return [
87
+ ...buildAddStockPrefix(item, profileError),
88
+ `⚠️ 自动拉取 ${klineCount} 天日K失败: ${message}`,
89
+ ].filter(Boolean).join("\n");
90
+ }
91
+ },
92
+ };
93
+ }
94
+ function buildAddStockPrefix(item, profileError) {
95
+ return [
96
+ `✅ 已添加: ${item.name}(${item.symbol}),成本价: ${formatCostPrice(item.costPrice)}`,
97
+ formatWatchlistProfile(item),
98
+ formatWatchlistProfileWarning(profileError),
99
+ ].filter((value) => Boolean(value));
100
+ }
101
+ function formatWatchlistProfile(item) {
102
+ const parts = [
103
+ item.sector ? `行业分类: ${item.sector}` : null,
104
+ item.themes.length > 0 ? `概念板块: ${item.themes.join("、")}` : null,
105
+ ].filter(Boolean);
106
+ if (parts.length === 0) {
107
+ return null;
108
+ }
109
+ return `🏷️ ${parts.join(" | ")}`;
110
+ }
111
+ function formatWatchlistProfileWarning(profileError) {
112
+ if (!profileError) {
113
+ return null;
114
+ }
115
+ return `⚠️ 行业分类/概念板块获取失败: ${profileError}`;
116
+ }
117
+ function formatAddStockFailure(symbol, error) {
118
+ const message = error instanceof Error ? error.message : String(error);
119
+ if (!symbol) {
120
+ return `添加失败😔 请求参数无效:${message}`;
121
+ }
122
+ return `添加失败😔 ${symbol} 暂时无法添加:${message}`;
123
+ }
@@ -0,0 +1,8 @@
1
+ import { CompositeAnalysisOrchestrator } from "../analysis/orchestrators/composite-analysis.orchestrator.js";
2
+ export declare function analyzeTool(compositeAnalysisOrchestrator: CompositeAnalysisOrchestrator): {
3
+ name: string;
4
+ description: string;
5
+ run({ rawInput }: {
6
+ rawInput?: unknown;
7
+ }): Promise<string>;
8
+ };
@@ -0,0 +1,24 @@
1
+ import { normalizeSymbol } from "../utils/symbol.js";
2
+ function parseSymbol(rawInput) {
3
+ if (typeof rawInput === "string" && rawInput.trim()) {
4
+ return rawInput.trim();
5
+ }
6
+ if (typeof rawInput === "object" && rawInput !== null) {
7
+ const symbol = String(rawInput.symbol ?? "").trim();
8
+ if (symbol) {
9
+ return symbol;
10
+ }
11
+ }
12
+ throw new Error("analyze requires a symbol");
13
+ }
14
+ export function analyzeTool(compositeAnalysisOrchestrator) {
15
+ return {
16
+ name: "analyze",
17
+ description: "Run fixed-pipeline stock analysis using technical data, financial data, and timely market information.",
18
+ async run({ rawInput }) {
19
+ const symbol = normalizeSymbol(parseSymbol(rawInput));
20
+ const result = await compositeAnalysisOrchestrator.analyze(symbol);
21
+ return compositeAnalysisOrchestrator.formatForUser(result);
22
+ },
23
+ };
24
+ }
@@ -0,0 +1,8 @@
1
+ import { KeyLevelsBacktestService } from "../services/key-levels-backtest-service.js";
2
+ export declare function backtestKeyLevelsTool(keyLevelsBacktestService: KeyLevelsBacktestService): {
3
+ name: string;
4
+ description: string;
5
+ run({ rawInput }: {
6
+ rawInput?: unknown;
7
+ }): Promise<string>;
8
+ };
@@ -0,0 +1,43 @@
1
+ function parseInput(rawInput) {
2
+ if (rawInput == null || rawInput === "") {
3
+ return {};
4
+ }
5
+ if (typeof rawInput === "string") {
6
+ const text = rawInput.trim();
7
+ if (!text || text.toLowerCase() === "all" || text === "全部") {
8
+ return {};
9
+ }
10
+ const [symbol, limitToken] = text.split(/\s+/, 2);
11
+ return {
12
+ symbol,
13
+ recentLimit: normalizeLimit(limitToken),
14
+ };
15
+ }
16
+ if (typeof rawInput === "object" && rawInput !== null) {
17
+ const input = rawInput;
18
+ return {
19
+ symbol: typeof input.symbol === "string" && input.symbol.trim() ? input.symbol.trim() : undefined,
20
+ recentLimit: normalizeLimit(input.recentLimit ?? input.limit ?? input.count),
21
+ };
22
+ }
23
+ throw new Error("backtest_key_levels input is invalid");
24
+ }
25
+ function normalizeLimit(value) {
26
+ if (value == null || value === "") {
27
+ return undefined;
28
+ }
29
+ const limit = Number(value);
30
+ if (!Number.isFinite(limit) || limit <= 0) {
31
+ throw new Error("backtest_key_levels recentLimit must be > 0");
32
+ }
33
+ return Math.min(Math.trunc(limit), 20);
34
+ }
35
+ export function backtestKeyLevelsTool(keyLevelsBacktestService) {
36
+ return {
37
+ name: "backtest_key_levels",
38
+ description: "Backtest active key-level snapshots with 1/3/5-day support, resistance, stop-loss, take-profit, and breakthrough effectiveness statistics.",
39
+ async run({ rawInput }) {
40
+ return keyLevelsBacktestService.render(parseInput(rawInput));
41
+ },
42
+ };
43
+ }
@@ -0,0 +1,6 @@
1
+ import { DailyUpdateWorker } from "../background/daily-update.worker.js";
2
+ export declare function dailyUpdateStatusTool(dailyUpdateWorker: DailyUpdateWorker, _configSource: string): {
3
+ name: string;
4
+ description: string;
5
+ run(): Promise<string>;
6
+ };
@@ -0,0 +1,9 @@
1
+ export function dailyUpdateStatusTool(dailyUpdateWorker, _configSource) {
2
+ return {
3
+ name: "daily_update_status",
4
+ description: "Show the daily-update scheduler status, config source, heartbeat, and recent daily-update/review results.",
5
+ async run() {
6
+ return dailyUpdateWorker.getStatusReport();
7
+ },
8
+ };
9
+ }
@@ -0,0 +1,8 @@
1
+ import { FinancialService } from "../services/financial-service.js";
2
+ export declare function fetchFinancialsTool(financialService: FinancialService): {
3
+ name: string;
4
+ description: string;
5
+ run({ rawInput }: {
6
+ rawInput?: unknown;
7
+ }): Promise<string>;
8
+ };
@@ -0,0 +1,224 @@
1
+ import { normalizeSymbol } from "../utils/symbol.js";
2
+ import { ALL_FINANCIAL_SECTIONS, } from "../services/financial-service.js";
3
+ const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
4
+ const SECTION_ALIASES = {
5
+ income: "income",
6
+ 利润表: "income",
7
+ profit: "income",
8
+ metrics: "metrics",
9
+ metric: "metrics",
10
+ indicators: "metrics",
11
+ 核心指标: "metrics",
12
+ 财务指标: "metrics",
13
+ cash_flow: "cash_flow",
14
+ cashflow: "cash_flow",
15
+ cash: "cash_flow",
16
+ 现金流: "cash_flow",
17
+ 现金流量表: "cash_flow",
18
+ balance_sheet: "balance_sheet",
19
+ balancesheet: "balance_sheet",
20
+ balance: "balance_sheet",
21
+ 资产负债表: "balance_sheet",
22
+ };
23
+ function parseInput(rawInput) {
24
+ if (typeof rawInput === "object" && rawInput !== null) {
25
+ const obj = rawInput;
26
+ const symbol = String(obj.symbol ?? "").trim();
27
+ if (!symbol) {
28
+ throw new Error("fetch-financials requires symbol");
29
+ }
30
+ const startDate = readOptionalString(obj.startDate ?? obj.start_date);
31
+ const endDate = readOptionalString(obj.endDate ?? obj.end_date);
32
+ const latest = readOptionalBoolean(obj.latest);
33
+ const sections = normalizeSections(obj.sections ?? obj.section ?? obj.type);
34
+ validateDate(startDate, "startDate");
35
+ validateDate(endDate, "endDate");
36
+ return {
37
+ symbol,
38
+ startDate,
39
+ endDate,
40
+ latest: latest ?? true,
41
+ sections,
42
+ };
43
+ }
44
+ if (typeof rawInput === "string" && rawInput.trim()) {
45
+ return {
46
+ symbol: rawInput.trim(),
47
+ latest: true,
48
+ sections: ALL_FINANCIAL_SECTIONS,
49
+ };
50
+ }
51
+ throw new Error("invalid fetch-financials input");
52
+ }
53
+ function readOptionalString(value) {
54
+ if (value == null) {
55
+ return undefined;
56
+ }
57
+ const text = String(value).trim();
58
+ return text || undefined;
59
+ }
60
+ function readOptionalBoolean(value) {
61
+ if (value == null) {
62
+ return undefined;
63
+ }
64
+ if (typeof value === "boolean") {
65
+ return value;
66
+ }
67
+ if (typeof value === "string") {
68
+ const normalized = value.trim().toLowerCase();
69
+ if (["true", "1", "yes", "on"].includes(normalized)) {
70
+ return true;
71
+ }
72
+ if (["false", "0", "no", "off"].includes(normalized)) {
73
+ return false;
74
+ }
75
+ }
76
+ throw new Error(`invalid boolean value: ${String(value)}`);
77
+ }
78
+ function normalizeSections(value) {
79
+ if (value == null) {
80
+ return ALL_FINANCIAL_SECTIONS;
81
+ }
82
+ const rawItems = Array.isArray(value)
83
+ ? value
84
+ : typeof value === "string"
85
+ ? value.split(",")
86
+ : [value];
87
+ const resolved = rawItems
88
+ .map((item) => SECTION_ALIASES[String(item).trim().toLowerCase()] ?? SECTION_ALIASES[String(item).trim()])
89
+ .filter((item) => item != null);
90
+ if (resolved.length === 0) {
91
+ throw new Error("fetch-financials sections must include income, metrics, cash_flow, or balance_sheet");
92
+ }
93
+ return [...new Set(resolved)];
94
+ }
95
+ function validateDate(value, fieldName) {
96
+ if (value && !DATE_PATTERN.test(value)) {
97
+ throw new Error(`${fieldName} must be YYYY-MM-DD`);
98
+ }
99
+ }
100
+ export function fetchFinancialsTool(financialService) {
101
+ return {
102
+ name: "fetch_financials",
103
+ description: "Fetch income statement, balance sheet, cash flow, and financial metrics from TickFlow.",
104
+ async run({ rawInput }) {
105
+ const input = parseInput(rawInput);
106
+ const symbol = normalizeSymbol(input.symbol);
107
+ const snapshot = await financialService.fetchSnapshot(symbol, {
108
+ start_date: input.startDate,
109
+ end_date: input.endDate,
110
+ latest: input.latest,
111
+ }, input.sections);
112
+ return renderFinancialSnapshot(snapshot, input);
113
+ },
114
+ };
115
+ }
116
+ function renderFinancialSnapshot(snapshot, input) {
117
+ const lines = [
118
+ `📘 获取 ${snapshot.symbol} 财务数据完成`,
119
+ `查询条件: ${renderScope(input)}`,
120
+ `维度: ${input.sections.join(", ")}`,
121
+ "",
122
+ ];
123
+ for (const section of input.sections) {
124
+ if (section === "income") {
125
+ lines.push(...renderIncomeSection(snapshot.income), "");
126
+ }
127
+ else if (section === "metrics") {
128
+ lines.push(...renderMetricsSection(snapshot.metrics), "");
129
+ }
130
+ else if (section === "cash_flow") {
131
+ lines.push(...renderCashFlowSection(snapshot.cashFlow), "");
132
+ }
133
+ else if (section === "balance_sheet") {
134
+ lines.push(...renderBalanceSheetSection(snapshot.balanceSheet), "");
135
+ }
136
+ }
137
+ while (lines.length > 0 && lines[lines.length - 1] === "") {
138
+ lines.pop();
139
+ }
140
+ return lines.join("\n");
141
+ }
142
+ function renderScope(input) {
143
+ const parts = [];
144
+ if (input.latest === true) {
145
+ parts.push("latest=true");
146
+ }
147
+ else if (input.latest === false) {
148
+ parts.push("latest=false");
149
+ }
150
+ if (input.startDate) {
151
+ parts.push(`start=${input.startDate}`);
152
+ }
153
+ if (input.endDate) {
154
+ parts.push(`end=${input.endDate}`);
155
+ }
156
+ return parts.join(", ") || "默认参数";
157
+ }
158
+ function renderIncomeSection(rows) {
159
+ if (rows.length === 0) {
160
+ return ["## 利润表", "暂无数据"];
161
+ }
162
+ const latest = rows[0];
163
+ return [
164
+ "## 利润表",
165
+ `期数: ${rows.length} | 最新报告期: ${latest.period_end} | 公告日: ${latest.announce_date ?? "未知"}`,
166
+ `营收=${formatLargeNumber(latest.revenue)} | 营业利润=${formatLargeNumber(latest.operating_profit)} | 利润总额=${formatLargeNumber(latest.total_profit)}`,
167
+ `净利润=${formatLargeNumber(latest.net_income)} | 归母净利润=${formatLargeNumber(latest.net_income_attributable)} | 基本EPS=${formatScalar(latest.basic_eps)}`,
168
+ ];
169
+ }
170
+ function renderMetricsSection(rows) {
171
+ if (rows.length === 0) {
172
+ return ["## 核心财务指标", "暂无数据"];
173
+ }
174
+ const latest = rows[0];
175
+ return [
176
+ "## 核心财务指标",
177
+ `期数: ${rows.length} | 最新报告期: ${latest.period_end} | 公告日: ${latest.announce_date ?? "未知"}`,
178
+ `ROE=${formatScalar(latest.roe)} | ROA=${formatScalar(latest.roa)} | 毛利率=${formatScalar(latest.gross_margin)} | 净利率=${formatScalar(latest.net_margin)}`,
179
+ `营收同比=${formatScalar(latest.revenue_yoy)} | 净利同比=${formatScalar(latest.net_income_yoy)} | 资产负债率=${formatScalar(latest.debt_to_asset_ratio)}`,
180
+ ];
181
+ }
182
+ function renderCashFlowSection(rows) {
183
+ if (rows.length === 0) {
184
+ return ["## 现金流量表", "暂无数据"];
185
+ }
186
+ const latest = rows[0];
187
+ return [
188
+ "## 现金流量表",
189
+ `期数: ${rows.length} | 最新报告期: ${latest.period_end} | 公告日: ${latest.announce_date ?? "未知"}`,
190
+ `经营现金流=${formatLargeNumber(latest.net_operating_cash_flow)} | 投资现金流=${formatLargeNumber(latest.net_investing_cash_flow)} | 筹资现金流=${formatLargeNumber(latest.net_financing_cash_flow)}`,
191
+ `现金净变动=${formatLargeNumber(latest.net_cash_change)} | 资本开支=${formatLargeNumber(latest.capex)}`,
192
+ ];
193
+ }
194
+ function renderBalanceSheetSection(rows) {
195
+ if (rows.length === 0) {
196
+ return ["## 资产负债表", "暂无数据"];
197
+ }
198
+ const latest = rows[0];
199
+ return [
200
+ "## 资产负债表",
201
+ `期数: ${rows.length} | 最新报告期: ${latest.period_end} | 公告日: ${latest.announce_date ?? "未知"}`,
202
+ `总资产=${formatLargeNumber(latest.total_assets)} | 总负债=${formatLargeNumber(latest.total_liabilities)} | 所有者权益=${formatLargeNumber(latest.total_equity)}`,
203
+ `货币资金=${formatLargeNumber(latest.cash_and_equivalents)} | 流动资产=${formatLargeNumber(latest.total_current_assets)} | 流动负债=${formatLargeNumber(latest.total_current_liabilities)}`,
204
+ ];
205
+ }
206
+ function formatLargeNumber(value) {
207
+ if (value == null || Number.isNaN(value)) {
208
+ return "-";
209
+ }
210
+ const abs = Math.abs(value);
211
+ if (abs >= 1e8) {
212
+ return `${(value / 1e8).toFixed(2)}亿`;
213
+ }
214
+ if (abs >= 1e4) {
215
+ return `${(value / 1e4).toFixed(2)}万`;
216
+ }
217
+ return value.toFixed(2);
218
+ }
219
+ function formatScalar(value) {
220
+ if (value == null || Number.isNaN(value)) {
221
+ return "-";
222
+ }
223
+ return value.toFixed(4);
224
+ }
@@ -0,0 +1,11 @@
1
+ import { type TickflowApiKeyLevel } from "../config/tickflow-access.js";
2
+ import { KlineService } from "../services/kline-service.js";
3
+ import { TradingCalendarService } from "../services/trading-calendar-service.js";
4
+ import { IntradayKlinesRepository } from "../storage/repositories/intraday-klines-repo.js";
5
+ export declare function fetchIntradayKlinesTool(tickflowApiKeyLevel: TickflowApiKeyLevel, klineService: KlineService, intradayKlinesRepository: IntradayKlinesRepository, tradingCalendarService: TradingCalendarService): {
6
+ name: string;
7
+ description: string;
8
+ run({ rawInput }: {
9
+ rawInput?: unknown;
10
+ }): Promise<string>;
11
+ };