作为技术分析工具的 MTF 指标(基础篇)
MTF 指标在 MT5 里的定位
MTF(多时间框架)指标的核心价值,是让当前图表直接叠加更高或更低周期的信号,而不必手动切换窗口。在 MetaTrader 5 里,这类指标属于终端内置的技术分析工具,靠 OnCalculate 多周期调用实现跨周期数据读取。 原作者 Alexander Lasygin 于 2019 年 5 月 10 日发布该主题,截至统计时点累计浏览 5089 次、评论 20 条,说明多周期分析在零售交易者中一直有稳定需求。 外汇与贵金属属高杠杆品种,MTF 信号仅代表概率倾向,实盘前应在 MT5 策略测试器用历史数据验证周期组合是否过拟合。
「多周期分析里的窗口切换陷阱」
多数有经验的交易员会从日线、4小时这类更高周期往下看,再切到执行交易的短周期。这种自顶向下的多时间段分析,基本是专业写法的标配。但如果用同一套工具,就得在 MT5 里开好几个窗口或者反复切周期,预分析的成本直接压在盘前。 在 H1 及以上周期交易时,你还有余裕去翻高周期确认背景。可一旦落到 M1–M15,根本没有时间切出去看一眼。而 Wolfe Waves、Elder 三重滤网这类 MTF 策略,恰恰要求你同时盯住不同周期——缺了高周期的那块拼图,信号就可能读歪。 短周期盯盘时错过高周期信号,容易让人提前平掉好仓、或者漏掉反转点。外汇与贵金属杠杆高、跳空频繁,这种信息断层带来的不是小亏,而是节奏乱掉后的连续误判。 解法不是逼自己练切换手速,而是用指标把多周期或多品种数据聚合到当前图表。除了把趋势的真实状态摆在你面前,它还能按综合数据提示下一步该看多还是看空——当然只是概率倾向,不是指令。
◍ MTF 指标怎么跨周期搬数据
经典指标只盯着当前图表那一根周期算数,MTF 指标不一样,它能把更高或更低时间框架的广义行情信息先算好,再喂回你正在看的图表。振荡、趋势、成交量这类指标,或者它们的组合,都能按这套逻辑跑在多周期上,底层还是原算法,只是多了按设置里指定的时间间隔传数据的动作。 这版 MTF 比起早年的自制 MTF 省事很多:不用改一堆特殊配置,只要给个时间间隔,或者列一下要取数的交易品种清单(参数或参数组都行)。 输出位置也自由,既能叠在主图窗口,也能单开一个子窗口;按工具类型归组后,直接以信号样式呈现,省得你眼睛来回切周期。外汇和贵金属跨周期信号常有假突破,实盘前建议在 MT5 用 EURUSD 的 M15+H1 组合先验证一次。
多时间框架指标到底分几类
在 MT5 里把多时间框架(MTF)指标粗暴归为「一类」会误事。按呈现与计算方式,至少能拆出六类,每一类的实战用法和局限都不同。 信息类只堆数据不画信号。典型如 MultiTimeframe 指标,把各周期蜡烛收盘倒计时、买卖价、阴阳/DOJI 状态与成交量直接列在副图,信息密度高但只能看不能交易;另有进阶版会内嵌多标准指标计算并直接给交易建议,省去你叠指标的麻烦。 图形类在不同周期画同一工具。比如 M5/M15/M30 上各放一条 MA(13) 包络线,或者把随机振荡指标参数按周期翻倍:M5 用 (5,3,3)、M15 用 (15,3,9)、M30 用 (30,3,18),纯数学映射,跨周期共振一眼可见。 严格 MTF 引用并非总能实现,其缺陷在某些品种上严重到不该用,后续会单独拆适用边界。信号类则为避免图面过载,只输出信号线或色块反映趋势方向,如 MTF_Coral。还有「窗口中的窗口」类,把别的周期或指标缩进主图;以及波动性类如 MTF Candles,专看跨周期波动结构。外汇和贵金属杠杆高,多周期同看也只是提高概率,不等于方向锁定。
「用三条均线把多周期塞进一个窗口」
想在 MT5 主图同时看 1 分钟、5 分钟、15 分钟的三条 MA,最直白的线性实现就是给指标开 3 个 buffer 和 3 个 handle,每个时间框架独立算一遍再画出来。下面这段源码把 tf1/tf2/tf3 设成 1/5/15,maPeriod 统一用 13,属于「同指标多周期」里最省脑子的写法。 数组绑定有个硬条件:所依附的时间框架必须大于等于当前图表周期,否则 period 算出来没意义。初始化里用 MathFloor(tf1/timeframe) 把大周期折算成当前周期的 K 线倍数,比如图表在 M1 时,tf3=15 会得到 period3=13×15=195 根。 这种堆周期数的做法计算冗余明显,但有个场景它反而最合适:要把两三个非标准化振荡指标叠在同一窗口,因为它们振幅不同、相对中心线漂移,直接叠会看花眼;分周期画线能各自归位。外汇与贵金属波动剧烈,多周期共振也只是概率倾向,实盘前务必在策略测试器跑一遍。 别把正态当圣经 代码里 ENUM_TIMEFRAMES 直接写 1/5/15 是偷懒写法,正式发布建议用 PERIOD_M1/PERIOD_M5/PERIOD_M15 宏,避免个别经纪商环境对裸数字解析异常。
class=class="str">"cmt">//---- 指标设置 class="macro">#class="kw">property indicator_chart_window class="macro">#class="kw">property indicator_buffers class="num">3 class="macro">#class="kw">property indicator_plots class="num">3 class="macro">#class="kw">property indicator_type1 DRAW_LINE class="macro">#class="kw">property indicator_type2 DRAW_LINE class="macro">#class="kw">property indicator_type3 DRAW_LINE class="macro">#class="kw">property indicator_color1 Blue class="macro">#class="kw">property indicator_color2 Red class="macro">#class="kw">property indicator_color3 Lime class="macro">#class="kw">property indicator_width1 class="num">1 class="macro">#class="kw">property indicator_width2 class="num">1 class="macro">#class="kw">property indicator_width3 class="num">1 class=class="str">"cmt">//---- 输入参数 class="kw">input ENUM_TIMEFRAMES tf1 = class="num">1; class=class="str">"cmt">// 时间框架 (class="num">1) class="kw">input ENUM_TIMEFRAMES tf2 = class="num">5; class=class="str">"cmt">// 时间框架 (class="num">2) class="kw">input ENUM_TIMEFRAMES tf3 = class="num">15; class=class="str">"cmt">// 时间框架 (class="num">3) class="kw">input class="type">int maPeriod = class="num">13; class=class="str">"cmt">// MA 周期数 class="kw">input class="type">int Shift = class="num">0; class=class="str">"cmt">// 偏移 class="kw">input ENUM_MA_METHOD InpMAMethod = MODE_SMA; class=class="str">"cmt">// 移动平均方法 class="kw">input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; class=class="str">"cmt">// 应用的价格 class=class="str">"cmt">//---- 指标缓冲区 class="type">class="kw">double ExtBuf1[]; class="type">class="kw">double ExtBuf2[]; class="type">class="kw">double ExtBuf3[]; class=class="str">"cmt">//---- 移动平均的 句柄 class="type">int ExtHandle1; class="type">int ExtHandle2; class="type">int ExtHandle3; class=class="str">"cmt">//--- 所需计算的最小柱数 class="type">int ExtBarsMinimum; class=class="str">"cmt">//--- class="type">int period1=class="num">0; class="type">int period2=class="num">0; class="type">int period3=class="num">0; class="type">void OnInit() { class="type">int timeframe; class=class="str">"cmt">//---- 指标缓冲区映射 SetIndexBuffer(class="num">0,ExtBuf1,INDICATOR_DATA); SetIndexBuffer(class="num">1,ExtBuf2,INDICATOR_DATA); SetIndexBuffer(class="num">2,ExtBuf3,INDICATOR_DATA); class=class="str">"cmt">//--- timeframe =_Period; class=class="str">"cmt">//--- if(tf1>=timeframe) { period1=maPeriod*(class="type">int)MathFloor(tf1/timeframe);
◍ 多周期均线的句柄与绘图初始化收尾
三套均线在 OnInit 里各自按更高周期整除当前周期来推算实际长度:period2 = maPeriod * MathFloor(tf2/timeframe),period3 同理,只有 tfN >= timeframe 才建线,否则那一层直接空置。 每一层都先 PlotIndexSetInteger 设 PLOT_DRAW_BEGIN 为周期减一(第一根可画柱的索引),再设 PLOT_SHIFT 统一偏移,最后用 PLOT_LABEL 写成 MA(实际周期) 方便数据窗口读。 ExtHandle1/2/3 分别由 iMA(NULL,0,periodN,0,InpMAMethod,InpAppliedPrice) 拿句柄,注意 NULL 和 0 表示抓当前图表品种与周期,方法价格走外部输入。 IndicatorSetInteger(INDICATOR_DIGITS,_Digits) 把指标精度钉成账户小数位;ExtBarsMinimum 取三层最大周期加 Shift,MT5 据此少算前置冗余柱。 OnCalculate 的参数表到此列完,从 time[] 到 volume[] 一共 9 个引用数组,接下来就是 CopyBuffer 拉句柄数据再填 plot 的循环,开盘前把这套挂 EURUSD 十五分钟图验证偏移是否如设。
PlotIndexSetInteger(class="num">0,PLOT_DRAW_BEGIN,period1-class="num">1); class=class="str">"cmt">//设置要画的第一个柱的索引 PlotIndexSetInteger(class="num">0,PLOT_SHIFT,Shift); class=class="str">"cmt">//画线的偏移 PlotIndexSetString(class="num">0,PLOT_LABEL,"MA("+class="type">class="kw">string(period1)+")"); class=class="str">"cmt">//用于数据窗口的名称 ExtHandle1=iMA(NULL,class="num">0,period1,class="num">0,InpMAMethod,InpAppliedPrice); class=class="str">"cmt">//取得 MA 的句柄 } class=class="str">"cmt">//---- if(tf2>=timeframe) { period2=maPeriod*(class="type">int)MathFloor(tf2/timeframe); PlotIndexSetInteger(class="num">1,PLOT_DRAW_BEGIN,period2-class="num">1); class=class="str">"cmt">//设置要画的第一个柱的索引 PlotIndexSetInteger(class="num">1,PLOT_SHIFT,Shift); class=class="str">"cmt">//画线时的偏移 PlotIndexSetString(class="num">1,PLOT_LABEL,"MA("+class="type">class="kw">string(period2)+")"); class=class="str">"cmt">//用于数据窗口的名称 ExtHandle2=iMA(NULL,class="num">0,period2,class="num">0,InpMAMethod,InpAppliedPrice); class=class="str">"cmt">//取得 MA 的句柄 } class=class="str">"cmt">//---- if(tf3>=timeframe) { period3=maPeriod*(class="type">int)MathFloor(tf3/timeframe); PlotIndexSetInteger(class="num">2,PLOT_DRAW_BEGIN,period3-class="num">1); class=class="str">"cmt">//设置要画的第一个柱的索引 PlotIndexSetInteger(class="num">2,PLOT_SHIFT,Shift); class=class="str">"cmt">//画线时的偏移 PlotIndexSetString(class="num">2,PLOT_LABEL,"MA("+class="type">class="kw">string(period3)+")"); class=class="str">"cmt">//用于数据窗口的名称 ExtHandle3=iMA(NULL,class="num">0,period3,class="num">0,InpMAMethod,InpAppliedPrice); class=class="str">"cmt">//取得 MA 的句柄 } class=class="str">"cmt">//--- 设置精确度 IndicatorSetInteger(INDICATOR_DIGITS,_Digits); class=class="str">"cmt">//--- 所需计算的最小柱数 class="type">int per=MathMax(period3,MathMax(period1,period2)); ExtBarsMinimum=per+Shift; class=class="str">"cmt">//--- 初始化结束 } class="type">int OnCalculate(class="kw">const class="type">int rates_total, class="kw">const class="type">int prev_calculated, class="kw">const class="type">class="kw">datetime &time[], class="kw">const class="type">class="kw">double &open[], class="kw">const class="type">class="kw">double &high[], class="kw">const class="type">class="kw">double &low[], class="kw">const class="type">class="kw">double &close[], class="kw">const class="type">long &tick_volume[], class="kw">const class="type">long &volume[],