一句话结论:89.6% 的日子,今天日盘会突破昨天日盘高低点的至少一侧;两边都没破的有 10.4%。
单看一边:昨日高点被突破的概率是 55.7%,昨日低点是 43.7%。
作用:当你今天已经明确了要做哪个方向,把这个方向上的昨日高点或低点当作目标位,是一个相对可靠的选择。
最近看阿布先生的过往直播,听到他多次提到昨天高低点的“90% 法则”。我用 ES 2010 到 2026 年清洗后的数据做了回测,专门看一件事:今天会不会突破昨天的最高点或最低点。
2010–2026 年 · 至少突破昨日高低点一侧
89.6%
样本 3816 个交易日
只破上
46.0%
1755 天
只破下
34.0%
1297 天
两边都破
9.7%
369 天
都没破
10.4%
395 天
逐年分布右侧是至少突破一侧的比例,点某一年只看这一年。
两种参照线对比2010–2026 年
结论:几乎就是 90% 法则
3816 个交易日里,89.6% 的日子至少突破了昨日高低点的一侧,几乎就是 Al Brooks 说的 90%。
而且很稳定:逐年都在 80.0% 到 93.2% 之间,最低的 2017 年也没有掉到 80% 以下。
也就是说,昨天的高点和低点,是图表上最可靠的两个磁吸位。开盘前把它们标出来,今天大概率会去测试其中至少一个。
剩下的日子:各占一成左右
- 两边都没破(10.4%):今天整天被关在昨天的区间里,也就是 inside day。
- 两边都破(9.7%):先破一边,又反向破另一边,通常是大波动或者来回扫的日子,也就是 outside day。
这两种都比较少见,也都是突破策略容易失败的日子。
方向偏向:上破比下破多
只破上 46.0%,只破下 34.0%,差了 12 个百分点。16 年里只有 2022 年是下破多于上破。
这是不是因为样本里大部分年份在上涨?用数据核对了一下,有关系,但不是一一对应:
| 年份 | ES 全年涨跌 | 只破上 | 只破下 |
|---|---|---|---|
| 2011 | −0.8% | 42.9% | 39.9% |
| 2018 | −6.7% | 43.3% | 33.5% |
| 2022 | −19.0% | 39.9% | 42.9% |
全年涨跌:这一年第一个交易日日盘的开盘价,到最后一个交易日日盘的收盘价。连续合约没有复权,换约时的价差也算在里面,所以只是近似值。
2011 和 2018 年全年下跌,昨日高低点仍然是上破更多;只有 2022 年这样全年跌了 19% 的熊市,才把方向反过来。所以上破偏多是常态,遇到持续下跌的熊市才需要切换。
逐年看:命中率能反映市场状态
2017 年命中率最低,只有 80.0%:那年波动极小,有两成的日子闷在昨天的区间里。2022、2013、2020 这些趋势明显或波动大的年份,命中率都在 92% 以上。
所以当你发现昨日高低点频繁被突破,说明市场进入了活跃期;当 inside day 变多,说明在盘整,这时候突破策略就该收手。
和夜盘高低点比
切换到“夜盘高低点”会看到,夜盘区间被突破的比例更高(94.4%),两边都破的比例也是昨日的两倍多(21.2% 对 9.7%)。
原因是两个区间的宽度不一样:昨天日盘的区间和今天日盘差不多宽,宽度比的中位数是 1.01;夜盘区间更窄,中位数只有当天日盘的 0.77。区间越窄,单边被突破或者两边都被突破的概率相对更高。详见突破夜盘高低点。
定义和复现
突破昨日高低点
- 数据:清洗后的 ES 1 分钟 K 线,2010-06 到 2026-09,清洗方法见这篇。
- 日盘:美东 09:30–16:15,也就是 1 分钟 K 线从 09:30 到 16:14,5 分钟 K 线 81 根。不含夜盘。
- 昨日高点 / 低点:昨天日盘所有 K 线的最高价 / 最低价。今天也只看日盘。
- 昨天是哪一天:今天之前最近的一个股市交易日。节假日股市休市,后一天就用节前最后一个交易日,比如马丁·路德·金纪念日后的周二,昨天是上周五。
- 跳过的日子:昨天被清洗掉了(半日市、换约的周一等),或者两天不是同一个合约,今天就不算,不往前找。一共跳过 108 天,剩下 3816 天。
- 向上突破:今天日盘最高价严格高于昨日高点,也就是至少高 1 个跳动单位(0.25 点)。正好等于不算。高开在昨日高点之上也算突破。
- 向下突破:今天日盘最低价严格低于昨日低点。
- 四种结果:只破上、只破下、两边都破、都没破。
我有一份清洗过的 ES 期货 1 分钟 K 线 CSV(Databento 的 ES.c.0 连续合约,列有 ts_event、instrument_id、high、low,时间是 UTC)。请帮我写 Python 代码,统计“今天日盘有没有突破昨天日盘的最高点或最低点”。规则如下: 1. 时间先转成美东时间(US/Eastern),自动处理夏令时。日盘 = 09:30–16:15,也就是 1 分钟 K 线从 09:30 到 16:14(405 根),不含夜盘。 2. 昨日高点 / 低点 = 昨天日盘所有 K 线的最高价 / 最低价。今天的最高价 / 最低价也只看今天日盘。 3. “昨天”是今天之前最近的一个股市交易日,用纽交所日历判断:股市休市的节假日跳过(比如马丁·路德·金纪念日后的周二,昨天是上周五)。请用 pandas 自带的节假日规则写纽交所休市日,再加上 2012-10-29、2012-10-30、2018-12-05、2025-01-09 这几天临时休市。 4. 如果这个“昨天”不在我的数据里(被清洗掉了),今天就跳过,不要再往前找;如果两天的 instrument_id 不同(不是同一个合约),也跳过。 5. 向上突破:今天日盘最高价严格大于昨日高点(等于不算,也就是至少高 1 个跳动单位 0.25)。向下突破:今天日盘最低价严格小于昨日低点。 6. 每天归入四种结果之一:只破上、只破下、两边都破、都没破。打印样本天数、四种结果的占比、至少突破一侧的比例,再按年份列一张表。 请每一步加中文注释,说明为什么这样做。
# 突破昨日高低点:今天日盘有没有突破昨天日盘的最高点 / 最低点
# 输入:清洗后的 ES 1 分钟 K 线(Databento ES.c.0,时间是 UTC,含 instrument_id 列)
import numpy as np
import pandas as pd
from pandas.tseries.holiday import (
AbstractHolidayCalendar, Holiday, GoodFriday, USMartinLutherKingJr, USPresidentsDay,
USMemorialDay, USLaborDay, USThanksgivingDay, nearest_workday, sunday_to_monday,
)
class NYSE(AbstractHolidayCalendar): # 纽交所全天休市日
rules = [
Holiday("元旦", month=1, day=1, observance=sunday_to_monday),
USMartinLutherKingJr, USPresidentsDay, GoodFriday, USMemorialDay,
Holiday("六月节", month=6, day=19, start_date="2022-01-01", observance=nearest_workday),
Holiday("独立日", month=7, day=4, observance=nearest_workday),
USLaborDay, USThanksgivingDay,
Holiday("圣诞节", month=12, day=25, observance=nearest_workday),
]
CLOSED = pd.to_datetime(["2012-10-29", "2012-10-30", "2018-12-05", "2025-01-09"]) # 临时休市
df = pd.read_csv("ES-1min_标准版.csv", usecols=["ts_event", "instrument_id", "high", "low"])
t = pd.to_datetime(df.ts_event, utc=True).dt.tz_convert("US/Eastern").dt.tz_localize(None)
hm = t.dt.hour * 100 + t.dt.minute
rth = df[(hm >= 930) & (hm < 1615)].assign(date=t.dt.normalize()) # 日盘 09:30–16:15
day = rth.groupby("date").agg(hi=("high", "max"), lo=("low", "min"), contract=("instrument_id", "first"))
# 昨天 = 上一个股市交易日(节假日后那天,用节前最后一个交易日)
cal = pd.bdate_range(day.index.min() - pd.Timedelta(days=10), day.index.max())
cal = cal[~cal.isin(NYSE().holidays(cal.min(), cal.max()).union(CLOSED))]
prev = pd.Series(cal[:-1], index=cal[1:]).reindex(day.index)
today = day[prev.isin(day.index)] # 昨天也必须在清洗后的数据里,否则跳过
yday = day.loc[prev[today.index]].set_index(today.index)
same = today.contract == yday.contract # 两天必须是同一个合约
today, yday = today[same], yday[same]
up = today.hi > yday.hi # 严格高于,等于不算
down = today.lo < yday.lo
cls = pd.Series(np.select([up & down, up, down], ["两边都破", "只破上", "只破下"], "都没破"), index=today.index)
print("样本天数", len(cls))
print((cls.value_counts(normalize=True) * 100).round(1).to_string())
print("至少破一侧 %.1f%%" % (100 * (cls != "都没破").mean()))局限
- 只看有没有突破,没看突破了多远:超出 1 个跳动单位就算突破,所以这个数字说明昨日高低点会被测试,不说明突破之后能走多远、会不会站稳。
- 上破偏多是常态,但不是永远成立:像 2022 年这样持续下跌的熊市,方向会反过来。
- 跳过了节假日和换约前后的日子:这些日子本来就不正常,但统计结果不代表它们。
(本文首发于小红书。2026 年 10 月更新:改用清洗后的数据,日盘统一为 09:30–16:15,数字随之更新;加入可交互统计和复现卡片。)