实时分时图制作步骤有哪些?新手如何快速上手?
摘要:
核心概念:实时分时图是什么?实时分时图(Real-time Time & Sales Chart 或 Real-time Tick Chart)是一种在金融、股票、加密货币... 核心概念:实时分时图是什么?
实时分时图(Real-time Time & Sales Chart 或 Real-time Tick Chart)是一种在金融、股票、加密货币等领域常见的图表,它的核心特点是:
- X轴(时间轴):通常显示的是交易发生的时间点,精确到秒或毫秒,在实时场景下,时间轴会不断向右延伸。
- Y轴(价格轴):显示的是每次成交的价格。
- 数据点(K线/成交量柱):在每个时间点上,图表会显示该时间点成交的价格和成交量,最常见的表现形式是:
- 价格线:将每个成交价格点连接起来,形成一条价格波动的曲线。
- 成交量柱:在每个时间点(或价格点)下方,用一根垂直的柱状图表示该时间点的成交量大小,红/绿(或黑/白)颜色通常表示涨跌。
技术架构与选型
要实现一个实时分时图,你需要一个完整的技术栈,大致分为三个部分:
| 层次 | 功能 | 技术选型 |
|---|---|---|
| 数据源 | 提供实时行情数据 | WebSocket API (主流), REST API (轮询) (备用) |
| 后端 | 接收、处理、转发数据 | Node.js (EventEmitter, 高并发), Python (asyncio), Go (性能强) |
| 前端 | 接收数据并渲染图表 | JavaScript库 |
前端图表库推荐
选择一个强大的前端库是成功的关键,以下是几个主流选择:
-
ECharts (Apache ECharts)
- 优点:功能极其强大,配置灵活,对中文支持友好,有官方的实时数据更新示例,社区活跃。强烈推荐初学者和项目使用。
- 官网:https://echarts.apache.org/
-
TradingView Charting Library
- 优点:专业级图表库,性能极佳,交互体验(如缩放、平移)流畅,是许多专业交易软件(如TradingView平台、同花顺、东方财富)背后的技术,商业项目需要付费。
- 官网:https://www.tradingview.com/charting-library-docs/
-
Lightweight Charts (by TradingView)
- 优点:同样是TradingView出品,但更轻量、更现代化,专注于高性能渲染,非常适合移动端和需要高刷新率的场景,开源免费。
- 官网:https://www.tradingview.com/lightweight-charts/
本教程将以 ECharts 为例,因为它免费、功能全面且文档清晰。
详细制作步骤
我们将分步完成一个简单的实时分时图。
步骤 1:准备工作(HTML & ECharts 引入)
创建一个 index.html 文件,并引入 ECharts 的库。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">实时分时图示例</title>
<!-- 1. 引入 ECharts 文件 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<style>
body { margin: 0; font-family: Arial, sans-serif; }
#chart-container { width: 100%; height: 80vh; }
</style>
</head>
<body>
<!-- 2. 准备一个具备大小(宽高)的 DOM 容器 -->
<div id="chart-container"></div>
<!-- 3. 编写 JS 代码 -->
<script src="app.js"></script>
</body>
</html>
步骤 2:初始化图表(app.js)
在 app.js 中,我们首先初始化 ECharts 实例,并设置图表的基本配置。
// app.js
// 1. 初始化 ECharts 实例
const chartDom = document.getElementById('chart-container');
const myChart = echarts.init(chartDom);
// 2. 图表配置项
const option = {
// 标题 {
text: '实时分时图演示 (模拟数据)'
},
// 工具箱
toolbox: {
feature: {
dataZoom: { // 区域缩放
yAxisIndex: 'none'
},
restore: {}, // 还原
saveAsImage: {} // 保存为图片
}
},
// 提示框
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
// 网格
grid: [
{
left: '10%',
right: '10%',
height: '60%' // 价格图占60%的高度
},
{
left: '10%',
right: '10%',
top: '75%',
height: '20%' // 成交量图占20%的高度
}
],
// X轴
xAxis: [
{
type: 'category', // 类目轴
data: [], // 初始为空,后续动态添加
gridIndex: 0, // 关联到第一个 grid
axisLabel: {
show: false // 隐藏部分X轴标签,避免拥挤
},
axisLine: { show: false },
axisTick: { show: false }
},
{
type: 'category',
data: [],
gridIndex: 1, // 关联到第二个 grid
axisLabel: {
show: true
}
}
],
// Y轴
yAxis: [
{
type: 'value', // 数值轴
gridIndex: 0, // 关联到第一个 grid (价格)
scale: true, // 自适应
name: '价格'
},
{
type: 'value',
gridIndex: 1, // 关联到第二个 grid (成交量)
name: '成交量'
}
],
// 数据系列
series: [
{
name: '价格',
type: 'line', // 折线图
data: [], // 初始为空
smooth: true, // 平滑曲线
xAxisIndex: 0,
yAxisIndex: 0,
showSymbol: false, // 不显示每个数据点的标记
lineStyle: {
width: 1.5
}
},
{
name: '成交量',
type: 'bar', // 柱状图
xAxisIndex: 1,
yAxisIndex: 1,
data: [] // 初始为空
}
]
};
// 3. 使用配置项显示图表
myChart.setOption(option);
你打开 index.html 会看到一个空的图表框架。
步骤 3:模拟实时数据流
在真实项目中,数据来自 WebSocket,为了演示,我们使用 setInterval 来模拟一个不断产生新数据的流。
// app.js (接在上一段代码后面)
// --- 模拟数据生成器 ---
let basePrice = 100;
const generateNewTick = () => {
// 随机生成一个微小价格变动
const priceChange = (Math.random() - 0.5) * 0.5;
basePrice += priceChange;
// 获取当前时间
const now = new Date();
const timeStr = now.toTimeString().split(' ')[0] + '.' + String(now.getMilliseconds()).padStart(3, '0');
// 返回一个数据点 { time, price, volume }
return {
time: timeStr,
price: Number(basePrice.toFixed(2)),
volume: Math.floor(Math.random() * 1000) + 100 // 随机成交量
};
};
// --- 数据更新逻辑 ---
const maxDataPoints = 50; // 最多显示50个数据点,避免内存无限增长
const updateChart = () => {
const newTick = generateNewTick();
// 获取当前的数据
let timeData = myOption.xAxis[0].data;
let priceData = myOption.series[0].data;
let volumeData = myOption.series[1].data;
// 添加新数据
timeData.push(newTick.time);
priceData.push([newTick.time, newTick.price]); // ECharts 的 line data 格式是 [x, y]
volumeData.push([newTick.time, newTick.volume]); // ECharts 的 bar data 格式是 [x, y]
// 保持数据长度
if (timeData.length > maxDataPoints) {
timeData.shift();
priceData.shift();
volumeData.shift();
}
// 更新图表
myChart.setOption(myOption);
};
// --- 启动定时器,模拟实时更新 ---
const updateInterval = setInterval(updateChart, 500); // 每500毫秒更新一次
// 为了演示,5秒后停止更新
setTimeout(() => {
clearInterval(updateInterval);
console.log('数据流已停止。');
}, 5000);
注意:这里我们把 option 对象提取为 myOption 以便在 updateChart 函数中修改,完整的 app.js 应该将 option 重命名为 myOption。
再次打开 index.html,你就能看到图表开始动态更新,价格线在波动,成交量柱在增长。
步骤 4:连接真实数据源(WebSocket)
这是将“模拟”变为“真实”的关键一步,假设你有一个提供股票行情的 WebSocket 服务。
以 ws://your-data-provider.com/stock-quote 为例:
// app.js (替换掉模拟数据的部分)
// ... (前面的 ECharts 初始化代码保持不变) ...
// --- 真实 WebSocket 连接 ---
const socket = new WebSocket('ws://your-data-provider.com/stock-quote');
socket.onopen = function(event) {
console.log('WebSocket 连接已建立!');
// 可以在这里发送订阅消息,socket.send(JSON.stringify({action: 'subscribe', symbol: 'AAPL'}));
};
socket.onmessage = function(event) {
try {
const data = JSON.parse(event.data); // 假设数据是 JSON 格式
// console.log('收到数据:', data);
// 假设数据格式为: { symbol: 'AAPL', price: 150.25, volume: 500, timestamp: 1678886400000 }
const newTick = {
time: new Date(data.timestamp).toLocaleTimeString(), // 转换为时间字符串
price: data.price,
volume: data.volume
};
// --- (下面的数据更新逻辑与模拟部分完全相同) ---
const maxDataPoints = 50;
let timeData = myOption.xAxis[0].data;
let priceData = myOption.series[0].data;
let volumeData = myOption.series[1].data;
timeData.push(newTick.time);
priceData.push([newTick.time, newTick.price]);
volumeData.push([newTick.time, newTick.volume]);
if (timeData.length > maxDataPoints) {
timeData.shift();
priceData.shift();
volumeData.shift();
}
myChart.setOption(myOption);
} catch (error) {
console.error('解析数据时出错:', error);
}
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`连接已关闭,代码=${event.code},原因=${event.reason}`);
} else {
console.error('连接异常中断');
}
};
socket.onerror = function(error) {
console.error(`WebSocket 错误: ${error.message}`);
};
优化与高级功能
-
性能优化:
- 数据采样:当数据量极大时(如高频交易),可以考虑对数据进行采样或聚合,避免渲染过多数据点导致卡顿。
large模式:ECharts 为大数据量提供了large模式,开启后可以优化渲染性能。- 防抖:如果数据更新频率极高(如每秒上百次),可以考虑使用防抖技术,将多次更新合并为一次,减少渲染次数。
-
交互功能:
- 区域缩放:ECharts 默认的
toolbox.dataZoom已经提供了基本的缩放功能,用户可以通过鼠标拖拽来放大或缩小特定时间区域。 - 十字准线:通过配置
tooltip.axisPointer.type: 'cross',可以实现鼠标悬停时的十字准线,方便查看特定时间点的价格和成交量。
- 区域缩放:ECharts 默认的
-
K线图与分时图切换:
- 很多应用允许用户在分时图和K线图之间切换,这可以通过动态地改变
series的type属性('line'vs'candlestick')和xAxis的type属性('category'vs'time')来实现,并配合不同的数据源。
- 很多应用允许用户在分时图和K线图之间切换,这可以通过动态地改变
制作一个实时分时图的核心流程可以概括为:
- 选择工具:根据需求选择合适的前端图表库(如 ECharts)。
- 搭建框架:初始化图表,配置好基本的网格、坐标轴和数据系列,使其具备分时图的“骨架”。
- 获取数据:通过 WebSocket 建立与数据源的持久连接,这是实现“实时”的基础。
- 更新渲染:编写逻辑,在接收到新数据时,更新图表内部的数据数组,并调用
setOption方法将变化渲染到页面上,注意控制数据量,防止内存溢出。 - 迭代优化:根据实际使用情况,添加性能优化、交互功能和更复杂的业务逻辑。
希望这份详细的指南能帮助你成功制作出自己的实时分时图!
作者:咔咔本文地址:https://www.jits.cn/content/83.html发布于 10-30
文章转载或复制请以超链接形式并注明出处杰思科技・AI 股讯



还没有评论,来说两句吧...