一个绘制支撑和阻力线的指标实例·进阶篇
(2/3)·手动拖线总慢半拍?这篇把分形当锚点,让指标自己挑峰谷画障碍
很多交易者把支撑阻力画成了心理安慰剂:线随便拖、周期不统一,价格一碰就怀疑自己画错了。真正麻烦的不是画不画,而是看不见那些被分形悄悄标出来的峰谷拐点。
「第二点怎么从分形里挑」
画一条倾斜线至少得有两个锚点,第一个点定下之后,第二个点选哪直接影响线的斜率和预警意义。最直白的规则是取第一个点之后出现的第二个分形点,这样得到的是贴近当前价格的最近一条趋势线。 也可以换思路:比如取图表上未被价格突破的最高点做阻力线参考,未被跌破的最低点做支撑线参考,逻辑跟分形法不同但都合法。外汇和贵金属波动大、假突破多,这类线的高风险属性要时刻记着。 我们这一版就固定用「第一个点之后的第二个分形」作为第二点。你可以开 MT5 把分形指标调出来,手动标两次点验证这条线对近期回调的贴合度。
突破判定与线形作废的边界条件
线形不能只看“碰线即废”。阻力线按定义是价格向上越过才算突破,支撑线则需向下越过;但实盘中常出现刺穿 2~3 个点又收回的毛刺,若直接作废线形会频繁误删。做法是引入允许的偏差点数,未超偏差的越线不视为有效突破,从而避免错误取消已有线形。 另一条边界是“冻结线”。价格可能长时间偏离水平再不回头,原线悬在半空失去意义。用柱数表达最大线形长度后,前面线形一旦超长即可强制结束并启动新线搜索;同一时刻价格变化下不应并存两条阻力线与两条支撑线,新线只能在前一线形结束后按条件寻找。 每条新线分配独立缓冲区,便于分别观察多头与空头推动的分形竞争:阻力线取第一个分形高点与后续更高分形低点配对,支撑线反之。MT5 中打开自定义指标草稿,按上述边界写突破判定,能直接看出线形在什么条件下被你亲手作废。外汇与贵金属波动剧烈,偏差点数与最大柱数须按品种波动率手调,误设会放大假信号风险。
◍ 倾斜阻力线的双分形抓取逻辑
做倾斜线指标,先开两个缓冲区分别装支撑和阻力,再暴露 Pips_(突破判定点数)和 MaxBars(线的最大长度)两个输入参数,自动化部分跑完才到手动调参的活。 载入时要先判断是不是首载:首载得跳过前两根柱,因为比尔·威廉姆分形要求左右各两个邻柱,前面柱数不够构不成分形;非首载就从 prev_calculated 之后接着算,别重头刷。 分形判定不要直接读内置缓冲区,自己写 up() / down() 函数更安全,里面必须拦住 q<2 和 q>=ArraySize-2 的越界访问,否则高频重绘时容易爆数组。 找阻力线时,先扫出第一个分形记到 r1;若后面出现更高的分形,r1 直接被覆盖更新。等到出现比 r1 低的第二个分形 r2,才算凑齐画线两点,此时 speedr=(high[r2]-high[r1])/(r2-r1) 就是线斜率。 画线从 r1 倒回去算 ResistanceBuffer[w]=high[r1]+speedr*(w-r1),这样累积误差不会超过单根柱容差。突破只在 w>r2 之后查:当 high[w] 超过缓冲线 Pips_*_Point 以上,r1、r2 清零等重新构建。外汇和贵金属波动大,这种线被毛刺刺穿的概率不低,真用在 MT5 上建议先把 Pips_ 设 3~5 点回测。 下面这段是核心抓取与绘制的可用代码,逐行拆完你能直接贴进自定义指标里改。
class="type">int limit=prev_calculated; if(limit>class="num">3)limit-=class="num">3; if(limit<class="num">2)limit=class="num">2; class="type">bool up(class="kw">const class="type">class="kw">double &h[],class="type">int q) { class=class="str">"cmt">// 检查一个柱后是否有至少两个柱, class=class="str">"cmt">// 如果少于两个柱,这个柱就不可能是分形 class=class="str">"cmt">// 如果是这样,我们就不做进一步检查而直接返回 class="kw">false if(q>=ArraySize(h)-class="num">2)class="kw">return(class="kw">false); class=class="str">"cmt">// 检查前方是否有至少两个柱, class=class="str">"cmt">// 如果少于两个柱,这个柱就不可能是分形 class=class="str">"cmt">// 如果是这样,我们就不做进一步检查而直接返回 class="kw">false if(q<class="num">2)class="kw">return(class="kw">false); class=class="str">"cmt">// 检查柱是否为分形,如果是,我们就返回 true if(h[q]>=h[q-class="num">1]) if(h[q]>=h[q-class="num">2]) if(h[q]>h[q+class="num">1]) if(h[q]>h[q+class="num">2]) class="kw">return(true); class=class="str">"cmt">// 如果我们已经进行了全部检查而仍然在这个模块中,这个柱就不是分形,返回 class="kw">false class="kw">return(class="kw">false); } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool down(class="kw">const class="type">class="kw">double &h[],class="type">int q) { class=class="str">"cmt">// 本模块与之前的类似 if(q>=ArraySize(h)-class="num">2)class="kw">return(class="kw">false); if(q<class="num">2)class="kw">return(class="kw">false); if(h[q]<=h[q-class="num">1]) if(h[q]<=h[q-class="num">2]) if(h[q]<h[q+class="num">1]) if(h[q]<h[q+class="num">2]) class="kw">return(true); class="kw">return(class="kw">false); } for(class="type">int w=limit;w<rates_total;w++) { if(up(high,w)) class=class="str">"cmt">//检查柱上是否有分形 { if(r1==class="num">0)r1=w; class=class="str">"cmt">//如果它是分形并且我们还没有峰值1, 在此设置峰值1 } } if(high[w]>=high[r1])r1=w; class=class="str">"cmt">//与第一个峰值做比较。如果本分形更高,就把该峰值设为第一个 else { r2=w; class=class="str">"cmt">//取得第二个峰值数值 speedr=(high[r2]-high[r1])/(r2-r1); class=class="str">"cmt">//计算线形速度 w=r1-class="num">1; class=class="str">"cmt">//返回以绘制新线 } ResistanceBuffer[w]=high[r1]+speedr*(w-r1); class=class="str">"cmt">//为了最小化误差,我们从最顶端开始计算 if(w>r2) class=class="str">"cmt">//检查是否有突破 if(high[w]>ResistanceBuffer[w]+Pips_*_Point){r1=class="num">0;r2=class="num">0;}
「水平线的锚点该怎么挑」
画水平支撑阻力只需要一个锚点,比趋势线省事,但锚点怎么选直接决定线的含金量。常见做法里,用前一日 K 线算斐波那契、用平均日 ATR 叠斐波那契、数某区间分形密集度、累计某价位的开盘收盘极值、统计成交量分布(市场剖面)、识别特定形态反转点,都能当条件。 核心逻辑只有一条:找价格反复触碰就回头的条件,符合的条件越多,这条水平线作为支撑或阻力的有效性越高。实战里最朴素的就是拿每日最高价当阻力、最低价当支撑——统计上价格极少收在极值上,大多触到就折返。 我们这版先用前一日极值做底稿。线在交易日结束时定型,下一天才拿去参考;但行情不停留,所以指标必须能切更高周期取「前一根柱」,并给每条线配独立系数做相对偏移。外汇和贵金属波动受事件驱动,这种静态水平仅作概率参考,破位风险始终存在。