在做行情数据处理时,K线生成一直是比较基础但容易被忽略的一环。很多平台会直接提供分钟线、小时线等标准数据,但当策略需要自定义周期,比如30秒K线、5分钟K线或者特殊时间窗口时,就需要根据历史Tick数据重新计算。
我之前处理加密货币行情时,也尝试过自己合成K线。刚开始关注点更多放在价格计算上,后来才发现,一根K线是否准确,不只是开高低收四个字段的问题,Tick数据的时间顺序和归属周期同样会影响最终结果。
使用加密货币api获取历史Tick数据后,一根K线通常由Open、High、Low、Close四个价格组成。其中开盘价的确定方式比较简单,就是取当前周期内第一笔成交价格。
例如生成10点到10点1分这一分钟K线,Tick数据如下:
10:00:02 62000 10:00:15 62020 10:00:38 61990 10:00:55 62040
这一分钟K线的开盘价就是62000,收盘价则是62040。最高价和最低价分别取这一时间范围内的最大值和最小值。
这里比较关键的一点是,Tick数据必须按照成交时间排序。如果时间顺序出现变化,第一条数据就可能不是实际成交中的第一笔,最终生成的K线也会出现偏差。
在实际数据处理中,时间戳往往比价格计算更容易影响结果。不同行情接口返回的数据格式可能不同,有的是毫秒时间戳,有的是UTC时间,有的是交易所本地时间。
如果没有统一时间标准,同一笔成交可能被划分到错误的K线周期。
比如:
12:00:59 价格30000 12:01:00 价格30020
如果时间精度处理不准确,第二笔数据可能仍然归入上一分钟,那么下一根K线的开盘价自然会发生变化。
我的处理方式一般是保留原始时间字段,统一转换时间格式后,再按照目标周期进行分组。这样生成K线时,第一条Tick数据才能真正代表这一周期的开盘价格。
除了历史数据,实时行情中也会有自定义K线需求。例如实时图表展示或者指标计算,都需要持续接收Tick并更新当前周期。以 AllTick API 为例,可以通过WebSocket获取实时Tick数据,根据时间判断当前数据属于哪个K线周期。
import websocket
import json
from datetime import datetime
bar = {}
def on_message(ws, message):
data = json.loads(message)
price = float(data["price"])
timestamp = data["timestamp"]
minute = datetime.fromtimestamp(
timestamp / 1000
).strftime("%Y-%m-%d %H:%M")
global bar
if bar.get("time") != minute:
bar = {
"time": minute,
"open": price,
"high": price,
"low": price,
"close": price
}
else:
bar["high"] = max(bar["high"], price)
bar["low"] = min(bar["low"], price)
bar["close"] = price
ws = websocket.WebSocketApp(
"wss://api.alltick.co/stock/websocket",
on_message=on_message
)
ws.run_forever()
这段逻辑的核心就是,新周期开始时接收到的第一笔价格作为开盘价,后续Tick不断更新最高价、最低价和收盘价。
实际应用中,还有几个细节值得关注。
部分行情数据可能存在重复推送,需要根据时间和成交标识进行过滤。部分交易对短时间内没有成交,也需要提前定义是否生成空K线。
另外,不同币种的价格精度不同,计算阶段最好保留原始精度,展示阶段再进行格式化,避免因为小数处理影响结果。
从Tick生成K线,本身并不是复杂的计算过程,真正影响结果的是数据处理方式。开盘价虽然只是K线中的一个字段,但它依赖准确的时间排序和周期划分。
在使用加密货币api进行行情分析时,基础数据处理稳定之后,后续无论是指标计算还是策略验证,都会更加可靠。很多时候,行情系统的准确性并不来自复杂算法,而是来自这些细节上的处理。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048654/viewspace-3181164/ ,如需转载,请注明出处,否则将追究法律责任。