erlangshen 0.1.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 (93) hide show
  1. package/.claude/agents/equity-agent.md +26 -0
  2. package/.claude/agents/macro-agent.md +25 -0
  3. package/.claude/commands/analyze.md +40 -0
  4. package/.claude/commands/macro.md +29 -0
  5. package/.claude/settings.json +12 -0
  6. package/CODEX_GOAL.md +46 -0
  7. package/README.md +206 -0
  8. package/bin/cli.js +67 -0
  9. package/bin/erlangshen +2 -0
  10. package/bin/xiaoergod +2 -0
  11. package/frontend/index.html +700 -0
  12. package/knowledge/crypto_guide.md +147 -0
  13. package/knowledge/economic_indicators.md +125 -0
  14. package/knowledge/financial_glossary.md +148 -0
  15. package/knowledge/first_principles.md +50 -0
  16. package/knowledge/first_principles_deep.md +115 -0
  17. package/knowledge/global_markets.md +173 -0
  18. package/knowledge/insights.md +141 -0
  19. package/knowledge/market_basics.md +116 -0
  20. package/knowledge/memos/session_20260513_003616.json +6 -0
  21. package/knowledge/memos/session_20260513_003822.json +6 -0
  22. package/knowledge/risk_management.md +151 -0
  23. package/knowledge/team_context.md +42 -0
  24. package/knowledge/trading_strategies.md +114 -0
  25. package/package.json +42 -0
  26. package/requirements.txt +14 -0
  27. package/scripts/postinstall.js +188 -0
  28. package/scripts/preuninstall.js +22 -0
  29. package/src/__init__.py +4 -0
  30. package/src/__pycache__/__init__.cpython-313.pyc +0 -0
  31. package/src/agents/__init__.py +3 -0
  32. package/src/agents/base.py +103 -0
  33. package/src/agents/base_agent.py +86 -0
  34. package/src/agents/equity.py +136 -0
  35. package/src/agents/equity_agent.py +91 -0
  36. package/src/agents/erlang.py +165 -0
  37. package/src/agents/macro.py +137 -0
  38. package/src/agents/macro_agent.py +81 -0
  39. package/src/agents/multi_asset.py +147 -0
  40. package/src/agents/multi_asset_agent.py +87 -0
  41. package/src/api/__init__.py +1 -0
  42. package/src/api/__pycache__/__init__.cpython-313.pyc +0 -0
  43. package/src/api/__pycache__/server.cpython-313.pyc +0 -0
  44. package/src/api/cli.py +435 -0
  45. package/src/api/cli_enhanced.py +537 -0
  46. package/src/api/server.py +266 -0
  47. package/src/brain.py +200 -0
  48. package/src/cli.py +153 -0
  49. package/src/commands/__init__.py +3 -0
  50. package/src/commands/analyze.py +131 -0
  51. package/src/commands/macro.py +100 -0
  52. package/src/commands/memo.py +216 -0
  53. package/src/commands/portfolio.py +154 -0
  54. package/src/commands/report.py +228 -0
  55. package/src/commands/risk.py +183 -0
  56. package/src/commands/search.py +183 -0
  57. package/src/commands/stock.py +124 -0
  58. package/src/config.py +327 -0
  59. package/src/core/__init__.py +1 -0
  60. package/src/core/brain.py +645 -0
  61. package/src/core/cerebellum.py +175 -0
  62. package/src/core/investment_universe.py +423 -0
  63. package/src/core/knowledge.py +207 -0
  64. package/src/core/memory.py +115 -0
  65. package/src/hooks/__init__.py +3 -0
  66. package/src/hooks/session_end.py +57 -0
  67. package/src/hooks/session_start.py +75 -0
  68. package/src/knowledge/__init__.py +1 -0
  69. package/src/mcp/__init__.py +3 -0
  70. package/src/mcp/feishu.py +331 -0
  71. package/src/mcp/fund_tools.py +323 -0
  72. package/src/mcp/macro.py +452 -0
  73. package/src/mcp/market.py +331 -0
  74. package/src/mcp/registry.py +168 -0
  75. package/src/network/__init__.py +15 -0
  76. package/src/network/detector.py +125 -0
  77. package/src/network/proxy.py +199 -0
  78. package/src/network/router.py +103 -0
  79. package/src/prompts/__init__.py +1 -0
  80. package/src/prompts/analysis_framework.md +164 -0
  81. package/src/prompts/persona.md +65 -0
  82. package/src/prompts/report_template.md +144 -0
  83. package/src/skills/__init__.py +3 -0
  84. package/src/skills/framework.py +105 -0
  85. package/src/skills/templates.py +342 -0
  86. package/src/tools/__init__.py +1 -0
  87. package/src/tools/file_tools.py +209 -0
  88. package/src/tools/macro_tools.py +152 -0
  89. package/src/tools/market_tools.py +1172 -0
  90. package/src/tools/registry.py +398 -0
  91. package/src/tools/search_tools.py +777 -0
  92. package/tests/__init__.py +1 -0
  93. package/tests/test_erlangshen.py +140 -0
@@ -0,0 +1,452 @@
1
+ """
2
+ MCP 工具 - 宏观数据
3
+ 使用真实数据库数据
4
+ """
5
+
6
+ import sys
7
+ from typing import Dict, Any, Optional, List
8
+ from datetime import datetime
9
+ import logging
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ # 导入投资系统数据库连接
14
+ sys.path.insert(0, '/Users/wanghui/.openclaw-agent-06/workspace/investment-strategy')
15
+ from backend.core.database import execute_local_query
16
+
17
+
18
+ class MacroMCP:
19
+ """
20
+ 宏观数据 MCP
21
+
22
+ 提供宏观经济指标、利率、汇率等数据接口
23
+ 数据来源:本地数据库 (macro_monitor)
24
+ """
25
+
26
+ def __init__(self):
27
+ self.name = "macro"
28
+
29
+ async def get_macro_indicator(
30
+ self,
31
+ indicator_code: str,
32
+ country: str = "CN"
33
+ ) -> Dict[str, Any]:
34
+ """
35
+ 获取宏观指标最新值
36
+
37
+ Args:
38
+ indicator_code: 指标代码,如 "GDP_YOY", "CPI", "PMI_MFG", "SHIBOR_3M"
39
+ country: 国家代码 (CN, US, EU)
40
+
41
+ Returns:
42
+ 宏观指标数据
43
+ """
44
+ try:
45
+ sql = """
46
+ SELECT indicator_code, indicator_name, data_value, period, period_type, publish_date
47
+ FROM cn_macro_data
48
+ WHERE indicator_code = %s
49
+ ORDER BY period DESC
50
+ LIMIT 1
51
+ """
52
+ rows = execute_local_query('macro', sql, (indicator_code,))
53
+ if rows:
54
+ r = rows[0]
55
+ return {
56
+ "indicator_code": r['indicator_code'],
57
+ "name": r['indicator_name'],
58
+ "value": float(r['data_value']) if r['data_value'] else None,
59
+ "period": str(r['period']),
60
+ "period_type": r.get('period_type', ''),
61
+ "publish_date": str(r['publish_date']) if r.get('publish_date') else None,
62
+ "country": country,
63
+ "source": "macro_monitor_db"
64
+ }
65
+ return {"error": f"未找到指标 {indicator_code}", "indicator_code": indicator_code}
66
+ except Exception as e:
67
+ logger.error(f"获取宏观指标 {indicator_code} 失败: {e}")
68
+ return {"error": f"数据库查询失败: {str(e)}", "indicator_code": indicator_code}
69
+
70
+ async def get_macro_history(
71
+ self,
72
+ indicator_code: str,
73
+ months: int = 12
74
+ ) -> List[Dict[str, Any]]:
75
+ """
76
+ 获取宏观指标历史数据
77
+
78
+ Args:
79
+ indicator_code: 指标代码
80
+ months: 历史月数
81
+
82
+ Returns:
83
+ 历史数据列表
84
+ """
85
+ try:
86
+ sql = """
87
+ SELECT indicator_code, indicator_name, data_value, period, period_type
88
+ FROM cn_macro_data
89
+ WHERE indicator_code = %s
90
+ ORDER BY period DESC
91
+ LIMIT %s
92
+ """
93
+ rows = execute_local_query('macro', sql, (indicator_code, months))
94
+ if rows:
95
+ return [
96
+ {
97
+ "period": str(r['period']),
98
+ "value": float(r['data_value']) if r['data_value'] else None,
99
+ "name": r['indicator_name'],
100
+ "period_type": r.get('period_type', ''),
101
+ }
102
+ for r in rows
103
+ ]
104
+ return [{"error": f"未找到指标 {indicator_code} 的历史数据"}]
105
+ except Exception as e:
106
+ logger.error(f"获取宏观指标 {indicator_code} 历史失败: {e}")
107
+ return [{"error": f"数据库查询失败: {str(e)}"}]
108
+
109
+ async def list_indicators(self, category: str = None) -> List[Dict[str, Any]]:
110
+ """
111
+ 列出可用指标
112
+
113
+ Args:
114
+ category: 指标类别 (可选),如 "景气指标", "经济增长", "外贸", "金融"
115
+
116
+ Returns:
117
+ 指标列表
118
+ """
119
+ try:
120
+ if category:
121
+ sql = "SELECT indicator_code, indicator_name, category, unit, frequency, source, description FROM indicator_metadata WHERE category = %s"
122
+ rows = execute_local_query('macro', sql, (category,))
123
+ else:
124
+ sql = "SELECT indicator_code, indicator_name, category, unit, frequency, source, description FROM indicator_metadata"
125
+ rows = execute_local_query('macro', sql, ())
126
+ return rows if rows else []
127
+ except Exception as e:
128
+ logger.error(f"列出指标失败: {e}")
129
+ return []
130
+
131
+ async def get_interest_rates(
132
+ self,
133
+ rate_type: str = "LPR",
134
+ country: str = "CN"
135
+ ) -> Dict[str, Any]:
136
+ """
137
+ 获取利率数据
138
+
139
+ Args:
140
+ rate_type: 利率类型 (LPR, MLF, SLF, SHIBOR_3M, SHIBOR_1Y)
141
+ country: 国家代码
142
+
143
+ Returns:
144
+ 利率数据
145
+ """
146
+ # 利率指标映射
147
+ rate_map = {
148
+ "LPR": "LPR",
149
+ "MLF": "MLF",
150
+ "SLF": "SLF",
151
+ "SHIBOR_3M": "SHIBOR_3M",
152
+ "SHIBOR_1Y": "SHIBOR_1Y",
153
+ }
154
+ indicator_code = rate_map.get(rate_type, rate_type)
155
+
156
+ try:
157
+ sql = """
158
+ SELECT indicator_code, indicator_name, data_value, period, publish_date
159
+ FROM cn_macro_data
160
+ WHERE indicator_code = %s
161
+ ORDER BY period DESC
162
+ LIMIT 1
163
+ """
164
+ rows = execute_local_query('macro', sql, (indicator_code,))
165
+ if rows:
166
+ r = rows[0]
167
+ return {
168
+ "rate_type": rate_type,
169
+ "name": r['indicator_name'],
170
+ "country": country,
171
+ "value": float(r['data_value']) if r['data_value'] else None,
172
+ "period": str(r['period']),
173
+ "publish_date": str(r['publish_date']) if r.get('publish_date') else None,
174
+ "source": "macro_monitor_db"
175
+ }
176
+ return {"error": f"未找到利率数据 {rate_type}", "rate_type": rate_type}
177
+ except Exception as e:
178
+ logger.error(f"获取利率 {rate_type} 失败: {e}")
179
+ return {"error": f"数据库查询失败: {str(e)}", "rate_type": rate_type}
180
+
181
+ async def get_currency_rates(
182
+ self,
183
+ base: str = "USD",
184
+ target: Optional[str] = None
185
+ ) -> Dict[str, Any]:
186
+ """
187
+ 获取汇率数据
188
+
189
+ Args:
190
+ base: 基准货币代码
191
+ target: 目标货币代码 (可选,None则返回所有)
192
+
193
+ Returns:
194
+ 汇率数据
195
+ """
196
+ currency_names = {
197
+ "USD": "美元",
198
+ "CNY": "人民币",
199
+ "EUR": "欧元",
200
+ "JPY": "日元",
201
+ "GBP": "英镑",
202
+ "HKD": "港币",
203
+ "AUD": "澳元",
204
+ "CHF": "瑞士法郎",
205
+ }
206
+
207
+ if target:
208
+ try:
209
+ pair = f"{base}/{target}"
210
+ sql = """
211
+ SELECT currency_pair, rate, period
212
+ FROM cn_currency_rates
213
+ WHERE currency_pair = %s
214
+ ORDER BY period DESC
215
+ LIMIT 1
216
+ """
217
+ rows = execute_local_query('macro', sql, (pair,))
218
+ if rows:
219
+ r = rows[0]
220
+ return {
221
+ "base": base,
222
+ "target": target,
223
+ "base_name": currency_names.get(base, base),
224
+ "target_name": currency_names.get(target, target),
225
+ "rate": float(r['rate']) if r['rate'] else None,
226
+ "period": str(r['period']),
227
+ "source": "macro_monitor_db"
228
+ }
229
+ return {"error": f"未找到汇率 {pair}", "base": base, "target": target}
230
+ except Exception as e:
231
+ logger.error(f"获取汇率 {base}/{target} 失败: {e}")
232
+ return {"error": f"数据库查询失败: {str(e)}"}
233
+ else:
234
+ # 返回主要货币对人民币汇率
235
+ targets = ["CNY", "EUR", "JPY", "GBP", "HKD", "AUD"]
236
+ rates = {}
237
+ for t in targets:
238
+ rates[t] = {"name": currency_names.get(t, t), "rate": None}
239
+ return {
240
+ "base": base,
241
+ "base_name": currency_names.get(base, base),
242
+ "rates": rates,
243
+ "date": datetime.now().isoformat(),
244
+ "source": "macro_monitor_db"
245
+ }
246
+
247
+ async def get_economic_calendar(
248
+ self,
249
+ start_date: Optional[str] = None,
250
+ end_date: Optional[str] = None,
251
+ country: str = "CN"
252
+ ) -> List[Dict[str, Any]]:
253
+ """
254
+ 获取经济日历
255
+
256
+ Args:
257
+ start_date: 开始日期
258
+ end_date: 结束日期
259
+ country: 国家代码
260
+
261
+ Returns:
262
+ 经济事件列表
263
+ """
264
+ try:
265
+ # 尝试从 global_macro_data 获取经济日历数据
266
+ if start_date and end_date:
267
+ sql = """
268
+ SELECT indicator_code, indicator_name, data_value, period, publish_date
269
+ FROM global_macro_data
270
+ WHERE period BETWEEN %s AND %s
271
+ ORDER BY period DESC
272
+ LIMIT 50
273
+ """
274
+ rows = execute_local_query('macro', sql, (start_date, end_date))
275
+ else:
276
+ sql = """
277
+ SELECT indicator_code, indicator_name, data_value, period, publish_date
278
+ FROM global_macro_data
279
+ ORDER BY period DESC
280
+ LIMIT 20
281
+ """
282
+ rows = execute_local_query('macro', sql, ())
283
+ if rows:
284
+ return [
285
+ {
286
+ "period": str(r['period']),
287
+ "event": r['indicator_name'],
288
+ "value": float(r['data_value']) if r['data_value'] else None,
289
+ "publish_date": str(r['publish_date']) if r.get('publish_date') else None,
290
+ "country": country,
291
+ }
292
+ for r in rows
293
+ ]
294
+ return []
295
+ except Exception as e:
296
+ logger.error(f"获取经济日历失败: {e}")
297
+ return []
298
+
299
+ async def get_bond_yield(self, bond_type: str = "10Y") -> Dict[str, Any]:
300
+ """
301
+ 获取债券收益率
302
+
303
+ Args:
304
+ bond_type: 债券期限 (2Y, 5Y, 10Y, 30Y)
305
+
306
+ Returns:
307
+ 债券收益率数据
308
+ """
309
+ bond_info = {
310
+ "2Y": {"name": "2年期国债收益率", "indicator": "国债收益率2Y"},
311
+ "5Y": {"name": "5年期国债收益率", "indicator": "国债收益率5Y"},
312
+ "10Y": {"name": "10年期国债收益率", "indicator": "国债收益率10Y"},
313
+ "30Y": {"name": "30年期国债收益率", "indicator": "国债收益率30Y"},
314
+ }
315
+
316
+ info = bond_info.get(bond_type, {"name": bond_type, "indicator": bond_type})
317
+
318
+ try:
319
+ sql = """
320
+ SELECT indicator_code, indicator_name, data_value, period, publish_date
321
+ FROM cn_macro_data
322
+ WHERE indicator_code = %s
323
+ ORDER BY period DESC
324
+ LIMIT 1
325
+ """
326
+ rows = execute_local_query('macro', sql, (info['indicator'],))
327
+ if rows:
328
+ r = rows[0]
329
+ return {
330
+ "bond_type": bond_type,
331
+ "name": info['name'],
332
+ "yield": float(r['data_value']) if r['data_value'] else None,
333
+ "period": str(r['period']),
334
+ "publish_date": str(r['publish_date']) if r.get('publish_date') else None,
335
+ "source": "macro_monitor_db"
336
+ }
337
+ return {"error": f"未找到债券收益率 {bond_type}", "bond_type": bond_type}
338
+ except Exception as e:
339
+ logger.error(f"获取债券收益率 {bond_type} 失败: {e}")
340
+ return {"error": f"数据库查询失败: {str(e)}", "bond_type": bond_type}
341
+
342
+ async def get_cn_credit_data(
343
+ self,
344
+ data_type: str = "社融"
345
+ ) -> Dict[str, Any]:
346
+ """
347
+ 获取中国信用数据
348
+
349
+ Args:
350
+ data_type: 数据类型 (社融, M2, 人民币贷款)
351
+
352
+ Returns:
353
+ 信用数据
354
+ """
355
+ indicator_map = {
356
+ "社融": "社会融资规模",
357
+ "M2": "M2",
358
+ "人民币贷款": "人民币贷款",
359
+ }
360
+
361
+ indicator_name = indicator_map.get(data_type, data_type)
362
+
363
+ try:
364
+ sql = """
365
+ SELECT indicator_code, indicator_name, data_value, period, publish_date
366
+ FROM cn_macro_data
367
+ WHERE indicator_name = %s
368
+ ORDER BY period DESC
369
+ LIMIT 1
370
+ """
371
+ rows = execute_local_query('macro', sql, (indicator_name,))
372
+ if rows:
373
+ r = rows[0]
374
+ return {
375
+ "type": data_type,
376
+ "name": r['indicator_name'],
377
+ "value": float(r['data_value']) if r['data_value'] else None,
378
+ "period": str(r['period']),
379
+ "publish_date": str(r['publish_date']) if r.get('publish_date') else None,
380
+ "source": "macro_monitor_db"
381
+ }
382
+ return {"error": f"未找到信用数据 {data_type}", "data_type": data_type}
383
+ except Exception as e:
384
+ logger.error(f"获取信用数据 {data_type} 失败: {e}")
385
+ return {"error": f"数据库查询失败: {str(e)}", "data_type": data_type}
386
+
387
+ def list_tools(self) -> List[Dict[str, Any]]:
388
+ """列出所有可用工具"""
389
+ return [
390
+ {
391
+ "name": "get_macro_indicator",
392
+ "description": "获取宏观指标数据",
393
+ "parameters": {
394
+ "indicator_code": "指标代码 (GDP_YOY, CPI, PMI_MFG, SHIBOR_3M等)",
395
+ "country": "国家代码 (CN, US, EU)"
396
+ }
397
+ },
398
+ {
399
+ "name": "get_macro_history",
400
+ "description": "获取宏观指标历史数据",
401
+ "parameters": {
402
+ "indicator_code": "指标代码",
403
+ "months": "历史月数 (默认12)"
404
+ }
405
+ },
406
+ {
407
+ "name": "list_indicators",
408
+ "description": "列出可用指标",
409
+ "parameters": {
410
+ "category": "指标类别 (可选)"
411
+ }
412
+ },
413
+ {
414
+ "name": "get_interest_rates",
415
+ "description": "获取利率数据",
416
+ "parameters": {
417
+ "rate_type": "利率类型 (LPR, MLF, SHIBOR_3M等)",
418
+ "country": "国家代码"
419
+ }
420
+ },
421
+ {
422
+ "name": "get_currency_rates",
423
+ "description": "获取汇率数据",
424
+ "parameters": {
425
+ "base": "基准货币",
426
+ "target": "目标货币"
427
+ }
428
+ },
429
+ {
430
+ "name": "get_economic_calendar",
431
+ "description": "获取经济日历",
432
+ "parameters": {
433
+ "start_date": "开始日期",
434
+ "end_date": "结束日期",
435
+ "country": "国家代码"
436
+ }
437
+ },
438
+ {
439
+ "name": "get_bond_yield",
440
+ "description": "获取债券收益率",
441
+ "parameters": {
442
+ "bond_type": "债券期限 (2Y, 5Y, 10Y, 30Y)"
443
+ }
444
+ },
445
+ {
446
+ "name": "get_cn_credit_data",
447
+ "description": "获取中国信用数据",
448
+ "parameters": {
449
+ "data_type": "数据类型 (社融, M2, 人民币贷款)"
450
+ }
451
+ },
452
+ ]