我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

缠论笔段复盘:1分钟与5分钟行情数据清洗实战指南

缠论笔段复盘:1分钟与5分钟行情数据清洗实战指南 简介缠中说禅课程配套的上证指数历史复盘数据包重点服务于缠论学习者与实战复盘者尤其对应第56至61课涉及的线段划分与走势理解。数据覆盖2000年至2009年共十年行情包含1分钟与5分钟两种周期K线配合飞狐软件使用解压后置于步步为盈00-04、05-09目录打开FoxTrader.exe即可查看左右分屏的走势界面可自由切换周期并锁定时间便于逐课对照复盘。资源共2000个文件以行情数据文件为主含大量sbk、dll、exe、txt等类型压缩包约32.82MB已吸引1164人学习下载。通过直观图表还原当年大盘实况可弥补早期缠论教学无图辅助的想象偏差帮助读者在真实行情中体会线段划分规则逐步建立缠论盘感适合反复研读原课并自行验证划分思路。1. 缠中说禅课程配齐了但要复现他的笔段你得先解决 1 分钟和 5 分钟行情数据缠论学习者最容易卡住的地方不在背口诀而在打开行情软件盯了半天连一笔都画不利索。缠中说禅的课程和 2000 到 2008 年上证指数 1 分钟、5 分钟级别的复盘资料摆在一起其实就是一句话光看 30 分钟图意淫趋势没有用得回到分钟级别去验证笔、线段和中枢的递归过程。这些年我帮人做过不少缠论量化回测头一件事永远是找齐干净的分时数据而不是急着写画笔算法。这个标题指向的东西并不玄学它是一套「课程讲解 历史行情数据」的组合目的是让你拿着 2000 年到 2008 年上证指数的分钟级数据在图表或者脚本里一帧一帧还原当年缠论定义的走势。适合三类人想把缠论从理论变成实盘肌肉记忆的交易者想做历史回测的量化脚本党以及带学员复盘、需要统一数据口径的培训者。但这套数据有一个绕不开的坎当年互联网上没人给你规规整整打包好 CSV你拿到的往往是裸的原始 tick 或者带各种复权问题的 K 线必须自己清理才能进下一步。下面把这条路的完整走法、参数选择和踩坑记录一次讲透。2. 为什么复盘必须回到 1 分钟与 5 分钟缠论的级别递归与数据粒度缠中说禅的整套体系建立在「走势由级别递归生长」这个前提上。原文反复强调最低级别中枢是由次级别走势重叠构成的而 A0最小分析单位的选择直接决定你看到的笔和线段长什么样。2000 到 2008 年的上证指数横跨完整牛熊从 2245 点跌到 998 点再从 998 点拉到 6124 点这中间有大量教科书级别的趋势背驰和盘整背驰是验证这套理论最理想的时间窗。2.1 1 分钟定笔5 分钟定线段A0 的实战选型逻辑复盘时你至少要准备两套粒度1 分钟图用来定义最小级别笔5 分钟图用来组合线段和确认中枢区间。常见做法是把 1 分钟作为 A05 分钟作为 A1因为缠论原文里最精细的买卖点讨论都落在 1 分钟级别上例如第一类买点往往出现在 1 分钟趋势背驰之后的 V 型反转里。只用 5 分钟做起点当然也能画但你会漏掉很多盘中瞬间的转折信号线段的重叠区间也会被磨平。这里有个容易被新缠友忽略的点K 线的生成规则会直接影响分型的形成。1 分钟图上一根 K 线就是 60 秒内所有成交的聚合5 分钟图则是 300 秒的聚合。在缠论的包含处理里相邻 K 线的高低点完全包含关系要先合并这依赖的是每一根 K 线的 OHLC 而不是只取收盘价。如果你的数据源只给了你收盘价的序列那分型、笔和线段全都无从谈起。所以拿到数据后的第一件事就是确认字段里有 open、high、low、close 和时间戳四项完整信息缺一不可。2.2 2000 到 2008 年这个区间为什么值得精读把复盘区间限定在 2000 到 2008 年的上证指数不是因为这段行情“涨得猛”而是因为它的走势类型足够齐全。这段区间里有连续单边上涨、长期阴跌、急速崩盘、宽幅震荡和底部盘整缠论定义的所有转折形态基本都能找到对应片段。特别是 2005 年 998 点到 2007 年 6124 点的这段 5 分钟级别上涨线段不断延伸中枢逐步上移是一个可以直接用来校验画笔算法正确性的黄金样本。另一个实际原因是 A 股早期数据质量不高越往前分钟数据的缺失越严重。2000 到 2008 年这个区间数据源相对稳定券商行情接口还能追溯到这部分历史再往前的 90 年代数据经常出现大段空白复盘起来连笔都连不齐。选择这段区间做复盘既是理论上的最优解也是数据可得性和质量上的现实均衡。2.3 数据字段标准一分钟 K 线到底需要哪些列无论你从哪个渠道拿原始数据最终都要整理成下表所示的统一结构。别嫌字段多每一列都有用途open 和 close 用于判断分型方向high 和 low 用于包含关系处理volume 在验证背驰时辅助确认放量或缩量。字段名格式示例用途备注datetime2005-06-06 09:31:00时间轴对齐必须是交易所本地时间排除 UTC 偏移open998.23分型起点判断前复权或等比后复权口径统一high1001.52包含关系处理与 low 共同决定 K 线合并方向low997.10包含关系处理不能出现 low high 的脏数据close1000.77笔的终点判定收盘价缺口会影响分型确认volume235100背驰辅助验证单位手或股需统一不要混用我一般会额外生成一列chg_pct用来快速筛出异常跳空后面避坑章节会专门讲它如何定位除权日和数据断裂处。整理好的数据建议存成 Parquet 或 CSV 两种格式Parquet 供 Python 脚本回测CSV 供通达信等图表软件导入。文件命名统一为SH000001_1min_YYYY.csv和SH000001_5min_YYYY.csv按年份切分比单文件几百万行更利于增量复盘。3. 把裸行情清洗成缠论画笔的标准输入下载、对齐、复权三步走很多人拿到一份标着“1 分钟历史数据”的文件就急着往画图软件里塞结果画笔画得七零八落。真相是绝大多数免费分钟级数据都需要二次清洗才能达到缠论画笔的要求。以 8 年上证指数 1 分钟数据为例交易所每个交易日约 240 根 K 线一年大概 5.8 万根八年就是 46 万根。这个量级 Excel 能勉强打开但运行卡顿脚本处理才是正路。3.1 从数据源获取原始分钟线的三种常见渠道早期数据获取没有统一途径常见做法有三条一是从通达信、同花顺的本地导出功能拉历史分钟线但多数版本只允许导出近几年数据2008 年以前的经常被限制二是用免费 Python 数据接口比如 tushare、akshare 或 baostock其中前者需要积分权限后两者在一定程度上能拿到上证指数的历史分钟数据三是直接找早期行情软件留下的二进制数据文件自行解析这条路技术要求高但最可能拿到未经复权污染的第一手数据。以 Python 脚本为例用 baostock 拉上证指数日线验证区间可用性是最快的办法。注意分钟级历史数据多数接口不提供完整 2000 年起的记录所以先用日线确认起止时间再决定是否值得为分钟数据付费或另寻渠道。拉数据的代码很短但判定数据有没有价值的代码要写得谨慎import baostock as bs import pandas as pd # 登录数据服务返回登录结果码 lg bs.login() # 获取上证指数日线用于验证数据源对该区间是否覆盖 rs bs.query_history_k_data_plus( sh.000001, date,open,high,low,close,volume, start_date2000-01-01, end_date2008-12-31, frequencyd, adjustflag3 # 3 表示不复权后续自己处理复权 ) # 把结果包装成 DataFrame rows [] while rs.error_code 0 and rs.next(): rows.append(rs.get_row_data()) df pd.DataFrame(rows, columnsrs.fields) bs.logout() print(df.head()) print(df.shape)这段代码的核心作用是确认数据源在目标区间内没有大段返回空数据。adjustflag3特意选择不复权原因是历史行情在除权除息日的跳空必须由你自己识别并决定处理方式如果数据源直接在价格里做了前复权后复权口径就再也找不回来了。跑完这段如果行数明显少于 2000 到 2008 年应有余的约 2100 个交易日说明数据源覆盖不全趁早换渠道。3.2 时间戳对齐与脏数据过滤重建标准分钟序列原始数据常有两个问题时间戳缺失导致某分钟缺失以及盘后测试数据混进正常行情里。交易所的 1 分钟序列在每个交易日内是固定的 240 根从 09:31 到 11:30、13:01 到 15:00中间不能有半点偏差。拿到数据后第一步是按日期分组对每个交易日重建完整的分钟索引缺失的 K 线用前一根的收盘价做前向填充同时打上缺失标记。清洗脚本的关键逻辑并不复杂但每一步都是在为后面的画笔算法扫雷import pandas as pd # 假设原始数据读取到 raw_df包含 datetime、open、high、low、close、volume raw_df[datetime] pd.to_datetime(raw_df[datetime]) raw_df raw_df.drop_duplicates(subsetdatetime, keeplast) # 生成标准交易日内的分钟序列排除午间休市 all_minutes [] for date in raw_df[datetime].dt.date.unique(): am pd.date_range(f{date} 09:31, f{date} 11:30, freq1min) pm pd.date_range(f{date} 13:01, f{date} 15:00, freq1min) all_minutes.extend(am) all_minutes.extend(pm) full_index pd.DatetimeIndex(all_minutes) df raw_df.set_index(datetime).reindex(full_index) # 用前值填充缺失 K 线并记录缺失位置以便追溯 df[is_filled] df[close].isna().astype(int) df[[open, high, low, close, volume]] df[ [open, high, low, close, volume] ].ffill() df df.reset_index().rename(columns{index: datetime}) df.to_parquet(SH000001_1min_clean.parquet, indexFalse)这段脚本的时间成本在一千万行数据上也只需要几秒但它解决的是画笔算法里最致命的错位问题。如果 11:30 那一根 K 线被错误地插到了 10:45 的位置后续所有分型、笔的划分都会连锁错位。drop_duplicates(keeplast)是处理早盘数据被重复推送的惯例动作ffill()则是用前收盘价顶替缺失位保证序列连续而不产生任意捏造的零值。整理完后务必打印is_filled的求和结果确认缺失比例在 0.1% 以内再进入下一步。3.3 复权口径对画笔的干扰为什么复盘建议用后复权复权是缠论复盘数据里最容易被忽视的坑。前复权价格会把历史价格整体压缩导致 2005 年 998 点变成一堆几块钱的数字这在计算历史百分位时会造成困扰更关键的是前复权会依据最新价格调整全部历史数据你今天导出的文件过几个月再做一次就会整体漂移。对于 2000 到 2008 年的固定区间复盘我一般建议使用后复权也就是把除权前的价格乘上一个累积因子让最新的价格被抬高而不是让历史价格被压扁。后复权数据的好处是单次生成后即为恒定量不会因为行情软件升级而改变适合做跨年度的笔段划分比较。缺点是高价位在图表上显得畸高但缠论画笔只关心中枢区间和相对高低点的关系绝对价位的大小不影响递归结构。如果你的画笔脚本内部用了价格阈值去过滤噪声比如高低点价差小于 0.1 元就忽略那复权口径改动后阈值必须重新校准这是很多复盘结论失真的隐藏原因。4. 用清洗后的数据跑通缠论画笔分型、包含处理与级别的参数映射数据干净之后最核心的工程是把画笔算法跑得和缠论原文一致。这个环节没有统一标准答案不同人的笔划分有细节差异但底层的处理步骤是一致的先做 K 线包含合并再识别分型然后连线成笔最后在 5 分钟级别合并线段。参数设定恰当多数情况下能得到稳定的复盘结果。4.1 包含关系处理的唯一正确顺序方向优先合并其次包含处理是全网缠论爱好者争论最多的地方但落到数据上其实规则非常机械。两根相邻 K 线若前一根的高点和低点都被后一根完全覆盖或者反过来先按之前走势的方向决定合并方向。如果此前是向上走势取两根 K 线中较高的高点作为合并后高点取两根中较高的低点作为合并后低点如果此前是向下走势则取较低的高点和较低的低点。这个规则在分钟级数据上表现得很稳定但需要写成循环递归因为合并完的新 K 线可能继续与下一根形成包含关系。用 Python 实现时要注意递归深度和数据量级的匹配一年 5.8 万根 1 分钟 K 线的包含处理在纯 Python 循环里大约需要几秒不会成为性能瓶颈。关键在于循环内的更新逻辑要保证方向判断使用的是「合并之前」的走势方向而不是本根的方向。常见的翻车写法是每根 K 线都重新判断方向导致向上走势中途忽然变成向下合并画笔全乱。4.2 分型确认的阈值顶分型和底分型必须严格隔开一笔的定义是相邻的顶分型和底分型之间连线中间不能共用 K 线。这个约束是画笔算法里最重要的前提。在实际数据上经常出现连续三根 K 线同时满足顶分型条件又满足底分型条件的情况比如一根长上下影线的十字星前一根高点比它高、后一根高点也比它高同时前一根低点比它低、后一根低点也比它低这时必须靠「相邻分型之间至少间隔一根 K 线」的规则来剔除。执行顺序上先识别全序列所有顶分型和底分型再逐个检查相邻分型的距离。距离小于等于 1 的时候就保留更晚形成的那个分型或者按价格幅度更大者优先两种策略各有偏好但在 1 分钟图上的差异很小。这里给出一个最小可运行的笔划分脚本片段它依赖已经清洗好的 1 分钟 K 线数据def find_pivots(df): pivots [] highs df[high].values lows df[low].values for i in range(1, len(df) - 1): left, right i - 1, i 1 # 顶分型中间K线高点最高且低点不低于两侧太多宽松条件 if highs[i] highs[left] and highs[i] highs[right]: pivots.append((df[datetime][i], top, highs[i])) # 底分型中间K线低点最低 if lows[i] lows[left] and lows[i] lows[right]: pivots.append((df[datetime][i], bottom, lows[i])) return pivots上面只是分型识别的最简版本实际应用时强烈建议把「中间 K 线必须在左侧 K 线收盘之后、右侧 K 线开盘之前得到确认」这个时间约束加进去。用 1 分钟图做复盘时会遇到 14:59 出现顶分型、15:00 收盘前又快速回落的情况如果不在分型识别阶段做时间过滤画笔会把这种日内噪声当成转折点。我一般会在分型判定后增加一个幅度过滤参数 min_move默认取 0.1%也就是顶分型与底分型之间的价格差至少达到当时价格的千分之一才保留这个参数直接决定笔的数量和灵敏程度。4.3 从 1 分钟笔到 5 分钟线段两级数据的衔接方式最常见的衔接方式是先在 1 分钟图上划分笔然后把连续的笔按 5 分钟 K 线时间轴切分每 5 根 1 分钟 K 线对应 1 根 5 分钟 K 线再把 1 分钟笔的高低点映射到 5 分钟时间轴上重新做包含处理。另一种更简单的做法是直接把 5 分钟原始 K 线当独立序列划分线段绕过 1 分钟笔的递归但这样会丢失 1 分钟级别的缺口和跳空信息。我倾向采用两层递归结构1 分钟分型产生笔笔的重叠区间构成 1 分钟中枢然后以 1 分钟中枢的边界为输入在 5 分钟图上识别线段。这种做法的好处是线段端点天然具有 1 分钟级别的精度而不仅仅是 5 分钟 K 线的粗糙高低点。代价是计算复杂度翻倍以及对 1 分钟数据质量的要求更高。如果你的 1 分钟数据有几段缺失合并出来的线段端点就会偏掉建议在 5 分钟级别复盘时拿原始 5 分钟 K 线做一次交叉验证。5. 缠论复盘数据避坑5 条踩过的真实记录围绕 2000 到 2008 年上证指数分钟数据的复盘我在实际项目中踩过不少坑有些坑属于数据源本身的有些坑属于算法参数选择的每一条都可能让复盘结论彻底偏离。5.1 前复权导致的“假背驰”现象用某个行情软件导出的 1 分钟数据复盘 2006 年行情在 2006 年 5 月到 7 月期间频繁出现顶背驰信号但事后看指数并没有明显下跌回测策略被反复打脸。原因导出时默认使用了前复权2006 年的价格被后面历次分红除权整体压低导致局部高低点比例失真背驰力度判断全部建立在错误的价格坐标上。解决重新下载不复权原始数据自行做后复权处理。在代码里统一用后复权价格参与笔段计算背驰信号恢复正常。从此任何分钟级数据入库前我都会先查复权字段确认adjustflag或等效参数的值后再确认是否用于复盘。5.2 涨停跌停跳空在 1 分钟图上制造假分型现象2007 年大牛市里涨停板频繁某日高开后迅速封死涨停1 分钟图上连续十几根 K 线的高点完全相同分型识别脚本在这些平台上反复出现顶分型又反复消失。原因涨停封板时成交价被钉在涨停价真实的分型被价格限制掩盖但数据序列上仍然存在微小的高低点差异算法把噪声读成了分型。解决在分型识别前加入「价格平稳区过滤」如果连续 5 根以上 K 线高低点价差小于最小变动价位A 股为 0.01 元视为无成交或一字板区间跳过这段区域不生成分型。这个参数按 1 分钟数据设置为 0.01 元按 5 分钟数据设置为 0.02 元效果稳定。5.3 午间休市的那 90 分钟被数据源错误填充现象某次从第三方渠道获取的 5 分钟数据里12:00 前后多出了两根看似正常的 K 线导致 5 分钟线段断点错位11:25 到 13:05 这段走势被硬拆成两段。原因部分数据源在重建分钟序列时把午间休市期间的 tick 或委托单数据也聚合成了 K 线而这些数据不属于连续竞价阶段。解决清洗阶段严格按 09:31 到 11:30、13:01 到 15:00 两个时间窗口过滤窗口外的 K 线直接丢弃。另外用每个交易日的 K 线数量做校验1 分钟数据应为 240 根5 分钟数据应为 48 根不匹配的一律标红复查。5.4 早期数据的千股停牌与复牌跳空现象2001 年到 2005 年熊市里个股大量停牌上证指数虽然是成分指数相对稳定但 2005 年股权分置改革试点期间成分股停牌导致指数分钟线出现断崖式跳空画笔在这些跳空处画出了一笔跨越数日的巨长笔。原因指数分钟数据在成分股停牌时未必做了平滑处理直接按缺失权重忽略造成指数点位在复牌瞬间跳变。解决对跳空幅度超过 1% 的相邻 K 线做标记人工判断跳空属于正常涨跌还是成分股变动。缠论画笔遇到这种跳空我一般直接将跳空处打断成两段不让笔跨越跳空缺口。缺口的处理规则是向上跳空后若三根 K 线不回补视作新线段起点三根内回补则按连续走势处理。5.5 非交易时段数据混入收盘集合竞价现象15:00 收盘后偶尔出现 15:00:00 到 15:00:30 的小成交量 K 线有些数据源会把深市的收盘集合竞价单独生成一根 1 分钟线导致当日最后一根 K 线的收盘价与行情软件显示不一致。原因数据源对收盘集合竞价的处理策略不同有的把它并入 14:59 到 15:00 那根 K 线有的则独立成线。解决统一以 15:00 整作为当日最后一根 K 线的结束时间所有时间戳 15:00 之后的记录全部截断。同时把收盘价对齐到行情软件的快照值如果偏差超过 0.1%优先信任行情软件的收盘价并反推修正最后一根 K 线。6. 用 Python 快速验证一段 5 分钟图的笔划分复盘结果的正确性检查笔划分完成后不能直接拿去推买卖点得先确认这一笔划分是可信的。最有效的验证手段是回看 2005 年 6 月 6 日 998 点附近的 5 分钟图这段历史极清晰底部 V 型反转在 5 分钟图上应该是 1 到 2 笔完成不应当出现三笔以上的碎笔。用脚本自动检查笔段数量与转折价格是否匹配已知高低点能快速暴露参数问题。首先把 5 分钟数据输入画笔函数输出所有笔的端点时间与价格然后与已知的关键点位做对照。998 点当天低点出现在 6 月 6 日早盘 10 点前后如果画笔把低点定位在 13:00 之后说明包含处理方向或分型幅度过滤参数有问题。验证脚本不需要复杂界面直接打印笔端点列表pivots find_pivots(df_5min) # 过滤出连续的底分型-顶分型交替即成笔的端点 strokes [] current None for p in pivots: if current is None: current p continue # 顶底交替且间隔至少2根K线 if p[1] ! current[1] and abs(p[0] - current[0]).seconds // 60 2: strokes.append((current, p)) current p for s in strokes: print(s[0][0], s[0][1], s[0][2], -, s[1][0], s[1][1], s[1][2])这段代码把相邻分型对连成笔同时强制顶底交替。运行后检查两个指标总笔数是否在 2005 年 6 月 6 日到 6 月 8 日区间内不过于密集正常行情 5 分钟图每日成笔大约 6 到 12 笔以及转折点价格是否与日后复盘文章中的关键点位一致。如果笔数明显偏多把min_move参数往上调如果笔数偏少往低调直到与已知历史走势描述吻合。我的习惯是每完成一年的分钟数据清洗和笔划分就手动翻看 3 个标志性日期附近的结果2005 年 6 月 6 日底部、2007 年 2 月 27 日大跌、2008 年 9 月 18 日政策反转日。这些日期的走势结构在缠论社区里有大量公开讨论笔的形态是否合理一眼就能看出。用这个笨办法校准参数比任何数学优化都可靠。希望这次把整套数据准备和复盘流程拆开讲能帮你少走一段弯路。本文还有配套的精品资源点击获取
返回列表