news 2026/9/17 15:58:19

k-skill korean-stock-search 实战指南:无需 KRX_API_KEY 的 KRX 韩国股票查询与代理实现剖析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
k-skill korean-stock-search 实战指南:无需 KRX_API_KEY 的 KRX 韩国股票查询与代理实现剖析

k-skill korean-stock-search 实战指南:无需 KRX_API_KEY 的 KRX 韩国股票查询与代理实现剖析

【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill

本文以 k-skill 仓库中的korean-stock-search技能说明文档为核心,完整讲解如何通过 k-skill-proxy 的三个 HTTP 端点完成 KRX 上市股票搜索、个股基本资讯与每日行情查询,并结合代理服务器源码剖析参数校验、结果打分、缓存策略与上游故障处理机制。读完后你可以直接用 curl 调通全部端点,并掌握在 Agent 场景下如何正确解释结果与处理degradednot_found等失败状态。

技能定位与应用边界

korean-stock-search是 k-skill("한국인을 위한 스킬 모음집")中面向金融数据查询的技能。它的默认行为是向https://k-skill-proxy.nomadamas.org/v1/korean-stock/...发起请求,完成三类只读查询:KRX 上市股票搜索(search)、个股基本资讯(base-info)、个股每日行情(trade-info)。

技能说明书(korean-stock-search/instruction.md)明确了适用与不适用场景:

适合使用的典型请求:

  • "삼성전자 종목코드랑 시장구분 찾아줘"(找一下三星电子的证券代码和市场区分)
  • "005930 기본정보 보여줘"(查看 005930 的基本资讯)
  • "SK하이닉스 20260408 종가/거래량 알려줘"(查询 SK 海力士 20260408 的收盘价与成交量)
  • "KOSDAQ 에서 알테오젠 시세 확인해줘"(在 KOSDAQ 市场确认 Alteogen 的行情)

明确不属于本技能范围的场景:

  • 美国/日本/虚拟资产等非韩国股票查询
  • 实时成交(체결)、买卖盘口(호가)、分钟 K 线查询
  • 财务报表与公告原文分析
  • 投资建议或买入推荐

skill.json中的元数据也印证了这一定位:profiles 为proxylookup,分类finance,地区ko-KR(见 korean-stock-search/skill.json)。

核心设计:密钥集中在代理层,用户零凭证

该技能最关键的设计是用户不需要申请KRX_API_KEY,也不需要本地安装 MCP 服务器。upstream 方案设计参考了开源项目jjlabsio/korea-stock-mcp,但用户侧被完全屏蔽了密钥管理:KRX_API_KEY只在 k-skill-proxy 服务器上配置与注入。

从代理源码看,这一点在三个层面得到确认:

  1. 代理从进程环境变量读取密钥:config.krxApiKey = trimOrNull(env.KRX_API_KEY)(packages/k-skill-proxy/src/server.js#L264);
  2. 每个端点在命中缓存后都会检查config.krxApiKey,若缺失直接返回 503upstream_not_configured(packages/k-skill-proxy/src/server.js#L5337-L5350);
  3. 底层 KRX 请求函数在发请求前再次兜底校验密钥,同样抛出 503(packages/k-skill-proxy/src/krx-stock.js#L126-L132)。

代理基地址的选取规则:如果设置了KSKILL_PROXY_BASE_URL环境变量,则使用其值;否则回退到默认地址https://k-skill-proxy.nomadamas.org。此外不需要任何客户端 API 层——直接向代理发 HTTP GET 请求即可。

输入参数详解

技能定义的全部输入如下,参数校验逻辑与默认值均可在代理源码中逐一对应:

参数说明校验规则与默认值(源自源码)
q股票名或证券代码搜索词,仅search端点使用必填;缺失时抛错返回 400
market市场区分:KOSPI|KOSDAQ|KONEXbase-info/trade-info必填;search可选,缺省时并行查询全部三个市场
code证券代码,通常为 6 位短代码(如005930base-info/trade-info必填;支持逗号分隔的多代码入参,取第一个
bas_dd基准日,格式YYYYMMDD可选;缺省时取 KST(Asia/Seoul)当天日期;若传入值不是 8 位数字则 400
limit搜索结果条数默认 10,范围 1~20,越界返回 400

参数归一化函数位于 packages/k-skill-proxy/src/server.js#L1447-L1498:

  • normalizeKoreanStockDatebas_dd为空时用getCurrentKstDate()(基于Intl.DateTimeFormat+Asia/Seoul时区,见 packages/k-skill-proxy/src/krx-stock.js#L50-L59)计算 KST 当天,然后强制匹配^\d{8}$
  • normalizeKoreanStockSearchQuery:接受qquery别名,bas_dd/basDd/date均可,limit默认 10 且上限 20;
  • normalizeKoreanStockLookupQuerycode支持codes/codeList/stockCode/stock_code别名,逗号分隔并去重后取第一项,用于base-infotrade-info

前置条件(Prerequisites):无。使用者无需准备KRX_API_KEY,upstream 密钥仅在代理服务器侧注入。

三个受支持的端点与 curl 示例

1. 股票搜索

GET /v1/korean-stock/search?q={검색어}&bas_dd={YYYYMMDD}
curl -fsS --get 'https://k-skill-proxy.nomadamas.org/v1/korean-stock/search' \ --data-urlencode 'q=삼성전자' \ --data-urlencode 'bas_dd=20260408'

2. 个股基本资讯

GET /v1/korean-stock/base-info?market={KOSPI|KOSDAQ|KONEX}&code={종목코드}&bas_dd={YYYYMMDD}
curl -fsS --get 'https://k-skill-proxy.nomadamas.org/v1/korean-stock/base-info' \ --data-urlencode 'market=KOSPI' \ --data-urlencode 'code=005930' \ --data-urlencode 'bas_dd=20260408'

3. 个股每日行情

GET /v1/korean-stock/trade-info?market={KOSPI|KOSDAQ|KONEX}&code={종목코드}&bas_dd={YYYYMMDD}
curl -fsS --get 'https://k-skill-proxy.nomadamas.org/v1/korean-stock/trade-info' \ --data-urlencode 'market=KOSPI' \ --data-urlencode 'code=005930' \ --data-urlencode 'bas_dd=20260408'

注意:中文/韩文等非 ASCII 搜索词务必使用--data-urlencode做 URL 编码,这在代理测试中也有覆盖——测试用例会用%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90("삼성전자" 的编码形式)注入请求(packages/k-skill-proxy/test/server.test.js#L2332-L2341)。

响应结构逐字段解读

三个端点共享统一响应骨架:业务数据(items/item)+ 回显的query+ 代理元信息proxyproxy.cache.hit标识本次是缓存命中还是实时查询,ttl_ms为缓存 TTL(默认 300000 毫秒)。

搜索响应

{ "items": [ { "market": "KOSPI", "code": "005930", "standard_code": "KR7005930003", "name": "삼성전자", "short_name": "삼성전자", "english_name": "Samsung Electronics", "listed_at": "1975-06-11" } ], "query": { "q": "삼성전자", "bas_dd": "20260408", "limit": 10 }, "proxy": { "name": "k-skill-proxy", "cache": { "hit": false, "ttl_ms": 300000 } } }

基本资讯响应

{ "item": { "market": "KOSPI", "code": "005930", "standard_code": "KR7005930003", "name": "삼성전자", "short_name": "삼성전자", "english_name": "Samsung Electronics", "security_group": "주권", "section_type": "대형주", "stock_certificate_type": "보통주", "par_value": 100, "listed_shares": 5969782550 }, "query": { "market": "KOSPI", "code": "005930", "bas_dd": "20260408" }, "proxy": { "name": "k-skill-proxy", "cache": { "hit": false, "ttl_ms": 300000 } } }

每日行情响应

{ "item": { "market": "KOSPI", "code": "005930", "standard_code": "KR7005930003", "base_date": "20260408", "name": "삼성전자", "close_price": 84000, "change_price": 1000, "fluctuation_rate": 1.2, "open_price": 83000, "high_price": 84500, "low_price": 82800, "trading_volume": 12345678, "trading_value": 1030000000000, "market_cap": 500000000000000 }, "query": { "market": "KOSPI", "code": "005930", "bas_dd": "20260408" }, "proxy": { "name": "k-skill-proxy", "cache": { "hit": false, "ttl_ms": 300000 } } }

行情字段由normalizeTradeItem从 KRX 原始字段映射而来:TDD_CLSPRCclose_priceCMPPREVDD_PRCchange_priceFLUC_RTfluctuation_rateTDD_OPNPRC/TDD_HGPRC/TDD_LWPRC→开高低、ACC_TRDVOL/ACC_TRDVAL→量额、MKTCAPmarket_cap(packages/k-skill-proxy/src/krx-stock.js#L87-L116)。映射时对数字做了去千分位逗号的解析(parseNumber),保证返回的是纯数字而非字符串。

Upstream 实现:KRX API 如何被真正调用

代理到 KRX 的完整数据流在 packages/k-skill-proxy/src/krx-stock.js 中,要点如下:

按市场分表的上游 URL。KRX 的 dbg 数据接口为三个市场提供了不同路径,源码中维护了静态映射(packages/k-skill-proxy/src/krx-stock.js#L5-L15):

市场基本资讯 upstream每日行情 upstream
KOSPIstk_isu_base_infostk_bydd_trd
KOSDAQksq_isu_base_infoksq_bydd_trd
KONEXknx_isu_base_infoknx_bydd_trd

三者均挂在data-dbg.krx.co.kr/svc/apis/sto/下,请求仅带basDd查询参数,并在请求头中以AUTH_KEY携带 API 密钥。

搜索是"全市场快照 + 本地打分",而非服务端模糊查询。searchStocks对选定市场(未指定market时为 KOSPI/KOSDAQ/KONEX 全部三个)用Promise.allSettled并发拉取该市场当日的基本资讯快照,然后在本地执行匹配打分(packages/k-skill-proxy/src/krx-stock.js#L264-L325):

  • 搜索词与code/standard_code/name/short_name/english_name任一字段完全相等(忽略大小写)得 100 分;
  • 按空白切分后每个 token 都出现在某个字段中得 50 分;
  • 未命中得 -1 分并过滤,最后按分数降序、同分按韩文localeCompare排序后截取前limit条。

这种设计解释了为什么搜索是确定性的、可缓存的,也解释了文档中"종목명이 모호하면 먼저search로 시장/종목코드를 좁힌 뒤"(股票名模糊时先收窄)这一响应策略的必要性。

degraded 的部分故障语义。只要有一个市场拉取成功,search就返回 200,并附带upstream: { degraded: true, requested_markets, successful_markets, failed_markets };只有全部市场都失败时才向上抛错、由路由层转成 502。failed_markets中每一项包含code/status_code/message序列化信息(serializeKrxError)。代理测试对这一行为有专门断言:当另一个市场失败时,search 响应会带出 degraded 元数据(packages/k-skill-proxy/test/server.test.js#L2477)。

trade-info 的短代码回退匹配。fetchTradeInfo先用 6 位短代码(ISU_SRT_CD)直接匹配当日行情快照;若无直接命中,会再拉一次基本资讯快照,用 12 位标准代码(ISU_CD,如KR7005930003)做二次匹配,并把基本资讯中的名称、上市股数等补进行情结果(packages/k-skill-proxy/src/krx-stock.js#L168-L191)。这层回退让"只有短代码的用户"也能查到行情。

网络层细节。krxRequest通过fetchWithRetry发起请求,超时设为 20 秒(AbortSignal.timeout(20000));上游返回非 2xx 时抛upstream_error(502),响应体缺少OutBlock_1数组时抛krx_api_error(502)——KRX 的数据就装在OutBlock_1里。

缓存策略与失败模式

缓存键与命中回显。每个路由用makeCacheKey({ route, ...参数 })生成缓存键(search 会把q转小写后再拼入键,保证大小写不敏感的命中)。命中缓存的响应会带proxy.cache.hit=true。测试中验证了带空格/别名的两种请求(q=vsquery=+date=)会归一化为同一查询(packages/k-skill-proxy/test/server.test.js#L2332-L2341)。

degraded 响应不进缓存。缓存层显式拒绝写入errorupstream.degraded=true的载荷(cache.set返回 false,见 packages/k-skill-proxy/test/server.test.js#L247-L251);search 路由也只有在!result.upstream?.degraded时才写缓存(packages/k-skill-proxy/src/server.js#L5389-L5395)。此外测试还覆盖了按客户端 IP(解析cf-connecting-ipx-forwarded-for链)的限流行为,超限返回rate_limited

完整失败模式对照表(与文档 Failure modes 一节一致,且全部可在路由源码中对应到具体分支):

条件HTTP 状态error 标识源码位置
q/market/code/bas_dd格式错误,或limit越界400bad_requestserver.js#L5306-L5314
代理未配置KRX_API_KEY503upstream_not_configuredserver.js#L5337-L5350
部分市场 upstream 失败200upstream.degraded=true+failed_marketskrx-stock.js#L315-L322
全部市场 upstream 失败 / KRX 返回错误502upstream_error/krx_api_errorkrx-stock.js#L143-L156
该基准日/市场下找不到该股票404not_foundserver.js#L6324-L6330

特别注意 404 分支的两个细节:base-info的提示语是"기준일 X 에 Y 시장 종목 Z 을(를) 찾지 못했습니다",而trade-info的提示语额外说明了"휴장일이거나 데이터가 아직 없을 수 있습니다"(可能是休市日或数据尚未生成)(server.js#L6417-L6423)。

响应策略与输出规范(Agent 必读)

技能文档对"拿到数据之后怎么讲"给出了明确的行为规范,这部分是技能质量的核心:

  • 查询顺序:股票名模糊时先走search收窄市场/证券代码,再进入base-infotrade-info
  • 部分故障要如实说明:看到upstream.degraded=truefailed_markets时,要在答案中一并说明哪些市场查询失败;
  • 不要过度承诺时效trade-info是日别 snapshot,不能表述为实时盘口/成交;
  • 休市日处理bas_dd为休市日或盘前时该日期可能无数据,应回退到最近营业日重试;此时trade-info可能以 404not_found而非 502 结束;
  • 数字呈现:用 원/주/억/조 等易读单位简短解读,同时保留原始数字;
  • 免责声明:答案末尾简短附上"KRX 공식 데이터 기준 / 투자 조언 아님"(以 KRX 官方数据为准 / 非投资建议)。

紧凑答案要求(Keep the answer compact):答案只保留股票名/市场/证券代码、基准日、收盘价/涨跌幅/成交量/市值;仅在需要时补充上市日/上市股数/面值;出现多个候选时只展示前 3~5 个,交由用户选择。

完成判据(Done when):模糊搜索词已先经search收窄;已按需用base-infotrade-info整理核心数值;全程保持了"用户无需KRX_API_KEY也能查询"的体验;已简短标注数据出处。

合规与法律边界

SKILL.md 声明本技能只读查询专用(read-only 조회 전용),且与 KRX、交易所、上市公司或任何数据提供方无官方关系。korean-stock-search/references/DISCLAIMER.md 进一步约束了使用边界:

  • 公开市场信息的自动收集仅限个人、非组织性的信息查询用途;
  • 禁止组织性/大规模爬取,禁止构建或再分发行情数据库;
  • 不得绕过访问控制、封锁或 quota;
  • 查询结果仅为投资参考信息,不构成投资劝诱、咨询或收益保证;
  • 该免责声明引用了韩国大法院判例(2005도1637、2021도1533)与商标法、信息通信网法、著作权法相关条款作为背景,但明确声明其本身不是法律保证。

小结

korean-stock-search展示了 k-skill 代理型技能的典型形态:把有密钥门槛的上游 API(KRX Open API,参考设计来自jjlabsio/korea-stock-mcp)收敛到一个统一代理后面,用户侧只剩三个 GET 请求和一组被严格归一化、有默认值、有明确失败码的查询参数。源码层面值得复用的点在于:全市场快照加本地确定性打分的搜索实现、短代码到标准代码的两级回退匹配、"degraded 不缓存"的缓存策略,以及对 400/404/502/503 各失败分支的清晰划分——这些设计让该技能既能在 Agent 对话中给出紧凑可靠的答复,又能把上游的部分故障透明地暴露给调用方。

【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 15:57:02

Directory.Build.props:MSBuild构建统一配置的核心机制

1. 为什么一个空文件能接管整个解决方案的编译逻辑?在 Visual Studio 2022 的实际项目维护中,我第一次见到Directory.Build.props文件时,它就静静地躺在解决方案根目录下,连一行 XML 都没有——打开后只有标准的 XML 声明和一个空…

作者头像 李华
网站建设 2026/9/17 15:56:59

transcribe.cpp流式API陷阱清单:5个常见错误与状态机使用规范

transcribe.cpp流式API陷阱清单:5个常见错误与状态机使用规范 【免费下载链接】transcribe.cpp ggml speech-to-text inference for 16 model families 项目地址: https://gitcode.com/GitHub_Trending/tr/transcribe.cpp transcribe.cpp 是基于 ggml 的 C …

作者头像 李华
网站建设 2026/9/17 15:56:43

LTP7792低噪声LDO原理与高精度供电实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 15:54:18

IDEA中解析Git Log:从可视化操作到命令行实战

1. 为什么要在IDEA里折腾Git Log先说个真实场景。前阵子同事跑来问我,说线上有个接口突然变慢了,明明上周还好好的,问我能不能查出来是谁改的。我打开IDEA,切到Git工具窗口的Log标签页,输入文件路径,再按时…

作者头像 李华
网站建设 2026/9/17 15:52:39

无人机分布式监控系统:协同算法与通信优化实践

1. 项目背景与核心价值无人机搭载相机网络的分布式监控系统正在成为安防、灾害监测和交通管理等领域的热门解决方案。相比传统固定摄像头网络,这种系统具备三大独特优势:首先是机动性,无人机可以快速部署到任何需要监控的区域;其次…

作者头像 李华