美林(Merrill)形态·综合运用
(3/3)·从利维到美林,16+16种M/W形态到底能不能在实盘数据上站住脚?
◍ 用前三根蜡烛高低点判定趋势偏向
这段逻辑把 K 线序列 rt[0]~rt[3] 当成判定原料:rt[0] 是当前收盘价,rt[1]~rt[3] 是往前数三根已完成蜡烛的最高与最低。先拿 SymbolInfoDouble 取 SYMBOL_POINT,把「最高点距收盘价的点数」换算成整型,再和 threshold 比大小。 上升趋势的判定很直白:若 (high1-close0)/point 超过阈值,记一次 a_uptrend;不满足就退看 high2,再不满足退看 high3。也就是说,最近一根完结蜡烛的高点离现价越远,越倾向被归为强势向上波动。 下跌方向对称处理:用 (close0-low1)/point 起步,依次退到 low2、low3,达标则累加 a/b/c_dntrend。外汇与贵金属波动大、滑点凶,threshold 设太小会把噪声当趋势,实盘验证时建议从 15~30 点起调。 调用处通过 CopyRates 取 4 根蜡烛,copied<4 直接返回 false 不评级。这套分类只输出计数、不预测方向,后续需结合其他权重(如上文 W13~W16 的排序返回)才可能给出交易倾向。
if(C>E && E>A && A>D && D>B) class="kw">return(W13); class=class="str">"cmt">//--- W14 if(E>C && C>A && A>D && D>B) class="kw">return(W14); class=class="str">"cmt">//--- W15 if(C>E && E>D && D>A && A>B) class="kw">return(W15); class=class="str">"cmt">//--- W16 if(E>C && C>D && D>A && A>B) class="kw">return(W16); class="kw">return(-class="num">1); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Define the profit categories | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CProgram::GetCategory(class="kw">const class="type">class="kw">string symbol,class="kw">const class="type">int shift,RATING_SET &rate,ENUM_TIMEFRAMES timeframe,class="type">int threshold) { class="type">MqlRates rt[]; class="type">class="kw">datetime start=StringToTime(TimeToString(m_calendar1.SelectedDate(),TIME_DATE)+" "+(class="type">class="kw">string)m_time_edit1.GetHours()+":"+(class="type">class="kw">string)m_time_edit1.GetMinutes()+":class="num">00"); start+=PeriodSeconds(timeframe)*shift; class="type">int copied=CopyRates(symbol,timeframe,start,class="num">4,rt); class=class="str">"cmt">//--- Get the data of previous candles if(copied<class="num">4) class="kw">return(false); class="type">class="kw">double high1,high2,high3,low1,low2,low3,close0,point; close0=rt[class="num">0].close; high1=rt[class="num">1].high; high2=rt[class="num">2].high; high3=rt[class="num">3].high; low1=rt[class="num">1].low; low2=rt[class="num">2].low; low3=rt[class="num">3].low; if(!SymbolInfoDouble(symbol,SYMBOL_POINT,point)) class="kw">return(false); class=class="str">"cmt">//--- Check for Uptrend if((class="type">int)((high1-close0)/point)>=threshold) { rate.a_uptrend++; } else if((class="type">int)((high2-close0)/point)>=threshold) { rate.b_uptrend++; } else if((class="type">int)((high3-close0)/point)>=threshold) { rate.c_uptrend++; } class=class="str">"cmt">//--- Check for Downtrend if((class="type">int)((close0-low1)/point)>=threshold) { rate.a_dntrend++; } else if((class="type">int)((close0-low2)/point)>=threshold) { rate.b_dntrend++; } else if((class="type">int)((close0-low3)/point)>=threshold) { rate.c_dntrend++; } class="kw">return(true); }
把形态统计写进表格的那段函数
在 MT5 里跑价格行为统计,最终要把每个时间周期下的形态命中率落进表格。下面这段函数负责把累计数据转成一行可读记录,你直接贴进 EA 的 CProgram 类就能用。 函数先取当前行号 m_total_row,再把上升与下降方向的 a/b/c 三类评分分别加总到 sum1、sum2。若 found 大于 0,就用 sum1/found*100 算出上涨倾向百分比 p1,同理得 p2;权重系数 k1、k2 则按 m_k1~m_k3 对三类评分加权后除以 found,得到带系数偏好的方向概率。 表格列依次填:形态名、出现次数、周期字符串、p1、p2、k1、k2,精度统一保留 2 位。写完一行后 ZeroMemory 清空 rate 结构体,m_total_row 自增,下一形态接着往下排。 外汇与贵金属市场波动剧烈、杠杆风险高,这类统计只反映历史样本概率,实盘信号可能失效,请用模拟盘先验证。
class="type">void CProgram::AddRow(CTable &table,class="type">class="kw">string pattern_name,RATING_SET &rate,class="type">int found,ENUM_TIMEFRAMES timeframe) { class="type">int row=m_total_row; class="type">class="kw">double p1,p2,k1,k2; class="type">int sum1=class="num">0,sum2=class="num">0; sum1=rate.a_uptrend+rate.b_uptrend+rate.c_uptrend; sum2=rate.a_dntrend+rate.b_dntrend+rate.c_dntrend; class=class="str">"cmt">//--- p1=(found>class="num">0)?(class="type">class="kw">double)sum1/found*class="num">100:class="num">0; p2=(found>class="num">0)?(class="type">class="kw">double)sum2/found*class="num">100:class="num">0; k1=(found>class="num">0)?(m_k1*rate.a_uptrend+m_k2*rate.b_uptrend+m_k3*rate.c_uptrend)/found:class="num">0; k2=(found>class="num">0)?(m_k1*rate.a_dntrend+m_k2*rate.b_dntrend+m_k3*rate.c_dntrend)/found:class="num">0; class=class="str">"cmt">//--- table.AddRow(row); table.SetValue(class="num">0,row,pattern_name); table.SetValue(class="num">1,row,(class="type">class="kw">string)found); table.SetValue(class="num">2,row,TimeframeToString(timeframe)); table.SetValue(class="num">3,row,DoubleToString(p1,class="num">2),class="num">2); table.SetValue(class="num">4,row,DoubleToString(p2,class="num">2),class="num">2); table.SetValue(class="num">5,row,DoubleToString(k1,class="num">2),class="num">2); table.SetValue(class="num">6,row,DoubleToString(k2,class="num">2),class="num">2); ZeroMemory(rate); m_total_row++; }
「把文件丢进正确的终端根目录」
随附文档里所有用到的文件都有固定归属,错放文件夹会导致脚本或指标在 MT5 里直接不加载。 核心动作只有一步:把 MQL5 文件夹整体放到终端根目录下,而不是随便解压到桌面。 在 MetaTrader 5 里按 Ctrl+Shift+D 能直接弹出终端根目录窗口,或者右键调出关联菜单也能进同一个路径(参考原文图例 7 的入口示意)。 外汇与贵金属品种波动剧烈、杠杆风险高,部署完建议先开模拟账户跑一遍,确认文件被终端识别再上真仓。
◍ 一点提醒
这套图表形态识别项目以 MQL5.zip(约 1.74 MB)分发,解压后需把文件放进 MT5 终端根目录的 MQL5 文件夹,否则面板和资源都不会加载。 有用户在 D1 欧元兑美元上测 M1 形态时发现,MainWindow.mqh 第 1055 行 GetCategories 算的是自然天数而非蜡烛数,导致 2019 年 7 月 1 日的形态被倒推到 5 月 9 日的高低点,差了 37 根 M1 蜡烛。 编译阶段也踩过坑:缺 passive_2.bmp、pressed_2.bmp 两张 GUI 资源,且 iATR 调用参数数量报错,共 3 错误 18 警告。外汇和贵金属波动剧烈、杠杆高风险大,拿这类社区工具做验证前,先补齐资源路径、核对时间计数逻辑再上图表。
resource file &class="macro">#x27;\Images\EasyAndFastGUI\Candles\passive_2.bmp&class="macro">#x27; not found MainWindow.mqh class="num">1244 class="num">11 resource file &class="macro">#x27;\Images\EasyAndFastGUI\Candles\pressed_2.bmp&class="macro">#x27; not found MainWindow.mqh class="num">1245 class="num">11