LAG()和LEAD()在K线分析中用于高效提取相邻K线的open、close、high、low等字段,从而计算涨跌幅、实体方向、突破信号及多根组合形态(如启明星),必须配合精确时间排序的OVER子句,避免自连接,一行SQL实现时序逻辑。

LEAD() 和 LAG() 在 K 线分析中到底能干什么?
它们不能直接画出 K 线图,但能高效提取「前一根」或「后一根」K 线的关键字段(如 open、close、high、low),从而计算涨跌幅、突破信号、连续阳线计数等指标。核心价值在于:避免自连接,一行 SQL 表达时序逻辑。
必须按时间排序,且不能用 GROUP BY
LEAD() 和 LAG() 是窗口函数,依赖 ORDER BY 定义“前后”。股票数据必须用精确到秒/毫秒的 datetime 排序,不能只用日期;否则同日多根 K 线顺序不确定,结果随机。常见错误是漏写 ORDER BY 或仅按 date 排序:
SELECT datetime, close, LAG(close, 1) OVER (ORDER BY datetime) AS prev_close FROM kline_1min;
以下写法是错的(会导致非确定性结果):
-
LAG(close) OVER ()—— 没有ORDER BY -
LAG(close) OVER (ORDER BY date)—— 同日多条记录顺序未定义
用 LAG() 计算单根 K 线的涨跌幅和实体方向
实体方向(阳线/阴线)和相对前一日的涨跌幅是最基础信号。注意:K 线的 close 与 open 比较判断当日方向,而涨跌幅通常用 close / LAG(close) - 1。
SELECT datetime, open, close, high, low, CASE WHEN close > open THEN '阳线' ELSE '阴线' END AS body_type, ROUND((close / LAG(close) OVER (ORDER BY datetime) - 1) * 100, 2) AS change_pct FROM kline_1min;
关键细节:
-
LAG(close)默认取前 1 行,第 1 条记录返回NULL,需用COALESCE(..., 0)处理 - 除零风险不存在(
LAG(close)为 0 才会出问题,但股价不会为 0),但空值必须显式处理 - 若用分钟级数据算“日涨跌幅”,需先按日聚合再开窗,不能直接在分钟表上
LAG()跨日
用 LEAD() + LAG() 组合识别典型 K 线形态
例如“启明星”(三根K线:大阴线 + 小实体十字星 + 大阳线)需要同时看前1根、当前、后1根。此时需两个窗口函数并存:
SELECT datetime, close, LAG(close, 1) OVER w AS prev_close, LEAD(close, 1) OVER w AS next_close, LAG(high, 1) OVER w AS prev_high, LAG(low, 1) OVER w AS prev_low FROM kline_1min WINDOW w AS (ORDER BY datetime);
注意点:
- 重复写
OVER (ORDER BY datetime)很冗余,用WINDOW w AS (...)命名窗口更清晰(PostgreSQL / MySQL 8.0+ / SQL Server 支持) - 形态识别逻辑(如“第二根实体长度 WHERE 或
CASE,不在窗口子句里做计算 - 跨多根 K 线的形态(如“五连阳”)更适合用
COUNT(*) OVER (ORDER BY datetime ROWS BETWEEN 4 PRECEDING AND CURRENT ROW),而非嵌套多个LAG()
真正难的不是函数语法,而是对 K 线定义的理解是否和你的交易系统一致——比如“十字星”的上下影线比例阈值、是否排除停牌日、复权状态是否统一。这些业务规则一旦错,窗口函数算得再快也没用。

















