yourdaylight-tushare-plugin-builder
npx skills add https://smithery.ai
Agent 安装分布
Skill 文档
ç®ç
å° Tushare ææ¡£ URL 转æ¢ä¸ºæ¬ä»åºçç产级æä»¶ï¼å
嫿°æ®æ½åãClickHouse è¡¨ç»æãæ¥è¯¢æå¡ï¼ä»¥å坿µè¯ç curl 示ä¾ã
使¶ä½¿ç¨
- ç¨æ·æä¾ Tushare ææ¡£ URL æé¡µé¢å 容ï¼è¦æ±çææä»¶ã
- ç¨æ·éè¦åºäºæä¸ª Tushare æ¥å£çææä»¶ + å ¥åº + service + Agent/MCP è°ç¨ã
- éªè¯å·²ææä»¶ï¼ç¨æ·è¦æ±æ£æ¥æä¸ªæä»¶æ¯å¦ç¬¦åè§èã
工使µç¨
1) æ¶éå¿ è¦è¾å ¥
- ç¡®ä¿ç¨æ·æä¾äº Tushare ææ¡£ URLãè¥æ æ³è®¿é®ï¼è¯·æ±æªå¾æå¤å¶çææ¡£å 容ã
- è¥æªæå®æä»¶åï¼è¯¢é®ç¨æ·ãä½¿ç¨ snake_case å½åï¼ä¸ç°æ
tushare_*æä»¶ä¿æä¸è´ã
2) ä»ææ¡£æå API è§æ ¼
- è§£ææ¥å£åç§°ãè¾å ¥åæ°ãè¾åºå段ã使ç¨è¯´æï¼é¢çéå¶ãåé¡µãæ°æ®ééå¶ï¼ã
- è®°å½å段å½åå·®å¼ï¼å¦
pct_changevspct_chgï¼åæé转æ¢ã
3) è§åæä»¶ç»æï¼åè references/plugin_conventions.mdï¼
- ç®å½ï¼
src/stock_datasource/plugins/<plugin_name>/ - æä»¶ï¼
__init__.pyãplugin.pyãextractor.pyãservice.pyãschema.jsonãconfig.jsonã<plugin_name>.md - ä»¥ç°æ
tushare_*æä»¶ä¸ºæ¨¡æ¿ã
4) å®ç° extractor
- 使ç¨
tushareSDKï¼API è°ç¨éç¨proxy_context()å 裹ã - å®ç°é¢çéå¶ãè¶ æ¶ãéè¯ï¼tenacityï¼ã
- æ ¹æ® API ç¹æ§æ¯æ
trade_dateæstart_date/end_dateã
5) å®ç° plugin
- å®ç°
extract_dataãvalidate_dataãtransform_dataãload_dataã - æå
¥åæ·»å
versionå_ingested_atåã - è½¬æ¢æ°å¼ç±»åï¼
trade_date转为Dateã
æä»¶åç±»ä¸è§è²
å¿ é¡»å®ç°ä»¥ä¸æ¹æ³æå®æä»¶çåç±»åè§è²ï¼
from stock_datasource.core.base_plugin import PluginCategory, PluginRole
def get_category(self) -> PluginCategory:
"""æä»¶åç±» - æå¸åºåå"""
return PluginCategory.CN_STOCK # æ HK_STOCK, INDEX, ETF_FUND, SYSTEM
def get_role(self) -> PluginRole:
"""æä»¶è§è²"""
return PluginRole.PRIMARY # æ BASIC, DERIVED, AUXILIARY
å类说æï¼
CN_STOCK: Aè¡ç¸å ³æ°æ®HK_STOCK: 港è¡ç¸å ³æ°æ®INDEX: ææ°ç¸å ³æ°æ®ETF_FUND: ETF/åºéç¸å ³æ°æ®SYSTEM: ç³»ç»æ°æ®ï¼å¦äº¤ææ¥åï¼
è§è²è¯´æï¼
PRIMARY: ä¸»æ°æ®ï¼å¦ daily è¡æ ï¼BASIC: åºç¡æ°æ®ï¼å¦ stock_basicï¼DERIVED: è¡çæ°æ®ï¼å¦å¤æå åï¼AUXILIARY: è¾ å©æ°æ®ï¼å¦ææ°æéï¼
ä¾èµé ç½®
å¨ plugin.py ä¸å®ç°ä¾èµæ¹æ³ï¼ä¸æ¯å¨ config.json ä¸é
ç½®ï¼ï¼
def get_dependencies(self) -> List[str]:
"""å¿
é¡»ä¾èµ - è¿äºæä»¶çæ°æ®å¿
é¡»å卿è½è¿è¡å½åæä»¶ã
ä¾å¦ï¼tushare_daily ä¾èµ tushare_stock_basic æä¾è¡ç¥¨ä»£ç å表ã
"""
return ["tushare_stock_basic"]
def get_optional_dependencies(self) -> List[str]:
"""å¯éä¾èµ - 忥䏻æä»¶æ¶é»è®¤ä¼åæ¥è¿äºä¾èµï¼ç¨æ·å¯éæ©ç¦ç¨ã
ä¾å¦ï¼tushare_daily å¯é忥 tushare_adj_factor 夿å åã
"""
return ["tushare_adj_factor"]
ä¾èµè§åï¼
- å¿ é¡»ä¾èµï¼å¨è¿è¡å½åæä»¶åï¼ä¼æ£æ¥ä¾èµæä»¶è¡¨ä¸æ¯å¦ææ°æ®
- å¯éä¾èµï¼å端å±ç¤ºæ¶ä¼æ¾ç¤ºå¯å¾éçå ³èæä»¶ï¼é»è®¤å¾é
6) å®ç° service æ¥è¯¢
- è³å°æä¾ä¸ä¸ªæ¥æèå´æ¥è¯¢åä¸ä¸ªææ°æ°æ®æ¥è¯¢ã
- å¿ é¡»ä½¿ç¨åæ°åæ¥è¯¢ï¼ç¦æ¢åç¬¦ä¸²æ¼æ¥ï¼ã
- è¿å JSON å¯åºååç»æã
7) å®ä¹ schema/config
schema.jsonï¼ä½¿ç¨ReplacingMergeTreeï¼partition_by为toYYYYMM(trade_date)ï¼order_by为主é®ãconfig.jsonï¼å å«å®æ´çæä»¶é ç½®ã
config.json 宿´ç»æ
{
"enabled": true,
"rate_limit": 120,
"timeout": 30,
"retry_attempts": 3,
"description": "æä»¶æè¿°",
"schedule": {
"frequency": "daily",
"time": "18:00",
"day_of_week": "monday"
},
"parameters": {
"max_empty_days": 5,
"validate_prices": true
},
"parameters_schema": {
"trade_date": {
"type": "string",
"format": "date",
"required": true,
"description": "Trade date in YYYYMMDD format"
}
}
}
åæ®µè¯´æï¼
| åæ®µ | å¿ é | 说æ |
|---|---|---|
enabled |
æ¯ | æ¯å¦å¯ç¨æä»¶ |
rate_limit |
æ¯ | API è°ç¨é¢çéå¶ï¼æ¬¡/åéï¼ |
timeout |
æ¯ | 请æ±è¶ æ¶æ¶é´ï¼ç§ï¼ |
retry_attempts |
æ¯ | éè¯æ¬¡æ° |
description |
æ¯ | æä»¶æè¿° |
schedule |
å¦ | è°åº¦é ç½® |
schedule.frequency |
å¦ | è°åº¦é¢çï¼daily æ weeklyï¼é»è®¤ daily |
schedule.time |
å¦ | æ§è¡æ¶é´ï¼æ ¼å¼ HH:MMï¼é»è®¤ 18:00 |
schedule.day_of_week |
å¦ | ä»
weekly æ¶ææï¼å¦ monday |
parameters |
å¦ | æä»¶ç¹å®åæ° |
parameters_schema |
æ¯ | åæ° schemaï¼ç¨äºéªè¯åå端å±ç¤º |
注æï¼ä¾èµé
ç½®ï¼dependenciesãoptional_dependenciesï¼ä¸å¨ config.json ä¸å®ä¹ï¼èæ¯éè¿ plugin.py ä¸ç get_dependencies() å get_optional_dependencies() æ¹æ³å®ç°ã
8) å建 ClickHouse 表
- æ ¹æ®
schema.jsonçæCREATE TABLESQLã - 使ç¨èæ¬ï¼
# ä» çæ SQL python .codebuddy/skills/tushare-plugin-builder/scripts/generate_create_table_sql.py \ src/stock_datasource/plugins/<plugin_name>/schema.json # çæå¹¶æ§è¡ python .codebuddy/skills/tushare-plugin-builder/scripts/generate_create_table_sql.py \ src/stock_datasource/plugins/<plugin_name>/schema.json --execute
9) éªè¯æ°æ®åºè¿æ¥
- æ§è¡åå
éªè¯ ClickHouse è¿æ¥æ¯å¦æ£å¸¸ï¼
# æµè¯è¿æ¥ python .codebuddy/skills/tushare-plugin-builder/scripts/verify_clickhouse_connection.py # ååºææè¡¨ python .codebuddy/skills/tushare-plugin-builder/scripts/verify_clickhouse_connection.py --list # éªè¯æå®è¡¨æ¯å¦åå¨ python .codebuddy/skills/tushare-plugin-builder/scripts/verify_clickhouse_connection.py --table <table_name>
10) è¿è¡æ°æ®æåæµè¯
- æ§è¡æä»¶æåå¹¶å卿 ·æ¬æ°æ®ï¼å¦æä¸äº¤ææ¥ï¼ã
- 代çé
ç½®ï¼è¿è¡åç¡®ä¿
runtime_config.jsonä¸ä»£ç设置æ£ç¡®ã - 使ç¨èæ¬ï¼
# è¿è¡æä»¶å¹¶éªè¯ python .codebuddy/skills/tushare-plugin-builder/scripts/run_plugin_test.py \ <plugin_name> --date 20250110 --verify - æä½¿ç¨æ¨¡åæ¹å¼ï¼
python -m stock_datasource.plugins.<plugin_name>.plugin --date 20250110
11) éªè¯ ClickHouse æ°æ®
- æ¥è¯¢ ClickHouse ç¡®è®¤æ°æ®å·²åå¨ï¼
# 使ç¨èæ¬éªè¯ python .codebuddy/skills/tushare-plugin-builder/scripts/verify_clickhouse_connection.py \ --table <table_name> --date 20250110 - ææå¨æ¥è¯¢ï¼
SELECT count(*), min(trade_date), max(trade_date) FROM <table_name> WHERE trade_date = '2025-01-10';
12) æµè¯ HTTP æå¡ç«¯ç¹
- è¥æªè¿è¡ï¼å¯å¨ HTTP æå¡ï¼
python -m stock_datasource.services.http_server - 使ç¨èæ¬ï¼
# ååºææ API è·¯ç± python .codebuddy/skills/tushare-plugin-builder/scripts/verify_service_http.py --list # æµè¯æå®æå¡æ¹æ³ python .codebuddy/skills/tushare-plugin-builder/scripts/verify_service_http.py \ --service <service_name> \ --method get_by_date_range \ --params '{"ts_code":"XXX","start_date":"20250101","end_date":"20250110"}' # ä» çæ curl å½ä»¤ python .codebuddy/skills/tushare-plugin-builder/scripts/verify_service_http.py \ --service <service_name> --method get_latest --params '{}' --curl
13) æµè¯ MCP å·¥å ·å¯ç¨æ§
- è¥æªè¿è¡ï¼å¯å¨ MCP æå¡ï¼
python -m stock_datasource.services.mcp_server - 使ç¨èæ¬ï¼
# ååºææ MCP å·¥å · python .codebuddy/skills/tushare-plugin-builder/scripts/verify_mcp_tool.py --list # æç´¢ç¸å ³å·¥å · python .codebuddy/skills/tushare-plugin-builder/scripts/verify_mcp_tool.py --pattern <service_name> # éªè¯æå®å·¥å · python .codebuddy/skills/tushare-plugin-builder/scripts/verify_mcp_tool.py --tool <tool_name>
14) æµè¯ Agent éæ
- å Orchestrator åéèªç¶è¯è¨æ¥è¯¢ï¼åºè°ç¨æ°æä»¶ç serviceã
- ç¤ºä¾æé®ï¼”æ¥è¯¢ XXX ææ°æè¿ä¸å¨çè¡æ æ°æ®”
- éªè¯ï¼
- Agent æ£ç¡®è¯å«æå¾å¹¶éæ©å·¥å ·ã
- å·¥å ·è°ç¨ä» ClickHouse è¿åæ°æ®ã
- ååºæ ¼å¼ååè¿åç»ç¨æ·ã
15) éªè¯éæç¹
- Service èªå¨åç°ï¼æ éé¢å¤æå¨æ³¨åã
- MCP/HTTP ç«¯ç¹æçæçè·¯ç±å·¥ä½ã
éªè¯èæ¬è¯´æ
æ¬ skill æä¾ä»¥ä¸éªè¯èæ¬ï¼ä½äº scripts/ ç®å½ï¼ï¼
| èæ¬ | ç¨é |
|---|---|
validate_plugin.py |
综åéªè¯æä»¶æ¯å¦ç¬¦åè§è |
verify_clickhouse_connection.py |
æµè¯æ°æ®åºè¿æ¥ãååºè¡¨ãéªè¯æ°æ® |
generate_create_table_sql.py |
æ ¹æ® schema.json çæå»ºè¡¨ SQL |
run_plugin_test.py |
è¿è¡æä»¶ ETL å¹¶éªè¯å ¥åº |
verify_service_http.py |
æµè¯ HTTP æå¡ç«¯ç¹ |
verify_mcp_tool.py |
éªè¯ MCP å·¥å ·æ³¨åç¶æ |
æä»¶éªè¯æµç¨
å½ç¨æ·è¦æ±éªè¯å·²ææä»¶ï¼æ 论æ¯èªå·±ç¼åè¿æ¯çæçï¼ï¼æ§è¡ä»¥ä¸æ¥éª¤ï¼
1) è¿è¡ç»¼åéªè¯èæ¬
# éªè¯å个æä»¶
python .codebuddy/skills/tushare-plugin-builder/scripts/validate_plugin.py <plugin_name>
# æ¾ç¤ºæææ£æ¥è¯¦æ
python .codebuddy/skills/tushare-plugin-builder/scripts/validate_plugin.py <plugin_name> --verbose
# ååºææå¯ç¨æä»¶
python .codebuddy/skills/tushare-plugin-builder/scripts/validate_plugin.py --list
# éªè¯æææä»¶
python .codebuddy/skills/tushare-plugin-builder/scripts/validate_plugin.py --all
2) éªè¯æ£æ¥é¡¹
validate_plugin.py ä¼èªå¨æ£æ¥ä»¥ä¸å
容ï¼
æä»¶ç»ææ£æ¥ï¼
-
__init__.pyåå¨ä¸å¯¼åº Plugin/Service ç±» -
plugin.pyåå¨ä¸ç»§æ¿ BasePlugin -
extractor.pyåå¨ä¸ä½¿ç¨ proxy_context -
service.pyåå¨ä¸ç»§æ¿ BaseService -
schema.jsonåå¨ä¸å å«å¿ éåæ®µ -
config.jsonåå¨ä¸å å«å¿ éé ç½®
代ç è§èæ£æ¥ï¼
- plugin.py å®ç°äº extract/validate/transform/load æ¹æ³
- plugin.py æ·»å äº version å _ingested_at ç³»ç»å
- plugin.py å®ç°äº get_category() è¿åæ£ç¡®ç PluginCategory
- plugin.py å®ç°äº get_role() è¿åæ£ç¡®ç PluginRole
- plugin.py å®ç°äº get_dependencies()ï¼è¿å空å表æä¾èµæä»¶åï¼
- plugin.py å®ç°äº get_optional_dependencies()ï¼å¦æå¯éä¾èµï¼
- extractor.py 使ç¨äºéè¯é»è¾ï¼tenacityï¼
- service.py 使ç¨åæ°å SQLï¼æ SQL æ³¨å ¥é£é©ï¼
- service.py å 嫿¥è¯¢æ¹æ³ï¼get_/query_/fetch_*ï¼
Schema è§èæ£æ¥ï¼
- å å« table_nameãcolumnsãengineãorder_by
- ä½¿ç¨ ReplacingMergeTree 弿
- å å« version å _ingested_at ç³»ç»å
- 设置äºååºçç¥ï¼partition_byï¼
è¿è¡æ¶æ£æ¥ï¼
- 模å坿£å¸¸å¯¼å ¥
- æ°æ®åºè¡¨å·²å建
- è¡¨ä¸ææ°æ®ï¼å¦å·²è¿è¡è¿ ETLï¼
3) å¤çéªè¯ç»æ
æ ¹æ®éªè¯ç»æéåè¡å¨ï¼
â éè¿ï¼æä»¶ç¬¦åè§èï¼å¯è¿è¡ä¸ä¸æ¥æµè¯ã
â ï¸ è¦åï¼æä»¶å¯è¿è¡ä½å卿½å¨é®é¢ï¼å»ºè®®ä¿®å¤ï¼
- 缺å°éè¯é»è¾ â æ·»å tenacity è£ é¥°å¨
- æªæ£æµå°åæ°åæ¥è¯¢ â æ£æ¥ SQL æ¯å¦ä½¿ç¨
%(param)s - 表为空 â è¿è¡æ°æ®æåæµè¯
â å¤±è´¥ï¼æä»¶åå¨ä¸¥éé®é¢ï¼å¿ 须修å¤ï¼
- SQL æ³¨å ¥é£é© â æ¹ç¨åæ°åæ¥è¯¢
- 缺å°å¿ éæä»¶ â è¡¥å 缺失æä»¶
- æªä½¿ç¨ proxy_context â API è°ç¨å°å¤±è´¥
- 缺å°ç³»ç»å â å¨ schema.json å plugin.py 䏿·»å
4) 端å°ç«¯éªè¯
éè¿åºç¡æ£æ¥åï¼æ§è¡å®æ´æµè¯æµç¨ï¼
# 1. éªè¯æ°æ®åºè¿æ¥
python .codebuddy/skills/tushare-plugin-builder/scripts/verify_clickhouse_connection.py
# 2. 建表ï¼å¦æè¡¨ä¸åå¨ï¼
python .codebuddy/skills/tushare-plugin-builder/scripts/generate_create_table_sql.py \
src/stock_datasource/plugins/<plugin_name>/schema.json --execute
# 3. è¿è¡ ETL å¹¶éªè¯å
¥åº
python .codebuddy/skills/tushare-plugin-builder/scripts/run_plugin_test.py \
<plugin_name> --date 20250110 --verify
# 4. æµè¯ HTTP æå¡
python .codebuddy/skills/tushare-plugin-builder/scripts/verify_service_http.py \
--service <service_name> --method get_latest --params '{}'
# 5. æµè¯ MCP å·¥å
·
python .codebuddy/skills/tushare-plugin-builder/scripts/verify_mcp_tool.py \
--pattern <service_name>
è¾åºæ£æ¥æ¸ å
- æä»¶ç®å½å·²å建ï¼å 嫿æå¿ éæä»¶ã
- Extractor 使ç¨
proxy_context()åtushareSDKã - Plugin å®ç°äº
get_category()åget_role()æ¹æ³ã - Plugin å®ç°äº
get_dependencies()åget_optional_dependencies()æ¹æ³ã - Service 使ç¨åæ°å SQLã
- Schema å¹é Tushare è¾åºå段ã
- Config å å«é¢çéå¶ãschedule ååæ° schemaã
- ClickHouse 表已åå»ºï¼æ°æ®å·²å ¥åºã
- éè¿ SQL æ¥è¯¢éªè¯ ClickHouse ä¸ææ°æ®ã
- HTTP æå¡ç«¯ç¹å·²éè¿ curl æµè¯ã
- MCP å·¥å ·å·²æ³¨åä¸å¯è°ç¨ã
- Agent å¯éè¿èªç¶è¯è¨æ¥è¯¢è°ç¨è¯¥æå¡ã