今天,Infoway API 正式上线韩国行情数据,覆盖韩国交易所KRX的全市场标的,所有套餐(包括免费试用)均可访问,提供实时成交明细、一档盘口、K 线以及韩国上市公司财务报表四类数据接口。

在下方表格中填入你的Infoway API Key,可以快速查询韩国股票行情:

基于 Infoway API,快速查询全球市场行情数据,支持 K 线、盘口、成交,或发起财报查询。

RESTful 行情查询 WebSocket 行情订阅 财务报表查询
查询 重置
清空 复制

            
连接 重置
清空 复制

            
查询 重置
清空 复制

            

1. 韩国股票市场背景

1.1 KRX:亚洲第四大交易所

韩国证券交易所(Korea Exchange,KRX)成立于 2005 年,由原首尔证券交易所、韩国期货交易所和 KOSDAQ 合并而成,总部位于釜山,交易系统在首尔运营。

KRX 按市值计算是全球第 14 大、亚洲第 4 大交易所(仅次于上交所、深交所和东交所),上市公司超过 2,600 家,总市值约 2.2 万亿美元

市场分为两个板块:

板块定位上市公司数量代表标的
KOSPI主板,大型蓝筹企业~940 家三星电子、SK 海力士、现代汽车
KOSDAQ成长板,科技/生物医药中小企业~1,700 家NAVER、Kakao、Celltrion

你一定知道这些公司,它们的股票代码是:

公司代码板块
三星电子005930.KSKOSPI
SK 海力士000660.KSKOSPI
现代汽车005380.KSKOSPI
LG 电子066570.KSKOSPI
POSCO Holdings005490.KSKOSPI
NAVER035420.KSKOSPI
Kakao035720.KSKOSPI
Celltrion068270.KSKOSPI
起亚汽车000270.KSKOSPI
KB 金融105560.KSKOSPI

1.2 交易时间

KRX 交易时间全程为韩国标准时间(KST,UTC+9),换算成北京时间(UTC+8)提前一小时:

时段KST(首尔)北京时间
集合竞价开盘08:30–09:0007:30–08:00
正式交易09:00–15:2008:00–14:20
集合竞价收盘15:20–15:3014:20–14:30
盘后交易15:40–18:0014:40–17:00

韩国不使用夏令时,所以北京时间和 KST 之间始终相差一小时,不需要像美股那样处理时区切换问题,对开发者相对友好。

1.3 小科普:韩国股票的折价问题

这里插播一个题外话,如果你研究过韩国股票,可能会发现一个很诡异的现象,韩国上市公司的市盈率很少有超过10倍的,像现在如日中天的宇宙第一牛股SK海力士,也只有9倍不到的PE,三星电子也是常年10倍以下,而同等规模的台积电 P/E 通常在 20 倍以上(我大A股千倍市梦率笑而不语)。

西方金融圈甚至给韩国股票极低估值的现象起了个名字:Korea Discount(韩国折价)

其实造成韩国折价问题的原因大致有三条:

一是财阀结构,像三星、现代、SK这些大财阀,多年以来通过交叉持股,形成了你中有我,我中有你的局面,导致小股东的权益可能会不受保护。

二是地缘问题,朝鲜是韩国稳定的最大的风险来源,每次半岛局势升温,韩国都会出现明显的资金外流。

三是低分红传统,韩国企业历史上习惯将利润留存而非分红,股东回报率偏低。(我大A再次笑而不语)

当然,韩国政府也意识到这个问题,2023 年以来,韩国政府和交易所开始主动推进”Korea Discount 修复”计划(Value-Up 项目),要求上市公司公布提升市盈率的方案,并对达标公司提供税收优惠。这个政策正在推动部分财阀企业提升股息支付率,对关注亚洲市场的量化策略是值得追踪的结构性变化。

2. 获取韩国股票数据的三条路

2.1 直连 KRX(Direct Feed)

和东京交易所、港交所一样,KRX 提供官方的数据直连服务,数据完整、延迟最低。代价同样可观:

  • 需要在韩国当地设立法人并签订授权合同
  • 年度授权费折合人民币约 15–30 万元
  • 还需要在韩国境内部署接收服务器(跨境专线成本另计)

这条路对大型机构可行,对个人开发者或中小团队基本等于关门。

2.2 Bloomberg / Refinitiv

这两家的覆盖面最全,数据质量最高,技术支持也最专业。代价是每个席位每年 2–5 万美元的订阅费,且以企业客户为目标,个人开发者没有签约渠道。

2.3 第三方 API(推荐)

供应商覆盖范围实时延迟价格面向用户
Bloomberg全球<1ms(直连)2–5万USD/年/席位机构
Refinitiv全球<1ms(直连)2–5万USD/年/席位机构
Infoway API全球主要市场<1s$99–$399/月个人/中小团队

对于需要快速构建韩股行情应用、量化回测或数据分析平台的开发者,Infoway API 是性价比最高的选择。

3. Infoway API 韩国股票数据覆盖

Infoway API 韩国行情数据接口 今日正式上线,覆盖四类数据:

数据类型说明
实时成交明细(Trade)每笔成交的价格、成交量、成交额、交易方向
最优盘口(Depth)最优买一价/卖一价及对应挂单量
K 线(Candles)1分钟至年K,最多500根,支持时间戳翻页查历史
韩国上市公司财报利润表、现金流量表、资产负债表、估值指标、股息数据等

免费试用用户可以直接访问上述所有数据,注册即可获得 API Key,无需绑定支付信息。

标的代码格式统一为 {6位代码}.KS,例如:

  • 005930.KS — 三星电子
  • 000660.KS — SK 海力士
  • 035420.KS — NAVER

4. REST API 接入示例(Python)

注册账号后,进入控制台即可看到你的 API Key。以下所有示例均需在请求头中带上 apiKey

4.1 实时成交明细

接口地址:GET https://data.infoway.io/korea/batch_trade/{codes}

Python
import requests

# 同时查询三星电子和 SK 海力士的最新成交
codes = "005930.KS,000660.KS"
url = f"https://data.infoway.io/korea/batch_trade/{codes}"

headers = {
    "apiKey": "YOUR_API_KEY",
    "Accept": "application/json"
}

resp = requests.get(url, headers=headers)
data = resp.json()

for item in data["data"]:
    direction = {0: "未知", 1: "买入", 2: "卖出"}.get(item["td"], "未知")
    print(f"{item['s']}: 最新价={item['p']}, 成交量={item['v']}, 方向={direction}")

返回字段说明:

字段说明
s标的代码,如 005930.KS
t成交时间(毫秒时间戳)
p最新成交价
v成交量(股)
vw成交额(韩元)
td交易方向:0=未知,1=买入,2=卖出

4.2 买卖盘口

接口地址:GET https://data.infoway.io/korea/batch_depth/{codes}

韩国盘口接口返回最优一档数据,即买一价/买一量和卖一价/卖一量:

Python
import requests

codes = "005930.KS"
url = f"https://data.infoway.io/korea/batch_depth/{codes}"

headers = {"apiKey": "YOUR_API_KEY"}

resp = requests.get(url, headers=headers)
result = resp.json()["data"][0]

ask_price = result["a"][0][0]   # 卖一价
ask_vol   = result["a"][1][0]   # 卖一量
bid_price = result["b"][0][0]   # 买一价
bid_vol   = result["b"][1][0]   # 买一量

print(f"标的:{result['s']}")
print(f"卖一:₩{float(ask_price):,.0f} × {float(ask_vol):.0f} 股")
print(f"买一:₩{float(bid_price):,.0f} × {float(bid_vol):.0f} 股")
print(f"价差:₩{float(ask_price) - float(bid_price):,.0f}")

a 是卖盘,b 是买盘,两个子数组分别是价格列表和挂单量列表(当前各一档),通过下标对应。

4.3 历史 K 线

接口地址:POST https://data.infoway.io/korea/v2/batch_kline

K 线接口支持 12 种周期,klineType 取值如下:

周期周期
11分钟74小时
25分钟8日K
315分钟9周K
430分钟10月K
51小时11季K
62小时12年K
Python
import requests

url = "https://data.infoway.io/korea/v2/batch_kline"

headers = {
    "apiKey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

# 查询 NAVER 最近 20 根 5 分钟 K 线
payload = {
    "klineType": 2,        # 5分钟K
    "klineNum": 20,
    "codes": "035420.KS"
    # "timestamp": 1234567890  # 可选,传秒时间戳向前翻页查历史
}

resp = requests.post(url, json=payload, headers=headers)
result = resp.json()

for item in result["data"]:
    print(f"\n{item['s']} K线列表(最新在前):")
    for bar in item["respList"]:
        print(f"  时间={bar['t']}, 开={bar['o']}, 高={bar['h']}, 低={bar['l']}, 收={bar['c']}, 量={bar['v']}, 涨跌幅={bar['pc']}")

多标的批量查询:多个代码用逗号分隔(最多100个),但注意多标的时 klineNum 最多只能填 2(只返回最近 2 根 K),单标的最多可查 500 根。

4.4 韩国上市公司财报

这是韩国数据的一个独特亮点:除了行情数据,Infoway API 还提供韩国上市公司的财务报表数据,包括利润表、现金流量表、资产负债表、估值指标等。

以查询三星电子的季度利润表为例:

Python
import requests

url = "https://data.infoway.io/common/basic/financial/income_statement"

headers = {"apiKey": "YOUR_API_KEY"}

params = {
    "symbol": "005930.KS",
    "type": "STOCK_KR",
    "period_type": "fq"    # fq=季度, fy=年度, fh=半年
}

resp = requests.get(url, params=params, headers=headers)
items = resp.json()["data"]

# 找出净利润条目
for item in items:
    if item["itemId"] == "net_income":
        print(f"报告期: {item['periodDate']}, 净利润: {item['itemValue']:,.0f} 韩元, TTM: {item['ttm']:,.0f} 韩元")
        break

财报接口支持的常用科目(itemId):

科目说明
net_income净利润
oper_income营业利润
revenue营业收入
gross_profit毛利润
free_cash_flow自由现金流(现金流量表)
total_assets总资产(资产负债表)
total_equity股东权益合计(资产负债表)
price_earnings市盈率(估值指标)
price_book市净率(估值指标)
roe净资产收益率(估值指标)

可用的财报端点:

Python
/common/basic/financial/income_statement    # 利润表
/common/basic/financial/cash_flow          # 现金流量表
/common/basic/financial/balance_sheet      # 资产负债表
/common/basic/financial/statistics         # 估值与财务比率(含实时PE/PB)
/common/basic/financial/dividend           # 股息指标
/common/basic/financial/earnings           # EPS 与营收预期对比(Beat/Miss)

5. 韩国涨跌停机制

在接入韩国行情数据之前,有一个机制值得专门说一下:韩国的涨跌停限制是 ±30%

这不是笔误。韩国的涨跌停幅度在全球主要股市里算是偏宽松的:

市场涨跌停幅度
中国 A 股(主板)±10%
中国 A 股(科创板/创业板)±20%
日本 TSE±最大价格幅度(随股价档位变化,约 ±10%–±25%)
韩国 KRX±30%
美股无硬性涨跌停,但有 LULD 熔断机制
港股无涨跌停

±30% 意味着什么?一只韩国股票在单个交易日最多可以涨 30%、也可以跌 30%。这在生物医药和科技小盘股里并不罕见,尤其是 KOSDAQ 板块的小市值标的,在重大消息(新药临床结果、政策变化)释放后,直接触及涨跌停是常有的事。

对行情数据接入的影响:如果你的策略需要检测涨跌停状态,不能套用 A 股的 ±10% 判断逻辑,要改成 ±30%。通过 K 线接口返回的 pc(涨跌幅)字段可以直接判断。

另外值得一提的是,韩国曾在 2023 年因 KOSPI 连续下跌、卖空压力过大,宣布全面禁止卖空长达一年以上,直到 2024 年底才分阶段解除。这在全球主要市场里是非常罕见的监管动作,说明 KRX 对异常波动的容忍度比其他市场低,量化策略在做空方向需要格外注意监管风险。

6. WebSocket 实时订阅(含断线重连)

WebSocket 是获取低延迟实时推送的最佳方式,连接建立后服务器会主动推送行情更新,不需要你反复轮询。韩国行情的 WebSocket 订阅地址:

Python
wss://data.infoway.io/ws?business=korea&apikey=YOUR_API_KEY

下面是一个完整的 Python 客户端示例,包含断线重连、心跳保活,订阅三星电子的实时成交明细、盘口和 1 分钟 K 线:

Python
import asyncio
import json
import logging
import os
import uuid
from typing import Optional

import websockets
from websockets.asyncio.client import ClientConnection
from websockets.exceptions import ConnectionClosed

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s"
)
logger = logging.getLogger("korea-ws")

# --- 协议号 ------------------------------------------------------------------
REQ_TRADE     = 10000   # 订阅实时成交明细
REQ_DEPTH     = 10003   # 订阅盘口
REQ_KLINE     = 10006   # 订阅K线
REQ_HEARTBEAT = 10010   # 心跳

PUSH_TRADE = 10002
PUSH_DEPTH = 10005
PUSH_KLINE = 10008
ACK_CODES  = {10001, 10004, 10007}

# 要订阅的韩国股票,多个用逗号分隔
SUBSCRIBE_CODES = "005930.KS,000660.KS,035420.KS"


class KoreaMarketWsClient:
    """韩国行情 WebSocket 客户端,带自动重连和心跳保活。"""

    def __init__(self, api_key: str):
        self.ws_url = f"wss://data.infoway.io/ws?business=korea&apikey={api_key}"
        self.ws: Optional[ClientConnection] = None
        self.running = True
        self.reconnect_base = 5
        self.reconnect_max  = 60
        self.heartbeat_interval = 30
        self.heartbeat_task: Optional[asyncio.Task] = None

    @staticmethod
    def _trace() -> str:
        return str(uuid.uuid4())

    async def _send(self, msg: dict) -> None:
        assert self.ws is not None
        await self.ws.send(json.dumps(msg))

    async def _subscribe_all(self) -> None:
        # 1. 实时成交明细
        await self._send({"code": REQ_TRADE, "trace": self._trace(),
                          "data": {"codes": SUBSCRIBE_CODES}})
        logger.info("已订阅成交明细: %s", SUBSCRIBE_CODES)

        # 2. 一档盘口
        await self._send({"code": REQ_DEPTH, "trace": self._trace(),
                          "data": {"codes": SUBSCRIBE_CODES}})
        logger.info("已订阅盘口: %s", SUBSCRIBE_CODES)

        # 3. 1 分钟 K 线
        await self._send({"code": REQ_KLINE, "trace": self._trace(),
                          "data": {"arr": [{"type": 1, "codes": SUBSCRIBE_CODES}]}})
        logger.info("已订阅1分钟K线: %s", SUBSCRIBE_CODES)

    def _start_heartbeat(self) -> None:
        self._stop_heartbeat()

        async def _loop():
            try:
                while True:
                    await asyncio.sleep(self.heartbeat_interval)
                    if self.ws is None or self.ws.close_code is not None:
                        break
                    await self._send({"code": REQ_HEARTBEAT, "trace": self._trace()})
                    logger.debug("心跳已发送")
            except (ConnectionClosed, asyncio.CancelledError):
                pass

        self.heartbeat_task = asyncio.create_task(_loop())

    def _stop_heartbeat(self) -> None:
        if self.heartbeat_task and not self.heartbeat_task.done():
            self.heartbeat_task.cancel()
        self.heartbeat_task = None

    def _on_message(self, raw: str) -> None:
        try:
            msg = json.loads(raw)
        except json.JSONDecodeError:
            logger.error("消息解析失败: %s", raw[:200])
            return

        code = msg.get("code")
        data = msg.get("data", {})

        if code == PUSH_TRADE:
            logger.info("[成交] %s: 价格=%s 量=%s 方向=%s",
                        data.get("s"), data.get("p"), data.get("v"),
                        {0: "未知", 1: "买入", 2: "卖出"}.get(data.get("td", 0)))
        elif code == PUSH_DEPTH:
            asks = list(zip(data.get("a", [[]])[0], data.get("a", [[], []])[1]))
            bids = list(zip(data.get("b", [[]])[0], data.get("b", [[], []])[1]))
            logger.info("[盘口] %s: 卖一=%s 买一=%s",
                        data.get("s"),
                        asks[0] if asks else "N/A",
                        bids[0] if bids else "N/A")
        elif code == PUSH_KLINE:
            logger.info("[K线] %s: 收=%s 涨幅=%s",
                        data.get("s"), data.get("c"), data.get("pfr"))
        elif code in ACK_CODES:
            logger.info("[订阅确认] code=%s msg=%s", code, msg.get("msg"))
        elif code == 200:
            logger.info("[连接成功] %s", msg.get("msg"))
        elif code == REQ_HEARTBEAT:
            logger.debug("[心跳响应] trace=%s", msg.get("trace"))
        else:
            logger.warning("[未知消息] code=%s", code)

    async def _connect_once(self) -> None:
        async with websockets.connect(self.ws_url) as ws:
            self.ws = ws
            logger.info("WebSocket 连接成功")
            await self._subscribe_all()
            self._start_heartbeat()
            try:
                async for message in ws:
                    self._on_message(message)
            finally:
                self._stop_heartbeat()
                self.ws = None

    async def start(self) -> None:
        backoff = self.reconnect_base
        while self.running:
            try:
                await self._connect_once()
                backoff = self.reconnect_base
                logger.warning("连接被服务端关闭")
            except ConnectionClosed as e:
                logger.warning("连接关闭: %s", e)
                backoff = self.reconnect_base
            except Exception as e:
                logger.error("连接异常: %s", e)

            if not self.running:
                break
            logger.info("%.0f 秒后重连...", backoff)
            await asyncio.sleep(backoff)
            backoff = min(backoff * 2, self.reconnect_max)

    def stop(self) -> None:
        self.running = False


async def main():
    api_key = os.environ.get("INFOWAY_API_KEY", "YOUR_API_KEY")
    client = KoreaMarketWsClient(api_key=api_key)
    await client.start()


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        logger.info("已退出")

运行前安装依赖:

Python
pip install websockets

设置 API Key:

Python
export INFOWAY_API_KEY="你的API Key"
python korea_ws.py

7. 综合示例:三星 + SK 海力士半导体监控脚本

下面这个脚本把 REST 接口组合使用,实时对比三星电子和 SK 海力士的价格走势,并在涨幅差超过 2% 时打印提示,这在半导体板块联动分析中是一个常见的监控需求。

Python
import time
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://data.infoway.io"
HEADERS  = {"apiKey": API_KEY}

CODES = "005930.KS,000660.KS"   # 三星电子, SK 海力士

def get_trade():
    url = f"{BASE_URL}/korea/batch_trade/{CODES}"
    return {item["s"]: item for item in requests.get(url, headers=HEADERS).json()["data"]}

def get_kline_daily(code: str):
    """获取最近 2 根日K,用于计算昨收价。"""
    resp = requests.post(
        f"{BASE_URL}/korea/v2/batch_kline",
        json={"klineType": 8, "klineNum": 2, "codes": code},
        headers={**HEADERS, "Content-Type": "application/json"}
    )
    bars = resp.json()["data"][0]["respList"]
    return bars   # bars[0] 是当日(未收盘),bars[1] 是昨日收盘

def calc_change(current_price: str, prev_close: str) -> float:
    return (float(current_price) - float(prev_close)) / float(prev_close) * 100

if __name__ == "__main__":
    # 拉昨收
    samsung_bars  = get_kline_daily("005930.KS")
    skhynix_bars  = get_kline_daily("000660.KS")
    samsung_prev  = samsung_bars[1]["c"]
    skhynix_prev  = skhynix_bars[1]["c"]

    print(f"三星昨收: ₩{float(samsung_prev):,.0f}")
    print(f"SK海力士昨收: ₩{float(skhynix_prev):,.0f}")
    print("-" * 40)

    while True:
        trades = get_trade()

        samsung_pct  = calc_change(trades["005930.KS"]["p"], samsung_prev)
        skhynix_pct  = calc_change(trades["000660.KS"]["p"], skhynix_prev)
        spread = samsung_pct - skhynix_pct

        print(f"三星: {samsung_pct:+.2f}%  SK海力士: {skhynix_pct:+.2f}%  价差: {spread:+.2f}%", end="")

        if abs(spread) > 2.0:
            print(f"  ⚠ 两者涨幅差超过 2%,关注联动异常!", end="")
        print()

        time.sleep(5)

8. 常见问题

Q1:韩国股票代码是什么格式?

统一使用六位数字加 .KS 后缀,例如 005930.KS(三星电子)。KOSPI 和 KOSDAQ 使用同一格式,通过代码段区分:KOSPI 主板通常是 0xxxxx,KOSDAQ 是 2xxxxx3xxxxx。完整标的列表可以登录 Infoway 控制台下载 Excel,或通过产品列表接口查询。

Q2:免费套餐能不能用韩国行情接口?

可以。所有套餐包括免费试用都能访问韩国行情的四类数据(成交明细、盘口、K线、财报)。免费套餐的 WebSocket 订阅额度是 10 个标的,REST 接口频率受套餐限制。

Q3:韩国股票的盘口是几档?

Infoway API 韩国盘口接口返回最优一档,即买一价/买一量和卖一价/卖一量。

Q4:财报数据支持哪些股票?

主要覆盖 KOSPI 和 KOSDAQ 的主要上市公司,包括三星电子、SK 海力士、NAVER、现代汽车等主要标的。财报数据按季度更新,历史数据可追溯多年。

Q5:K 线接口的 timestamp 参数怎么用来翻页?

翻页时,把上次返回结果中最早一根 K 线的 t(秒时间戳)减 1 后传入 timestamp,接口会向前返回更早的数据。注意这个参数仅对分钟 K 和小时 K 有效,日 K 及以上周期不受限制。

Q6:WebSocket 断线后订阅会不会自动恢复?

不会自动恢复,Infoway 的 WebSocket 是无状态的,断线重连后需要重新发送订阅请求。上面的 Python 示例已经处理了这个逻辑:_connect_once 每次建立新连接后都会调用 _subscribe_all 重新订阅。