Skip to content

chengzuopeng/kline-charts-react

Repository files navigation

KLine Charts

📈 专业级股票 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-react

Peer Dependencies

npm install react react-dom echarts

快速开始

import { 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

受控 / 非受控

periodadjustindicators 支持受控模式;defaultPerioddefaultAdjustdefaultIndicators 用于非受控默认值。

// 非受控
<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}
/>

KlineData 数据结构

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;     // 换手率(可选)
}

TimelineData 数据结构

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」,此时无昨收基准。

无限滚动加载历史(loadMore)

日/周/月 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 均可):组件会去重并按日期 升序归并后再渲染。

使用 Ref 控制图表

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" />
    </>
  );
}

unstable 二级导出

主入口只保留稳定导出。如果你明确需要内部 hooks / 子组件,请从 kline-charts-react/unstable 引入:

import { useKlineData, Toolbar } from 'kline-charts-react/unstable';

API 文档

KLineChartProps

属性 类型 默认值 说明
symbol string 必填 股票代码,如 sh600519sz000001
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 - 错误回调

RequestOptions

字段 类型 默认值 说明
debounceMs number 150 参数变化后的请求防抖时间
abortOnChange boolean true 参数变化时是否中止上一次请求(内置数据源的网络层不支持中止,仅丢弃过期结果)
dedupe boolean true 相同请求(同数据源 + 同参数)是否走缓存与去重
loadMoreLimit number 180 滚动加载历史时每次请求的条数(传给 getKlinelimit

KLineChartRef

方法 说明
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[],已附带指标字段)

PeriodType

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)。

IndicatorType

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 即为直连)。

如果你的部署环境仍遇到跨域拦截(例如目标端点策略变化、内网安全网关拦截),推荐:

自定义 DataProvider(推荐)

用自己的后端聚合/代理行情数据,前端只对同源接口取数——这同时解决跨域、鉴权与 数据合规问题:

<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 会执行 linttypechecktest:runbuildbuild:playgroundpack: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 里自行展示

License

MIT © 2025-present chengzuopeng

About

基于 ECharts,内置 Stock SDK 数据源,开箱即用的专业级股票 K 线图表 React 组件。

Topics

Resources

License

Stars

18 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages