k线我们天天都在用,不管是分钟k线,日k线,月k线还是年k线,可以你知道一根k线是怎样形成的吗?
一根k线的数据结构是这样的,它包含一个时间戳,代表k线起始的时间,开盘价,最高价,最低价,收盘价和成交量,我们都很熟悉:
{
Time : 1567736576000, // 一个时间戳,精确到毫秒,与Javascript的new Date().getTime()得到的结果格式一样
Open : 1000, // 开盘价
High : 1500, // 最高价
Low : 900, // 最低价
Close : 1200, // 收盘价
Volume : 1000000 // 交易量 }
但是,原始的k线是不存在的,每一根k线都是由tick数据合成的。
{
Info : {...},
High : 1000, // 最高价
Low : 500, // 最低价
Sell : 900, // 卖一价
Buy : 899, // 买一价
Last : 900, // 最后成交价
Volume : 10000000, // 最近成交量
Time : 1567736576000 // 毫秒级别时间戳
}
K线是通过将tick数据按照一定的时间间隔进行合并而生成的。一种常见的方法来合成K线是这样的:
确定K线的时间间隔:首先,你需要确定每个K线的时间间隔,例如1分钟、5分钟、15分钟等。这个时间间隔决定了每个K线的时间范围。
收集tick数据:从交易所获取到的tick数据包含了每一笔交易的价格、成交量和时间戳等信息。你需要收集足够多的tick数据来生成K线。
分组tick数据:将收集到的tick数据按照时间间隔进行分组。对于每个时间间隔,你需要将对应时间范围内的tick数据进行分组。
计算K线数据:对于每个时间间隔的tick数据分组,你可以根据需要计算K线的开盘价、最高价、最低价、收盘价和成交量等数据。常见的计算方法包括:
生成K线:根据计算得到的K线数据,你可以生成相应的K线。每个K线包含了开盘价、最高价、最低价、收盘价和成交量等信息。
需要注意的是,K线的合成方法可能因交易所和数据源而异。有些交易所可能提供直接的K线数据,而无需手动合成。此外,还有其他的K线合成方法,例如基于成交量、价格范围等的合成方法。具体的合成方法取决于你的需求和数据源的特点。
那么你现在知道k线是怎么合成出来了,可是你知道怎么画一根k线吗?
var cfgA = [{
__isStock: true,
title: {
text: 'A'
},
series: [{
type: 'candlestick',
name: 'A',
id: 'A',
data: []
}]
}];
function main() {
var symbols = "rb888";
var chart = Chart(cfgA);
chart.reset();
var arrLastTime = 0;
while (true) {
if (exchange.IO("status")) {
LogStatus("时间:", _D(), ",已经连接");
exchange.SetContractType(symbols);
var r = exchange.GetRecords();
for (var j = 0; j < r.length; j++) {
if (r[j].Time > arrLastTime) {
// 增加
chart.add(0, [r[j].Time, r[j].Open, r[j].High, r[j].Low, r[j].Close]);
arrLastTime = r[j].Time;
}
else if (r[j].Time == arrLastTime) {
// 更新
chart.add(0, [r[j].Time, r[j].Open, r[j].High, r[j].Low, r[j].Close], -1);
}
}
chart.update(cfgA);
}
Sleep(5000);
}
}
前面的图表设置我们不必于太过于关心,这里我们需要关注的是k线的数据是怎样添加的,让我们回到交易所接口返回的k线数据:
2023-07-12 09:02:00 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3694,"Volume":9784,"OpenInterest":1799446},{"Time":1689123660000,"Open":3694,"High":3696,"Low":3693,"Close":3695,"Volume":5541,"OpenInterest":1798668},{"Time":1689123720000,"Open":3695,"High":3695,"Low":3695,"Close":3695,"Volume":0,"OpenInterest":1799071}]
2023-07-12 09:01:58 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3694,"Volume":9784,"OpenInterest":1799446},{"Time":1689123660000,"Open":3694,"High":3696,"Low":3693,"Close":3695,"Volume":5541,"OpenInterest":1798668}]
2023-07-12 09:01:37 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3694,"Volume":9784,"OpenInterest":1799446},{"Time":1689123660000,"Open":3694,"High":3696,"Low":3693,"Close":3696,"Volume":2770,"OpenInterest":1798668}]
2023-07-12 09:01:22 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3694,"Volume":9784,"OpenInterest":1799446},{"Time":1689123660000,"Open":3694,"High":3694,"Low":3693,"Close":3693,"Volume":1847,"OpenInterest":1798668}]
2023-07-12 09:01:00 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3694,"Volume":9784,"OpenInterest":1799446},{"Time":1689123660000,"Open":3694,"High":3694,"Low":3694,"Close":3694,"Volume":0,"OpenInterest":1798668}]
2023-07-12 09:00:58 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3694,"Volume":9784,"OpenInterest":1799446}]
2023-07-12 09:00:37 信息 Records数据 [{"Time":1689123600000,"Open":3692,"High":3696,"Low":3692,"Close":3696,"Volume":4892,"OpenInterest":1799446}]
我们设置的周期为1分钟,有没有感到一点奇怪,为什么最后一根k线的数据不是固定的呢,可以看到时间是一样的,除了开盘价,其他值一直在变动:
只有到了新的时间段(Time),倒数第二个数据才算固定下来。OHLC和成交量都固定下来。
这是因为k线是被合成出来的,当最新的k线周期没有完成的时候,最后一根k线不是固定的,如果这里你理解了,你就可以明白了k线的数据是怎样添加的了。
循环语句 for (var j = 0; j < r.length; j++) 遍历了 r 数组中的所有元素,该数组包含了当前品种最新的 K 线数据。通过遍历 r 数组并将每个元素添加到当前品种对应的系列中,实现了将最新的 K 线数据添加到图表中并刷新的效果。在每次添加完数据之后,通过更新 arrLastTime 数组来记录最新的时间戳,并用于判断下一次是否需要添加/更新数据。
这里的数据添加和更新很有意思,如果上一根k线已经走完,就是新的时间戳大于上一个周期的时间戳,表示新的k线已经产生,这时候就要增加最新的数据。
if (r[j].Time > arrLastTime) {
// 增加
chart.add(0, [r[j].Time, r[j].Open, r[j].High, r[j].Low, r[j].Close]);
arrLastTime = r[j].Time;
}
而如果此时的k线周期还没有完成,最新的k线数据还没有固定,这时候就要不断的更新最新的k线数据,add函数里最后使用-1进行k线数据的更新。
else if (r[j].Time == arrLastTime) {
// 更新
chart.add(0, [r[j].Time, r[j].Open, r[j].High, r[j].Low, r[j].Close], -1);
}
综上,这个 for 循环共同实现了将最新的 K 线数据添加到对应的系列中,用于刷新图表并展示最新的数据。
这就是一根k线的故事,希望大家有所收获。