时间序列挖掘的数据标签(第2部分):使用Python制作带有趋势标记的数据集·综合运用
拿到序列后先人工过三道筛
基础清洗跑完不代表能直接喂模型。想拿更稳的标注样本,还得靠人肉介入做几步校验,这里只点方向不展开论证。 数据完整性是第一关。它衡量的是记录是否缺失——整条断档算缺失,某个字段空着也算。评估不难:拉统计里的记录数和唯一值数就能看出端倪。比如 M15 周期里,上期收盘 1000、下期开盘突然掉到 10,中间大概率漏了棒,必须查数据源补。外汇和贵金属从 MT5 客户端导出的缺口通常少,但你要是接了外部天气或交通时间序列,这种错位极常见,高风险品种尤其要警惕幽灵缺口。 标注准不准得肉眼复核。pytrendseries 自动打的趋势标签可能过敏或迟钝,把该拆的并了、该并的拆了。这时候只能把图拉出来看,分类边界不对就手动重切。这一步最耗精力,没有捷径。 最后做点统计验证看标注分布合不合理:完整性分布图看缺失集中在哪;热图扫两个变量的相关强弱;层次聚类看不同类数据是抱团还是散沙。方法不止这三种,但这三样开 MT5 导完数用 Python 跑一遍就能筛掉大半脏样本。
◍ 把趋势段写回 MT5 行情表
下面这段 Python 把前文检测出的下行趋势段,重新映射回从 MT5 拉取的 GOLD_micro M15 行情里,生成可供训练打标签用的 trend / trend_index 两列。
初始化时若写死终端路径 D:\\Project\\mt\\MT5\\terminal64.exe,换机器必须改成你本机 terminal64.exe 实际位置,否则 mt.initialize() 会直接返回失败。行情通过 copy_rates_from_pos("GOLD_micro", mt.TIMEFRAME_M15, 0, 1000) 取最近 1000 根 15 分钟 K 线,缺失的 GOLD_micro_M15.csv 也默认落在客户端根目录。
趋势检测参数 td='downtrend'、wd=120、limit=6,意思是在 120 根窗口内、至少连续 6 根确认一段下行。循环里把每段 downtrend 的 trend 置 1,并用 trend_index 记录段内相对位置,便于后续做序列标签。
外汇与贵金属杠杆高、滑点大,这套标签逻辑仅用于离线数据挖掘,实盘信号有效性需自行回测验证,不预示任何方向。
# Copyright class="num">2021, MetaQuotes Ltd. # [MQL5官方文档] class="kw">import MetaTrader5 as mt class="kw">import pandas as pd class="kw">import pytrendseries as pts if not mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"): print(&class="macro">#x27;initialize() failed!&class="macro">#x27;) else: print(mt.version()) sb=mt.symbols_total() rts=None if sb > class="num">0: rts=mt.copy_rates_from_pos("GOLD_micro",mt.TIMEFRAME_M15,class="num">0,class="num">1000) mt.shutdown() rts_fm=pd.DataFrame(rts) rts_fm[&class="macro">#x27;time&class="macro">#x27;]=pd.to_datetime(rts_fm[&class="macro">#x27;time&class="macro">#x27;], unit=&class="macro">#x27;s&class="macro">#x27;) td_data=rts_fm[[&class="macro">#x27;time&class="macro">#x27;,&class="macro">#x27;close&class="macro">#x27;]].set_index(&class="macro">#x27;time&class="macro">#x27;) # print(td_data.head(class="num">10)) td=&class="macro">#x27;downtrend&class="macro">#x27; # or "uptrend" wd=class="num">120 limit=class="num">6 trends=pts.detecttrend(td_data,trend=td,limit=limit,window=wd) # print(trends.head(class="num">15)) # pts.vizplot.plot_trend(td_data,trends) rts_fm[&class="macro">#x27;trend&class="macro">#x27;]=class="num">0 rts_fm[&class="macro">#x27;trend_index&class="macro">#x27;]=class="num">0 max_len_rts=len(rts_fm) max_len=len(trends) last_start=class="num">0 last_end=class="num">0 for trend in trends.iterrows(): start=trend[class="num">1][&class="macro">#x27;index_from&class="macro">#x27;] end=trend[class="num">1][&class="macro">#x27;index_to&class="macro">#x27;] if trend[class="num">0]==class="num">1 and start!=class="num">0: # Since the rts_fm["trend"] itself has been initialized to class="num">0, there is no need to change the "trend" column rts_fm[&class="macro">#x27;trend_index&class="macro">#x27;][class="num">0:start]=list(range(class="num">0,start)) elif trend[class="num">0]==max_len and end!=max_len_rts-class="num">1: class="macro">#we need to see if it ends in a downtrend at the end of the data rts_fm[&class="macro">#x27;trend_index&class="macro">#x27;][last_end+class="num">1:len(rts_fm)]=list(range(class="num">0,max_len_rts-last_end-class="num">1)) else: class="macro">#Process the uptrend segments other than the beginning and end of the data rts_fm["trend_index"][last_end+class="num">1:start]=list(range(class="num">0,start-last_end-class="num">1)) class="macro">#Process each segments of the downtrend rts_fm["trend"][start:end+class="num">1]=class="num">1 rts_fm["trend_index"][start:end+class="num">1]=list(range(class="num">0,end-start+class="num">1)) last_start=start last_end=end
「最后说句实在话」
把趋势片段切出来落盘,只需一行 loc 切片加 to_csv,就能把 M15 黄金微结构存成 GOLD_micro_M15.csv 供后续回测。 这套切法依赖 trends 表首行的 index_from 作为起点,若首行被异常值污染,导出的样本会整体偏移,开 MT5 前先 print 一下起点索引。 外汇与贵金属杠杆高、跳空频繁,导出的片段只代表历史微观结构,实盘信号概率会变,别当确定性依据。
class="macro">#rts_fm=rts_fm.iloc[trends.iloc[class="num">0,:][&class="macro">#x27;index_from&class="macro">#x27;]:end,:] rts_fm.to_csv(&class="macro">#x27;GOLD_micro_M15.csv&class="macro">#x27;)