📈 专业级股票 K 线图表 React 组件
基于 ECharts,内置 stock-sdk 数据源,开箱即用
安装 • 快速开始 • 功能特性 • API 文档 • 主题定制
- 🚀 零配置数据 - 内置 stock-sdk,传入股票代码自动获取数据
- 🔌 可插拔数据源 - 支持自定义 DataProvider(解决跨域/接入自有行情源/SSR)
- 🌍 多市场支持 - A 股、港股、美股
- 📊 丰富周期 - 分时、五日、日 K、周 K、月 K、分钟级 K 线
- 📈 技术指标 - MA/MACD/BOLL/KDJ/RSI/WR/BIAS/CCI/ATR/OBV/ROC/DMI/SAR/KC
- 🎯 交互完善 - 缩放、平移、十字准线、Tooltip、撤销/重做
- 🖥️ 全屏模式 - 一键全屏展示
- 🔄 自动刷新 - 分时模式支持自动刷新数据
- 🎨 高度可定制 - 主题、颜色、指标参数均可配置
- 📱 响应式设计 - 自适应容器尺寸
- 📦 轻量体积 - Tree-shaking 友好,按需引入 ECharts 组件
npm install kline-charts-react
# 或使用 yarn
yarn add kline-charts-react
# 或使用 pnpm
pnpm add kline-charts-reactnpm install react react-dom echartsimport { KLineChart } from 'kline-charts-react';
import 'kline-charts-react/style.css';
function App() {
return (
<KLineChart
symbol="sh600519" // 贵州茅台
height={600}
/>
);
}<KLineChart
symbol="sz000001" // 平安银行
market="A" // A 股(默认)
/><KLineChart
symbol="sh600519"
defaultPeriod="weekly" // 非受控模式下默认显示周 K
/>可选周期:timeline | timeline5 | 1 | 5 | 15 | 30 | 60 | daily | weekly | monthly
period、adjust、indicators 支持受控模式;defaultPeriod、defaultAdjust、defaultIndicators 用于非受控默认值。
// 非受控
<KLineChart
symbol="sh600519"
defaultPeriod="daily"
defaultAdjust="qfq"
defaultIndicators={['ma', 'volume', 'macd']}
/>// 受控
function App() {
const [period, setPeriod] = useState<PeriodType>('daily');
return (
<KLineChart
symbol="sh600519"
period={period}
onPeriodChange={setPeriod}
/>
);
}<KLineChart
symbol="sh600519"
indicators={['ma', 'volume', 'macd', 'kdj']}
indicatorOptions={{
ma: { periods: [5, 10, 20, 60] },
macd: { short: 12, long: 26, signal: 9 },
}}
/><KLineChart
symbol="sh600519"
theme="dark"
/><KLineChart
symbol="sh600519"
period="timeline"
autoRefresh={{ intervalMs: 5000, onlyTradingTime: true }}
/>解决跨域问题或接入自有行情源:
import { KLineChart, type KLineDataProvider } from 'kline-charts-react';
const customProvider: KLineDataProvider = {
// K 线数据(必须实现)
getKline: async (params, signal) => {
// params: { symbol, market, period, adjust, cursor?, limit? }
// cursor/limit 仅在「向左滚动加载更多历史」时传入,见下方「无限滚动加载历史」
const res = await fetch(`/api/kline?symbol=${params.symbol}&period=${params.period}`, { signal });
return res.json(); // 返回 KlineData[]
},
// 分时数据(可选,period 为 'timeline' / 'timeline5' 时使用)
getTimeline: async (params, signal) => {
// params.period: 'timeline'(单日,默认)| 'timeline5'(五日)
const days = params.period === 'timeline5' ? 5 : 1;
const res = await fetch(`/api/timeline?symbol=${params.symbol}&days=${days}`, { signal });
const json = await res.json();
// 推荐返回 { data, prevClose }:prevClose(昨收)用于分时图的涨跌着色与昨收参考线
return { data: json.data, prevClose: json.prevClose };
// 也兼容直接 return TimelineData[](此时无昨收线)
},
};
<KLineChart
symbol="sh600519"
dataProvider={customProvider}
/>getKline 需要返回 KlineData[],每条数据的字段如下:
interface KlineData {
date: string; // 日期/时间,如 "2024-01-15" 或 "2024-01-15 09:35"
open: number | null; // 开盘价
close: number | null; // 收盘价
high: number | null; // 最高价
low: number | null; // 最低价
volume: number | null; // 成交量
amount: number | null; // 成交额
changePercent?: number; // 涨跌幅(可选)
change?: number; // 涨跌额(可选)
amplitude?: number; // 振幅(可选)
turnoverRate?: number; // 换手率(可选)
}getTimeline 推荐返回 TimelineResult({ data, prevClose }),其中 data 为分时序列、prevClose 为昨收价;也兼容直接返回 TimelineData[]:
interface TimelineData {
time: string; // 时间:"09:30" 或 "2024-01-15 09:30" 均可(渲染层两种都支持;
// 内置源:A 股单日分时为 HH:mm,港/美股单日与所有五日分时带日期前缀)
price: number; // 当前价格
volume: number; // 累计成交量(按交易日累计)
amount: number; // 累计成交额(按交易日累计)
avgPrice: number; // 均价
}
interface TimelineResult {
data: TimelineData[];
prevClose?: number | null; // 昨收价:用于分时图涨跌着色与昨收参考线,缺省则不绘制昨收线
}技术指标(MA、MACD、KDJ 等)会由组件自动根据 K 线数据计算,无需在数据源中提供。 未实现
getTimeline的自定义数据源:分时/五日分时会退化为「调用getKline拿分钟数据 + 组件内聚合 VWAP」,此时无昨收基准。
日/周/月 K 向左滚动到最左侧时,组件会调用 getKline 并带上
cursor(当前最早一根的 date)与 limit(默认 180,可用
requestOptions.loadMoreLimit 配置)请求更早的历史:
const provider: KLineDataProvider = {
getKline: async ({ symbol, period, cursor, limit }, signal) => {
const qs = cursor ? `&before=${cursor}&limit=${limit}` : '';
const res = await fetch(`/api/kline?symbol=${symbol}&period=${period}${qs}`, { signal });
return res.json();
},
};
⚠️ 内置数据源不支持增量加载历史:默认 provider 一次性返回全部历史并忽略cursor/limit,向左滚动不会加载更多(首次触发后自动停止探测)。 无限滚动仅在自定义dataProvider实现了基于 cursor 的分页时生效。分页返回的顺序不限(newest-first / oldest-first 均可):组件会去重并按日期 升序归并后再渲染。
import { useRef } from 'react';
import { KLineChart, type KLineChartRef } from 'kline-charts-react';
function App() {
const chartRef = useRef<KLineChartRef>(null);
const handleRefresh = () => {
chartRef.current?.refresh();
};
const handleExport = () => {
const dataUrl = chartRef.current?.exportImage('png');
// 下载图片...
};
return (
<>
<button onClick={handleRefresh}>刷新</button>
<button onClick={handleExport}>导出图片</button>
<KLineChart ref={chartRef} symbol="sh600519" />
</>
);
}主入口只保留稳定导出。如果你明确需要内部 hooks / 子组件,请从 kline-charts-react/unstable 引入:
import { useKlineData, Toolbar } from 'kline-charts-react/unstable';| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
symbol |
string |
必填 | 股票代码,如 sh600519、sz000001 |
market |
'A' | 'HK' | 'US' |
'A' |
市场类型 |
period |
PeriodType |
- | 当前 K 线周期(受控) |
defaultPeriod |
PeriodType |
'daily' |
非受控模式下默认周期 |
adjust |
'' | 'qfq' | 'hfq' |
- | 当前复权类型(受控) |
defaultAdjust |
'' | 'qfq' | 'hfq' |
'qfq' |
非受控模式下默认复权 |
height |
number | string |
500 |
图表高度 |
width |
number | string |
'100%' |
图表宽度 |
theme |
'light' | 'dark' | ThemeConfig |
'light' |
主题配置 |
indicators |
IndicatorType[] |
- | 当前启用的技术指标(受控) |
defaultIndicators |
IndicatorType[] |
['ma', 'volume', 'macd'] |
非受控模式下默认指标 |
indicatorOptions |
IndicatorOptions |
- | 指标参数配置 |
showToolbar |
boolean |
true |
是否显示工具栏 |
showPeriodSelector |
boolean |
true |
是否显示周期切换 |
showIndicatorSelector |
boolean |
true |
是否显示指标切换 |
maxSubPanes |
number |
3 |
最多显示几个副图,0 表示不显示副图 |
visibleCount |
number |
60 |
初始可见 K 线数量(关闭缩放的周期不生效,显示全部) |
showDataZoomSlider |
boolean | Partial<Record<PeriodType, boolean>> |
true |
是否启用缩放(滚轮 + 底部滑块),可按周期设置,如 { timeline: false };关闭后该周期无缩放/平移、visibleCount 与滚动加载历史均不生效 |
dataProvider |
KLineDataProvider |
- | 自定义数据源(请用 useMemo 保持引用稳定) |
sdkOptions |
SDKOptions |
- | stock-sdk 配置 |
requestOptions |
RequestOptions |
- | 请求控制配置(见下表) |
autoRefresh |
boolean | AutoRefreshOptions |
- | 自动刷新配置 |
echartsOption |
EChartsOption |
- | 自定义 ECharts 配置 |
echartsOptionMerge |
EChartsOptionMergeOptions |
- | ECharts Option 合并策略 |
panes |
PaneConfig[] |
- | 自定义面板布局,支持单副图多指标;主图面板的 id 必须为 'main' |
onDataLoad |
(data: KlineWithIndicators[]) => void |
- | 数据加载回调(仅 K 线周期触发,数据已附带指标字段) |
onPeriodChange |
(period: PeriodType) => void |
- | 周期切换回调 |
onAdjustChange |
(adjust: AdjustType) => void |
- | 复权切换回调 |
onIndicatorsChange |
(indicators: IndicatorType[]) => void |
- | 指标切换回调 |
onVisibleRangeChange |
({ start, end }) => void |
- | 当前 dataZoom 可见范围变化 |
onError |
(error: Error) => void |
- | 错误回调 |
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
debounceMs |
number |
150 |
参数变化后的请求防抖时间 |
abortOnChange |
boolean |
true |
参数变化时是否中止上一次请求(内置数据源的网络层不支持中止,仅丢弃过期结果) |
dedupe |
boolean |
true |
相同请求(同数据源 + 同参数)是否走缓存与去重 |
loadMoreLimit |
number |
180 |
滚动加载历史时每次请求的条数(传给 getKline 的 limit) |
| 方法 | 说明 |
|---|---|
refresh() |
刷新数据 |
setPeriod(period) |
切换周期 |
setAdjust(adjust) |
切换复权 |
setIndicators(indicators) |
切换指标 |
zoomTo(start, end) |
缩放到指定范围 |
resetZoom() |
重置缩放 |
getVisibleRange() |
获取当前可见范围 { start, end } |
getEchartsInstance() |
获取 ECharts 实例,未初始化时返回 null |
exportImage(type?) |
导出图片(png/jpeg),图表实例未就绪时返回 null |
getData() |
获取当前 K 线数据(KlineWithIndicators[],已附带指标字段) |
type PeriodType =
| 'timeline' // 分时
| 'timeline5' // 五日分时
| '1' // 1分钟
| '5' // 5分钟
| '15' // 15分钟
| '30' // 30分钟
| '60' // 60分钟
| 'daily' // 日K
| 'weekly' // 周K
| 'monthly'; // 月K| 周期 | A 股 | 港股 | 美股 | 说明 |
|---|---|---|---|---|
分时 timeline |
✅ | ✅ | ✅ | A 股走行情分时接口(自带昨收);港/美股由 1 分钟数据聚合,昨收取自日 K |
五日分时 timeline5 |
✅ | ✅ | ✅ | 由 1 分钟数据按交易日聚合(VWAP 均价按日重置),昨收取自窗口前最近交易日的日 K 收盘 |
分钟 1/5/15/30/60 |
✅ | ✅ | ✅ | 按市场路由到对应分钟 K 线端点 |
| 日/周/月 | ✅ | ✅ | ✅ | 支持前复权/后复权/不复权 |
使用自定义
dataProvider时不受上表限制,支持范围由你的数据源决定。
代码格式(内置数据源):A 股带市场前缀如 sh600519 / sz000001;港股用 5 位
数字如 00700;美股需带交易所前缀,如 105.AAPL(105=纳斯达克、106=NYSE、107=AMEX)。
type IndicatorType =
// 主图指标
| 'ma' // 移动平均线
| 'boll' // 布林带
| 'sar' // 抛物线转向(SAR)
| 'kc' // 肯特纳通道(KC)
// 副图指标
| 'volume' // 成交量
| 'macd' // MACD
| 'kdj' // KDJ
| 'rsi' // RSI
| 'wr' // WR(威廉指标)
| 'bias' // BIAS(乖离率)
| 'cci' // CCI(顺势指标)
| 'atr' // ATR(平均真实波幅)
| 'obv' // OBV(能量潮)
| 'roc' // ROC(变动率)
| 'dmi'; // DMI(趋向指标)主图指标说明:
- MA - 移动平均线,显示不同周期的均线
- BOLL - 布林带,由上轨、中轨、下轨组成的通道
- SAR - 抛物线转向,以点状显示趋势反转信号
- KC - 肯特纳通道,基于 EMA 和 ATR 的通道指标
副图指标说明:
- OBV - 能量潮,通过成交量变化预测价格趋势
- ROC - 变动率,衡量价格变化的速度
- DMI - 趋向指标,包含 +DI、-DI、ADX、ADXR 四条线
// 浅色主题(默认)
<KLineChart theme="light" />
// 深色主题
<KLineChart theme="dark" /><KLineChart
theme={{
backgroundColor: '#1a1a2e',
textColor: '#eaeaea',
upColor: '#26a69a',
downColor: '#ef5350',
gridLineColor: '#2a2a4a',
// ... 更多配置
}}
/>内置数据源(stock-sdk v2)请求东方财富 / 雪球等多个行情端点,这些端点通常允许 浏览器直连,多数场景无需任何代理配置(本仓库 playground 即为直连)。
如果你的部署环境仍遇到跨域拦截(例如目标端点策略变化、内网安全网关拦截),推荐:
用自己的后端聚合/代理行情数据,前端只对同源接口取数——这同时解决跨域、鉴权与 数据合规问题:
<KLineChart
symbol="sh600519"
dataProvider={myDataProvider} // 实现见上方「自定义数据源」
/>说明:
sdkOptions.baseUrl在 stock-sdk v2 中只影响腾讯快照行情端点, 不会改写 K 线 / 分时等其余多数据源(eastmoney / xueqiu)的请求地址, 不能用作跨域网关方案;旧版针对qt.gtimg.cn的/qt单目标代理同样已失效。 需要收口出网流量时请使用方案 1(自定义 DataProvider)。
kline-charts-react/
├── src/
│ ├── components/ # 子组件
│ │ ├── Loading/ # 加载状态
│ │ ├── PeriodSelector/ # 周期切换
│ │ ├── IndicatorSelector/# 指标选择器
│ │ ├── Toolbar/ # 工具栏
│ │ ├── IndicatorDisplay/ # 主图指标数值
│ │ └── SubPaneTitle/ # 副图标题
│ ├── hooks/ # React Hooks
│ │ ├── useKlineData.ts # 数据获取 & 指标计算
│ │ ├── useEcharts.ts # ECharts 实例管理
│ │ └── useZoomHistory.ts # 缩放历史
│ ├── utils/ # 工具函数
│ │ ├── indicators.ts # 技术指标计算
│ │ ├── optionBuilder.ts # K 线 ECharts 配置
│ │ ├── timelineBuilder.ts# 分时图 ECharts 配置
│ │ ├── formatters.ts # 数据格式化
│ │ └── cache.ts # 数据缓存
│ ├── types/ # 类型定义
│ ├── KLineChart.tsx # 主组件
│ └── index.ts # 入口
├── playground/ # 调试环境
└── dist/ # 构建产物
# 安装依赖
yarn install
# 启动开发调试(直连本地源码,支持热更新)
yarn dev
# 构建组件库
yarn build
# 构建 playground 生产版本
yarn build:playground
# 代码检查
yarn lint
# 类型检查
yarn typecheck
# 单元测试
yarn test:run
# 打包校验
yarn pack:check开发模式说明:
yarn dev会启动 playground,直接引用src/下的源码,修改源码后自动热更新playground/通过本地file:..依赖引用当前仓库,避免和 npm 上的历史版本漂移- CI 会执行
lint、typecheck、test:run、build、build:playground和pack:check
- 导出图片:
exportImage()导出的图片仅包含 ECharts 图表内容,不包含左上角的指标数值文字(这部分是用 React 渲染在图表外部的) - 成交量单位:内置数据源的
volume原样透传上游数值,不同市场/端点的单位可能不同(股 vs 手)。若用于自定义计算或展示换算,请先用真实数据校准 - 自动刷新与节假日:
autoRefresh.onlyTradingTime仅按「星期 + 交易时段」判断,不含法定节假日/半日市日历——休市日(非周末)仍会按周期发起刷新 - 请求中止:内置数据源(stock-sdk v2)的接口不支持逐请求 AbortSignal,
requestOptions.abortOnChange对它只在结果层丢弃过期数据,不会真正取消网络请求;自定义 provider 透传signal即可获得真正的中止 - 无限滚动:内置数据源不支持
cursor/limit增量分页,向左滚动加载更多历史仅对实现了分页的自定义 provider 生效 - onDataLoad:仅 K 线周期触发;分时/五日分时的数据经由
getTimeline通道,不回调onDataLoad - 同参数刷新失败的提示:手动/自动刷新(参数不变)失败时会保留旧图、不弹内置错误层(避免遮挡与闪烁),仅触发
onError回调——需要显式提示时请在onError里自行展示
MIT © 2025-present chengzuopeng