自动构造支撑和阻力线(基础篇)
◍ 用分形自动画支撑阻力
MT5 里支撑阻力不必手动画。基于 Bill Williams 分形(至少 5 根 K 线,中间最高/最低,两侧各两根更低/更高)即可自动识别关键价位。 原文作者 Vladimir Mametov 于 2018-02-27 在 MT5 社区发布该思路,截至统计显示阅读 22 752、评论 20,说明手动画线痛点普遍。 核心做法:遍历历史 K 线,用 iFractal 抓取上/下分形,把最近 N 个未突破的分形连成 zone。注意外汇与贵金属杠杆高、滑点大,分形假突破概率不低,仅作区域参考而非触发依据。
「为什么要把支撑阻力线交给程序画」
支撑和阻力线是货币对与贵金属技术分析的基础骨架,但手工在 MT5 图表上逐个锚点连线,既耗时间又受主观偏移影响。把这条流程自动化,分析师能把精力挪到形态判别和仓位决策上。 外汇与贵金属属高杠杆品种,画线偏差可能直接放大进场误差,用确定性算法替代手绘,至少能把‘线画歪了’这类低级风险压下去。 文内给出的指标逻辑不只服务于肉眼盯盘,其输出的价格区间还能直接喂给 EA 的入场条件。也就是说,同一套支撑阻力判定,既能做人机协同的辅助,也能做全自动系统的底层信号源。
用 ZigZag 抓全周期极点值
支撑阻力线的根基是图表的局部波峰与波底,人工肉眼找容易漏,直接借之字折线(ZigZag)指标把极点自动标出来更稳。它的输入参数决定了回撤灵敏度,调参等于在设定“什么级别的反转才算一个波峰或波底”。 同一套 ZigZag 参数可以跨时间帧套用,极点值会随周期变形:30 分钟图上标出的拐点,放到 4 小时图上可能直接被平滑掉。这意味着你在小周期画的支撑阻力,到大周期未必成立,贵金属和外汇这种高波动品种尤其要双向核对。 实操上,先在 MT5 插入 ZigZag,把 deviation 和 backlog 按你交易品种波幅定好,再切到目标时间帧看极点分布,据此手绘水平线,比凭感觉画更有依据。
◍ 贴着价格挑极点才画得出有效线
支撑阻力线只在贴近当前价时才对交易有参考意义, 太远的极点只是历史噪音。要让线的斜率跟价格咬合, 下降趋势里取阻力极点必须不低于前一个波峰, 上升趋势里取支撑极点不能高于前一个波底, 这样连线才不会穿价。 原文示例里第一张图适用的极点序列是 1-2-3-4-5-7, 第二张是 1-2-3-6-7-8, 差别就在是否按上述规则剔除了反向极点。 代码上先建 ZigZag 句柄, 再逐根扫之字折线的 buffer, 把符合高低点条件的极点写进结构数组。下面这段是 OnInit 与极点筛选的核心, 可直接粘进 MT5 看效果。 外汇和贵金属杠杆高, 这类线只是概率参考, 实盘仍可能随时被扫。
class=class="str">"cmt">//+------------------------------------------------------------------+ class="kw">struct trade_points class=class="str">"cmt">// 定义极点值的结构 { class="type">class="kw">double price; class=class="str">"cmt">// 价格 class="type">int pos; class=class="str">"cmt">// 位置, 柱线的索引 class="type">bool hpoint; class=class="str">"cmt">// 为真, 则是波峰 class="type">bool lpoint; class=class="str">"cmt">// 为真, 则是波底 }; class="type">int OnInit() { ZZ_handle=iCustom(_Symbol,_Period,"ZigZag",ExtDepth,ExtDeviation,ExtBackstep); class="kw">return(INIT_SUCCEEDED); } class="type">class="kw">double max=close[class="num">1]; class="type">class="kw">double min=close[class="num">1]; class="type">int z=class="num">0; for(shift=class="num">0;shift<rates_total && !IsStopped();shift++) { CopyBuffer(ZZ_handle,class="num">0,shift,class="num">1,ZigzagBuffer); if(ZigzagBuffer[class="num">0]>class="num">0) { if(ZigzagBuffer[class="num">0]>=max && ZigzagBuffer[class="num">0]==high[shift]) { ArrayResize(mass,z+class="num">1); max=ZigzagBuffer[class="num">0]; mass[z].price=ZigzagBuffer[class="num">0]; mass[z].pos=shift; mass[z].hpoint=true; mass[z].lpoint=false; z++; } if(ZigzagBuffer[class="num">0]<=min && ZigzagBuffer[class="num">0]==low[shift]) { ArrayResize(mass,z+class="num">1); min=ZigzagBuffer[class="num">0]; mass[z].price=ZigzagBuffer[class="num">0]; mass[z].pos=shift; mass[z].lpoint=true; mass[z].hpoint=false; z++; } } }
「给趋势线设门槛:七条过滤标准怎么落地」
极点数组成型后,并不是任意两点连成的斜线都配叫支撑或阻力。随着行情推进,不少线会慢慢失效,堆在图表上只是噪音。所以要用一组标准做排序和淘汰,只留当下还有参考意义的线。 核心判断逻辑围绕七个维度展开:AB 与 BC 段的长度比率、价格穿越 AB 段的次数、穿越 BC 段的次数、点 C 到现价的间距、趋势线最小和最大长度、线条斜率,以及价格处在阻力线上方还是下方。这些维度可以组合使用,参数也能按自己的盘感往后改。 比率这块用斐波那契数卡下限比较稳。把最小允许比率设成 0.25 或 0.382,等价于要求 AB/AC ≥ 0.382 且 BC/AC ≥ 0.382,输入里直接给一个 fibo 参数就行。距离过滤也很实用:只画离现价不超过 50~100 点的线,能砍掉一大半失去相关性的旧线。 斜率方向必须和趋势性质对齐——上升支撑线斜率 ≥ 0,下跌阻力线斜率 ≤ 0,这是开仓线的基本门槛。穿越次数建议区分收盘价突破和影线触碰,前者更硬,后者仅作参考。下面这段是下跌阻力线筛选的局部实现,注意它边算比率边查最小长度,再核对端点偏离容忍度。 别把正态当圣经 代码里的 tolerance*_Point 是端点贴合容差,不是胜率保证。外汇和贵金属波动大、滑点凶,实盘里这套过滤最多帮你少看几根废线,拦不住跳空击穿,仓位自己控。 两种用法都留着:一种顺着未折返的线跟趋势,一种等反向破线再动手。指标里两者都绘制,切换只看你当天的交易倾向。
class=class="str">"cmt">// 判断这些趋势线是否符合我们的标准并填写下跌趋势矩阵。 for(j=z-class="num">1; j>=class="num">0; j--) { if(mass[j].hpoint) for(i=j-class="num">1; i>=class="num">0; i--) { if(mass[i].hpoint) if(i<j) { a=mass[j].pos; b=mass[i].pos; class="type">class="kw">double ratio=class="type">class="kw">double((a-b)*class="num">100/a); class=class="str">"cmt">// 定义 AB 段与 AC 总长度的比率 if(ratio>fibo && ratio<(class="num">100-fibo)) class=class="str">"cmt">// 定义是否符合标准 class="num">1, АB/BС 段的比例 if(b>Min_dist &&(a-b)>Min_dist) class=class="str">"cmt">// 定义是否满足标准 class="num">5, АB 和 BС 段的最小长度 { ax=mass[j].price; bx=mass[i].price; coef=(ax-bx)/(a-b); price=close[class="num">1]; deviation=(ax+coef*bx)-price; cross_bc=class="num">0; cross_ab=class="num">0; if(MathAbs(deviation)<tolerance*_Point) class=class="str">"cmt">// 定义是否满足条件4 (点 С 到前一根柱线收盘价的距离) { class=class="str">"cmt">// 从 a 点到 b 点的交叉次数 for(class="type">int n=a; n>b; n--) if((close[n]-(ax+coef*(b-n)))>class="num">0) cross_ab++; class=class="str">"cmt">// 从 b 点到端点的交叉次数