前端做金融图表的坑,我替你踩过了。
背景
说来话长,但我尽量说短。
某天产品跑过来跟我说:"在页面上加个 K 线图吧,应该不难。"
我当时心想,2025 年了,这东西还需要自己写?npm 上肯定一堆现成的。
结果我打开 npm 搜了一圈,发现情况不太乐观:
- 有些组件功能倒是全,但那是人家商业产品,开源版阉割得差不多了,想用完整功能得掏钱
- 有些看起来还行,点进去一看,最后一次 commit 是两年前,依赖的 React 版本还停留在 16
- 还有一些纯 Canvas 手撸的,佩服是佩服,但接入成本太高,文档还是英文半成品
纠结了一下午,我决定自己写一个。
直接看东西
项目叫 kline-charts-react,已经发到 npm 上了。
最简单的用法,五行代码搞定:
tsx
import { KLineChart } from 'kline-charts-react';
import 'kline-charts-react/style.css';
function App() {
return <KLineChart symbol="sh600519" height={600} />;
}
没错,一个 symbol 属性就完事了。数据获取、指标计算、图表渲染,组件内部全包了。
"那数据是从哪来的?不会要我自己对接接口吧?"
不需要,往下看。
功能概览
目标是做到雪球 K 线图那种体验。目前做到了大概八成:
多周期:分时走势、五日分时、日 K、周 K、月 K,还有 1 分钟到 60 分钟的分钟线。炒短线的朋友可以放心了。
技术指标:支持 15 种 ------ MA、BOLL、MACD、KDJ、RSI、WR、BIAS、CCI、ATR、OBV、ROC、DMI、SAR、KC。所有指标都在浏览器端计算,不需要服务端返回。说实话,写这些计算公式的过程挺上头的,特别是 DMI 和 SAR,逻辑绕得我差点怀疑人生。
交互体验:滚轮缩放、拖拽平移、十字准线跟随、Tooltip 信息展示、缩放的撤销/重做、一键全屏、导出 PNG 图片。
外观:浅色和深色两套内置主题,也可以传自定义的颜色配置进去。
复权支持:不复权、前复权、后复权三种模式可切换,默认前复权。
数据层 ------ 聊聊 stock-sdk
做图表组件,绑定什么数据源是个问题。
前端圈搞股票数据一直比较尴尬 ------ 好用的库几乎全是 Python 的。tushare、akshare、baostock,想用的话你得起个 Python 服务,前端再请求这个服务。链路长,维护烦。
为了解决这个痛点,我做了 stock-sdk,一个纯前端/Node.js 的股票行情 SDK。
核心思路就一句话:前端工程师获取股票数据,不应该需要 Python。
stock-sdk 的几个亮点:
- 零依赖、体积小,TypeScript 写的,打包压缩后不到 20KB
- 浏览器和 Node.js 都行,ESM 和 CJS 双格式输出
- 覆盖面广,A 股、港股、美股、公募基金,实时行情和历史 K 线都能取
- 自带指标计算,MA、MACD、BOLL、KDJ、RSI 等主流技术指标直接调用
- 类型提示完善,TS 项目用起来体验很好,字段名不用猜
简单示意:
ts
import { StockSDK } from 'stock-sdk';
const sdk = new StockSDK();
// 拉几只股票的实时报价
const quotes = await sdk.getSimpleQuotes(['sh600519', 'sz000858']);
quotes.forEach(q => {
console.log(`${q.name}: ${q.price} (${q.changePercent}%)`);
});
// 拉日 K 线数据
const kline = await sdk.getKline('sh600519', { period: 'daily', adjust: 'qfq' });
kline-charts-react 底层就集成了 stock-sdk,传一个股票代码进去,组件会自动请求数据、计算指标、渲染图表,整条链路在浏览器端闭环,不依赖任何后端服务。
stock-sdk 本身也是独立的 npm 包,不画图的场景一样能用 ------ 做个行情 Dashboard、写个 Node 定时任务抓数据之类的,都没问题。
更多用法参考官方文档:stock-sdk.linkdiary.cn
当然了,如果你们公司有现成的行情接口,组件也支持自定义数据源,完全可以绕过 stock-sdk。
技术选型
图表渲染这块我选了 ECharts。
有人可能觉得 ECharts 太重了,但实际上组件里用了按需引入 ------ 只注册了 CandlestickChart、LineChart、BarChart、ScatterChart 这几个模块,并不是把整个 ECharts 都打进去。
而且 ECharts 的优势很明显:渲染性能好、交互事件体系成熟、响应式适配开箱即用。自己从 Canvas 开始画当然也行,但工期不允许。
关于包体积,组件自身(不含 echarts 和 react)构建产物 77KB ,gzip 后约 19KB。echarts 走 peerDependency,项目里已有的话不会重复打包。
设计上的一些考量
1. 开箱即用 vs 高度可配
默认情况下传个 symbol 就能渲染,零配置。但所有细节都暴露了 props:
tsx
<KLineChart
symbol="sh600519"
period="weekly"
adjust="qfq"
theme="dark"
indicators={['ma', 'volume', 'kdj', 'rsi']}
indicatorOptions={{
ma: { periods: [5, 10, 20, 60] },
}}
maxSubPanes={3}
height={700}
/>
想用哪些指标、均线取几日、副图显示几个、用什么主题,随便调。
2. 自定义数据源
如果你有自己的行情 API,通过 dataProvider 可以完全替换内置的数据获取逻辑:
tsx
const myProvider = {
getKline: async (params, signal) => {
const res = await fetch(`/api/kline?symbol=${params.symbol}&period=${params.period}`, { signal });
return res.json();
},
getTimeline: async (params, signal) => {
const res = await fetch(`/api/timeline?symbol=${params.symbol}`, { signal });
return res.json();
},
};
<KLineChart symbol="sh600519" dataProvider={myProvider} />
数据结构很直观 ------ K 线是 { date, open, close, high, low, volume, amount },分时是 { time, price, volume, amount, avgPrice }。传进来原始数据就行,MA、MACD 这些指标组件内部会自己算。
3. 外部控制
通过 ref 可以在组件外部调用方法,适合需要和外部 UI 联动的场景:
tsx
const chartRef = useRef<KLineChartRef>(null);
// 手动刷新
chartRef.current?.refresh();
// 导出成图片
const dataUrl = chartRef.current?.exportImage('png');
// 程序化切换到周 K
chartRef.current?.setPeriod('weekly');
// 拿到底层 ECharts 实例
const instance = chartRef.current?.getEchartsInstance();
4. 分时自动刷新
盯盘场景下,分时图需要定时刷新。组件内置了轮询机制,还支持限制只在交易时段刷新:
tsx
<KLineChart
symbol="sh600519"
period="timeline"
autoRefresh={{ intervalMs: 5000, onlyTradingTime: true }}
/>
安装方式
bash
yarn add kline-charts-react
# peer dependencies 也别忘了装
yarn add react react-dom echarts
echarts 是 peerDependency,你项目里已经有的话就不用重复安装了。
还有哪些不足
几个目前没做好的地方,先摆出来:
- 手机端:触屏的捏合缩放、双指拖动这些还没有专门适配
- 图片导出:导出的图片不包含左上角的指标数值标签(那部分是 DOM 元素,不在 Canvas 上)
- WebSocket:暂时只有轮询,还没对接实时推送
这些都在计划中,后面会陆续补上。
写在最后
本来只是想解决手头的需求,没想到越写越多,最后索性做成了一个完整的组件库发了出来。
如果你正好有在 React 项目中展示 K 线图的需求,不妨装上试试。遇到问题欢迎在 GitHub 提 issue,PR 更好。
顺手点个 Star 就更好了,我写那些技术指标公式真的掉了不少头发。
- 在线演示: https://chengzuopeng.github.io/kline-charts-react/
- GitHub: https://github.com/chengzuopeng/kline-charts-react
- npm: https://www.npmjs.com/package/kline-charts-react
- stock-sdk 文档: https://stock-sdk.linkdiary.cn/
- License: MIT