沃尔夫波形 (Wolfe Waves)·进阶篇
(2/3)·从之字折线峰值到目标时间线,手动数浪漏掉的三条隐藏规则都在这里
接上篇的基础认知,我们继续深挖沃尔夫波形的工程化检测。很多交易者盯着1-5点入场,却忽略了点3必须远低于点1这类量化门槛,导致把普通楔形错判成有效波形,在外汇和贵金属市场里这种误判带来的回撤概率明显偏高。
「之字折线指标的增量计算骨架」
在 MT5 里写之字折线类指标,最忌讳每根 tick 都从头扫全历史。上面这段 OnCalculate 的入口逻辑,核心就是区分首次计算与增量更新:prev_calculated==0 时从 start=1 起步,并把 CurCount、PreCount、CurDir、PreDir、LastTime 全部清零;否则只从 prev_calculated-1 那根柱线接着跑,历史段不再重复处理。 主循环里用 time[i]>LastTime 判断是不是新柱线。是新的就把当前计数和方向暂存进 Pre 变量,不是新的(属同根重算)则把 Pre 的值回灌给 Cur,保证回踩历史柱时折线状态不漂移。 每次循环先把四个绘制缓冲(UpArrowBuffer、DnArrowBuffer、UpDotBuffer、DnDotBuffer)写成 EMPTY_VALUE 清掉旧图形,再用 CopyBuffer 从附属句柄拉两个元素进 lhb 数组,比较 lhb[0]!=lhb[1] 来识别是否出现了新的最高价柱——这一判别直接决定后面要不要落点。外汇与贵金属波动大,这种缓冲清空+重判的写法能避免旧拐点残影,但指标本身不预测方向,只描述已发生的折返。
if(llb[class="num">0]!=llb[class="num">1]){ DnDotBuffer[i]=low[i]; } class="type">int PreDir; class=class="str">"cmt">// 前一根柱线的之字折线方向 class="type">int CurDir; 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[], class="kw">const class="type">int &spread[]) { class="type">int start; class=class="str">"cmt">// 用于计算起始柱线的变量 if(prev_calculated==class="num">0){ class=class="str">"cmt">// 全部计算 start=class="num">1; CurCount=class="num">0; PreCount=class="num">0; CurDir=class="num">0; PreDir=class="num">0; LastTime=class="num">0; } else{ class=class="str">"cmt">// 仅计算新的柱线 start=prev_calculated-class="num">1; } class=class="str">"cmt">// 指标主循环 for(class="type">int i=start;i<rates_total;i++){ if(time[i]>LastTime){ class=class="str">"cmt">// 新柱线 LastTime=time[i]; PreCount=CurCount; PreDir=CurDir; } else{ class=class="str">"cmt">// 柱线重新计算 CurCount=PreCount; CurDir=PreDir; } class=class="str">"cmt">// 清除绘制箭头和点的缓冲区 UpArrowBuffer[i]=EMPTY_VALUE; DnArrowBuffer[i]=EMPTY_VALUE; UpDotBuffer[i]=EMPTY_VALUE; DnDotBuffer[i]=EMPTY_VALUE; class=class="str">"cmt">// 辅助变量 class="type">class="kw">double hval[class="num">1]; class="type">class="kw">double lval[class="num">1]; class="type">class="kw">double zz[class="num">1]; class=class="str">"cmt">// 新的最高价 class="type">class="kw">double lhb[class="num">2]; class=class="str">"cmt">// 接收缓冲区的两个元素, 内带新的最高价的柱线索引 if(CopyBuffer(handle,class="num">4,rates_total-i-class="num">1,class="num">2,lhb)<=class="num">0){ class="kw">return(class="num">0); } if(lhb[class="num">0]!=lhb[class="num">1]){ class=class="str">"cmt">// 这是新的最高价 class=class="str">"cmt">// 获取最高价格 (或基于之字折线计算的数据)
◍ 拐点写入与数组扩容的实现细节
这段逻辑处理之字折线在新高或新低出现时的两种状态:方向延续则刷新末位拐点,方向反转则写入新节点。向上分支先通过 CopyBuffer(handle,0,...) 取最新峰值,若返回 ≤0 直接 return(0) 放弃本根 K 线计算,避免脏数据污染波形序列。 向下分支结构对称,用 CopyBuffer(handle,5,...) 取含新低的柱线索引,再取 buffer 1 的低价。llb[0]!=llb[1] 才是确认新低,否则跳过。两个分支都预留了识别沃尔夫波形的注释位,实盘可在此挂条件判断。 AddNew 在数组满时按 1024 个元素步进扩容,外汇与贵金属 tick 波动密集时,这段能防止 PeackTrough 越界崩溃。RefreshLast 只改末位 Bar 和 Val,不增计数,保证当前波段拐点随价格延伸而移动。 开 MT5 把这段塞进你自己的 ZigZag 衍生指标,打印 CurCount 峰值,黄金 1 分钟图忙时一晚可能吃到上百次扩容,值得关注内存占用。
if(CopyBuffer(handle,class="num">0,rates_total-i-class="num">1,class="num">1,hval)<=class="num">0){ class="kw">return(class="num">0); } if(CurDir==class="num">1){ class=class="str">"cmt">// 已知的最后向上方向 class=class="str">"cmt">// 更新有关最后一个之字折线拐点的信息 RefreshLast(i,hval[class="num">0]); } else{ class=class="str">"cmt">// 之字折线方向已改变 class=class="str">"cmt">// 加入新的数值 AddNew(i,hval[class="num">0],class="num">1); } class=class="str">"cmt">// 此处, 我们将添加检查条件以便识别向下的沃尔夫波形 } class=class="str">"cmt">// 新的最低价 class="type">class="kw">double llb[class="num">2]; class=class="str">"cmt">// 接收缓冲区的两个元素, 内带新的最低价的柱线索引 if(CopyBuffer(handle,class="num">5,rates_total-i-class="num">1,class="num">2,llb)<=class="num">0){ class="kw">return(class="num">0); } if(llb[class="num">0]!=llb[class="num">1]){ class=class="str">"cmt">// 这是新的最低价 class=class="str">"cmt">// 获取最低价格 (或基于之字折线计算的数据) if(CopyBuffer(handle,class="num">1,rates_total-i-class="num">1,class="num">1,lval)<=class="num">0){ class="kw">return(class="num">0); } if(CurDir==-class="num">1){ class=class="str">"cmt">// 已知的最后向下方向 class=class="str">"cmt">// 更新有关最后一个之字折线拐点的信息 RefreshLast(i,lval[class="num">0]); } else{ class=class="str">"cmt">// 之字折线方向已改变 class=class="str">"cmt">// 加入新的数值 AddNew(i,lval[class="num">0],-class="num">1); } class=class="str">"cmt">// 此处, 我们将添加检查条件以便识别向上的沃尔夫波形 } } class="kw">return(rates_total); } class="type">void AddNew(class="type">int i,class="type">class="kw">double v,class="type">int d){ if(CurCount>=ArraySize(PeackTrough)){ class=class="str">"cmt">// 数组中没有可用元素 ArrayResize(PeackTrough,ArraySize(PeackTrough)+class="num">1024); class=class="str">"cmt">// 增加数组大小 } PeackTrough[CurCount].Dir=d; class=class="str">"cmt">// 设置方向 PeackTrough[CurCount].Val=v; class=class="str">"cmt">// 设置数值 PeackTrough[CurCount].Bar=i; class=class="str">"cmt">// 设置柱线 CurCount++; class=class="str">"cmt">// 使用数组占用元素的数量增加变量 CurDir=d; class=class="str">"cmt">// 记忆最后的之字折线方向 } class="type">void RefreshLast(class="type">int i,class="type">class="kw">double v){ PeackTrough[CurCount-class="num">1].Bar=i; class=class="str">"cmt">// 设置新柱线 PeackTrough[CurCount-class="num">1].Val=v; class=class="str">"cmt">// 设置新数值 }
沃尔夫波形里的两条直线求解
在 MT5 里做沃尔夫波形自动识别,绕不开两个基础几何问题:已知两点连线和第三点的柱线索引,求线上的价格;以及两条线各自由两点定义,求它们的交叉点坐标。 第一个问题本质是线性插值。斜率 D=(Y2-Y1)/(X2-X1) 表示每根柱线价格(或指标值)的变化量,拿到 X3 后 Y3=Y1+(X3-X1)*D 即可。EURUSD 的 M15 图上,若点1在柱线 100 价 1.0850、点2在柱线 120 价 1.0890,则 D=0.0020/20=0.0001,柱线 110 处线值约为 1.0860。 第二个问题先化直线为 Y=a+b*X 形式。两条线斜率 k1、k2 分别由各自两点算出,令两线 Y 相等解 X3,得到交点横坐标;反之也可先令 X 相等解 Y3。注意外汇与贵金属波动剧烈,这种几何推算只描述形态位置关系,实际击穿概率随波动率放大而升高。 下面三个函数可直接拷进 EA 或指标用:y3 做单线插值,TwoLinesCrossX 与 TwoLinesCrossY 分别求交点的横坐标和纵坐标,参数顺序严格对应两条线的四个端点。
class="type">class="kw">double y3(class="type">class="kw">double x1,class="type">class="kw">double y1,class="type">class="kw">double x2,class="type">class="kw">double y2,class="type">class="kw">double x3){ class="kw">return(y1+(x3-x1)*(y2-y1)/(x2-x1)); } class="type">class="kw">double TwoLinesCrossX(class="type">class="kw">double x11,class="type">class="kw">double y11,class="type">class="kw">double x12,class="type">class="kw">double y12,class="type">class="kw">double x21,class="type">class="kw">double y21,class="type">class="kw">double x22,class="type">class="kw">double y22){ class="type">class="kw">double k2=(y22-y21)/(x22-x21); class="type">class="kw">double k1=(y12-y11)/(x12-x11); class="kw">return((y11-y21-k1*x11+k2*x21)/(k2-k1)); } class="type">class="kw">double TwoLinesCrossY(class="type">class="kw">double x11,class="type">class="kw">double y11,class="type">class="kw">double x12,class="type">class="kw">double y12,class="type">class="kw">double x21,class="type">class="kw">double y21,class="type">class="kw">double x22,class="type">class="kw">double y22){ class="type">class="kw">double k2=(x22-x21)/(y22-y21); class="type">class="kw">double k1=(x12-x11)/(y12-y11); class="kw">return((x11-x21-k1*y11+k2*y21)/(k2-k1)); }
「用峰值数组捕捉沃尔夫波形突破」
检测沃尔夫波形的前提是至少攒够 5 个之字折线峰值,且当前折线方向必须朝下(CurDir == -1)才去查向上的反转波形。每次 OnCalculate 出新极值时,引擎会调 CheckUp() 或 CheckDn(),避免错过点 5 击穿 1-3 连线的瞬间。 直接读 PeakTrough 数组很笨,实战里用 v1~v5、i1~i5 这组短变量把最近 5 个峰值的价和柱线号提出来,后面所有几何判断都基于它们。若峰值 4 的索引已记录过信号(CurLastBuySig == i4),说明这套折线配置已经命中过,直接跳过,不重复画箭头。 波形确认靠几道硬门槛:点 3 要低于点 1 至少 K1*(v2-v1);点 4 须低于点 2 至少 K2*(v2-v3);最后一段低点 v5 要跌破 1-3 延长线在柱 i 上的插值。之后算 4-4' 与 2-2' 的垂直高差,只有 h2-h4 > K3*h2 时,1-3 与 2-4 两线才视为右侧交汇,波形成立。 向下波形由 CheckDn() 处理,逻辑对称但峰谷位置互换——点 1、3、5、6 在上方,点 2、4、7 在下方,初步检查改为「峰值不足或折线朝上则 return」。两套函数除方向变量颠倒和绘图颜色不同,核心交叉判定完全一致。外汇与贵金属波动剧烈,这类形态仅提供概率倾向,实盘须自担高风险。
class="type">void CheckUp(class="type">int rates_total,class="kw">const class="type">class="kw">double & low[],class="kw">const class="type">class="kw">datetime & time[],class="type">int i){ if(CurCount<class="num">5 || CurDir!=-class="num">1){ class=class="str">"cmt">// 如果没有足够的峰值, 或之字折线没有指向下方, 无需检查 class="kw">return; } class=class="str">"cmt">// 用峰值数据准备 class="type">class="kw">short 变量 class=class="str">"cmt">// 峰值数据变量 class="type">class="kw">double v1=PeackTrough[CurCount-class="num">5].Val; class="type">class="kw">double v2=PeackTrough[CurCount-class="num">4].Val; class="type">class="kw">double v3=PeackTrough[CurCount-class="num">3].Val; class="type">class="kw">double v4=PeackTrough[CurCount-class="num">2].Val; class="type">class="kw">double v5=PeackTrough[CurCount-class="num">1].Val; class=class="str">"cmt">// 峰值柱线变量 class="type">int i1=PeackTrough[CurCount-class="num">5].Bar; class="type">int i2=PeackTrough[CurCount-class="num">4].Bar; class="type">int i3=PeackTrough[CurCount-class="num">3].Bar; class="type">int i4=PeackTrough[CurCount-class="num">2].Bar; class="type">int i5=PeackTrough[CurCount-class="num">1].Bar; if(CurLastBuySig!=i4){ class=class="str">"cmt">// 如果在此之字折线结构中未检测到波形 class="type">class="kw">double d1=K1*(v2-v1); class=class="str">"cmt">// 相对于峰值 class="num">1 的缩进峰值 class="num">3 的最小值 if(v3<v1-d1){ class=class="str">"cmt">// 峰值 class="num">3 明显低于峰值 class="num">1 if(v4>v1+d1){ class=class="str">"cmt">// 线 class="num">1-class="num">4 指而向上 class="type">class="kw">double d2=K2*(v2-v3); class=class="str">"cmt">// 相对于峰值 class="num">2 的缩进峰值 class="num">4 的最小值 if(v4<v2-d2){ class=class="str">"cmt">// 峰值 class="num">4 明显低于峰值 class="num">2 class="type">class="kw">double v5l=y3(i1,v1,i3,v3,i); class=class="str">"cmt">// 点 class="num">5 处的值 if(v5<v5l){ class=class="str">"cmt">// 之字折线的最后线段与线 class="num">1-class="num">3 交叉 class="type">class="kw">double v4x=y3(i1,v1,i3,v3,i4); class=class="str">"cmt">// 点 class="num">4&class="macro">#x27; 处的值 class="type">class="kw">double v2x=y3(i1,v1,i3,v3,i2); class=class="str">"cmt">// 点 class="num">2&class="macro">#x27; 处的值 class="type">class="kw">double h4=v4-v4x; class=class="str">"cmt">// 线 class="num">4-class="num">4&class="macro">#x27; 高 class="type">class="kw">double h2=v2-v2x; class=class="str">"cmt">// 线 class="num">2-class="num">2&class="macro">#x27; 高 if(h2-h4>K3*h2){ class=class="str">"cmt">// 线 class="num">1-class="num">3 和 class="num">2-class="num">4 相遇 class="type">class="kw">double tb=TwoLinesCrossX(i1,v1,i3,v3,i2,v2,i4,v4); class=class="str">"cmt">// 线 class="num">1-class="num">3 与 class="num">2-class="num">4 交汇处的柱线 class="type">class="kw">double tv=y3(i1,v1,i4,v4,tb); class=class="str">"cmt">// 线 class="num">1-class="num">3 与 class="num">2-class="num">4 交汇点处的值
◍ 之字折线里的买点几何判定
这段逻辑只处理一种情形:之字折线已经累积出至少 5 个峰值,且方向向下(CurDir==-1)才会继续,否则直接 return。也就是说,少于 5 个拐点时,任何形态识别都不触发,避免在噪声里误报。 核心判定用 v1~v5 五个峰值价格与对应柱线 i1~i5。先算 d1=K1*(v2-v1) 作为峰值 3 相对峰值 1 的缩进阈值;若 v3<v1-d1 且 v4>v1+d1,说明线段 1-4 翘头向上。再算 d2=K2*(v2-v3),要求 v4<v2-d2 才认为峰值 4 明显低于峰值 2。 最后用 y3() 取线 1-3 在当前柱 i 的投影值 v5l,若实际 v5<v5l 表示末段下穿了 1-3 线。接着比较线 4-4' 与 2-2' 的高度差 h4、h2,当 h2-h4>K3*h2 时,认为 1-3 与 2-4 两线收敛交叉,此时用 TwoLinesCrossX() 求出交汇柱线 tb 与价位 tv,并把 tv 写进 UpDotBuffer[i] 作为目标点。 向下对称的函数 CheckDn() 把方向反过来:要求 CurDir==1 且同样至少 5 个峰值,变量取法完全一致。开 MT5 把 K1、K2、K3 三个系数从默认 0.1/0.1/0.3 往下调,可能更早捕捉到收敛,但假信号概率会上升,外汇和贵金属品种波动大,实盘前务必在策略测试器跑多周期验证。
if(CurCount<class="num">5 || CurDir!=-class="num">1){ class=class="str">"cmt">// 如果没有足够的峰值, 或之字折线没有指向下方, 无需检查 class="kw">return; } class=class="str">"cmt">// 峰值数据变量 class="type">class="kw">double v1=PeackTrough[CurCount-class="num">5].Val; class="type">class="kw">double v2=PeackTrough[CurCount-class="num">4].Val; class="type">class="kw">double v3=PeackTrough[CurCount-class="num">3].Val; class="type">class="kw">double v4=PeackTrough[CurCount-class="num">2].Val; class="type">class="kw">double v5=PeackTrough[CurCount-class="num">1].Val; class=class="str">"cmt">// 峰值柱线变量 class="type">int i1=PeackTrough[CurCount-class="num">5].Bar; class="type">int i2=PeackTrough[CurCount-class="num">4].Bar; class="type">int i3=PeackTrough[CurCount-class="num">3].Bar; class="type">int i4=PeackTrough[CurCount-class="num">2].Bar; class="type">int i5=PeackTrough[CurCount-class="num">1].Bar; if(CurLastBuySig!=i4){ class=class="str">"cmt">// 如果在此之字折线结构中未检测到波形 class="type">class="kw">double d1=K1*(v2-v1); class=class="str">"cmt">// 相对于峰值 class="num">1 的缩进峰值 class="num">3 的最小值 if(v3<v1-d1){ class=class="str">"cmt">// 峰值 class="num">3 明显低于峰值 class="num">1 if(v4>v1+d1){ class=class="str">"cmt">// 线 class="num">1-class="num">4 指而向上 class="type">class="kw">double d2=K2*(v2-v3); class=class="str">"cmt">// 相对于峰值 class="num">2 的缩进峰值 class="num">4 的最小值 if(v4<v2-d2){ class=class="str">"cmt">// 峰值 class="num">4 明显低于峰值 class="num">2 class="type">class="kw">double v5l=y3(i1,v1,i3,v3,i); class=class="str">"cmt">// 点 class="num">5 处的值 if(v5<v5l){ class=class="str">"cmt">// 之字折线的最后线段与线 class="num">1-class="num">3 交叉 class="type">class="kw">double v4x=y3(i1,v1,i3,v3,i4); class=class="str">"cmt">// 点 class="num">4&class="macro">#x27; 处的值 class="type">class="kw">double v2x=y3(i1,v1,i3,v3,i2); class=class="str">"cmt">// 点 class="num">2&class="macro">#x27; 处的值 class="type">class="kw">double h4=v4-v4x; class=class="str">"cmt">// 线 class="num">4-class="num">4&class="macro">#x27; 高 class="type">class="kw">double h2=v2-v2x; class=class="str">"cmt">// 线 class="num">2-class="num">2&class="macro">#x27; 高 if(h2-h4>K3*h2){ class=class="str">"cmt">// 线 class="num">1-class="num">3 和 class="num">2-class="num">4 相遇 class="type">class="kw">double tb=TwoLinesCrossX(i1,v1,i3,v3,i2,v2,i4,v4); class=class="str">"cmt">// 线 class="num">1-class="num">3 与 class="num">2-class="num">4 交汇处的柱线 class="type">class="kw">double tv=y3(i1,v1,i4,v4,tb); class=class="str">"cmt">// 线 class="num">1-class="num">3 与 class="num">2-class="num">4 交汇点处的值 UpDotBuffer[i]=tv; class=class="str">"cmt">// 显示目标价位的点 CurLastBuySig=i4; class=class="str">"cmt">// 记住, 在此之字折线配置中已发现形状 if(_DrawWaves){ class=class="str">"cmt">// 绘制结构 DrawObjects(BuyColor,BuyTargetColor,v1,v2,v3,v4,v5l,i1,i2,i3,i4,i5,time,i,tb,tv,rates_total); } } } } } } } class="type">void CheckDn(class="type">int rates_total,class="kw">const class="type">class="kw">double & high[],class="kw">const class="type">class="kw">datetime & time[],class="type">int i){ class=class="str">"cmt">// 没有足够的峰值, 或并非指向上方 if(CurCount<class="num">5 || CurDir!=class="num">1){ class="kw">return; } class="type">class="kw">double v1=PeackTrough[CurCount-class="num">5].Val; class="type">class="kw">double v2=PeackTrough[CurCount-class="num">4].Val; class="type">class="kw">double v3=PeackTrough[CurCount-class="num">3].Val; class="type">class="kw">double v4=PeackTrough[CurCount-class="num">2].Val; class="type">class="kw">double v5=PeackTrough[CurCount-class="num">1].Val; class="type">int i1=PeackTrough[CurCount-class="num">5].Bar;
峰谷序列里的卖出触发判定
这段逻辑只处理已累积至少 5 个峰谷点且方向向上(CurDir==1)的情形,否则直接 return,说明信号前置条件很硬,不是每根 K 线都参与计算。 先取前 4 个峰谷的 Bar 索引:i2 到 i5 分别对应 CurCount-4 至 CurCount-1,也就是最近四个拐点所在柱。若当前卖出信号记录 CurLastSellSig 不等于 i4,才进入新信号判别,避免同一拐点重复触发。 核心阈值用了三个系数:d1=K1*(v1-v2) 限定 v3 必须高于 v1+d1、v4 必须低于 v1-d1;d2=K2*(v3-v2) 再要求 v4 高于 v2+d2。这等于用两级幅度过滤,把弱势回调和假突破挡在门外。 突破确认后算 v5l=y3(i1,v1,i3,v3,i),即 1-3 峰连线的当前映射值,v5 高于它才算之字折线向上破线。接着用 y3 算 i4、i2 处的虚拟值 v4x、v2x,得到 h4=v4x-v4 与 h2=v2x-v2,当 h2-h4>K3*h2 时,认为点 4' 相对点 2' 的回落不足,倾向反转向下。 最后 TwoLinesCrossX 求 1-3 与 2-4 线交点横坐标 tb,tv=y3(i1,v1,i4,v4,tb) 作为目标位,给 DnArrowBuffer 和 DnDotBuffer 赋值并刷新 CurLastSellSig。外汇与贵金属波动剧烈,这类形态触发仅代表概率倾向,实盘须自测 K1/K2/K3 与周期匹配度。
class="type">int i2=PeackTrough[CurCount-class="num">4].Bar; class="type">int i3=PeackTrough[CurCount-class="num">3].Bar; class="type">int i4=PeackTrough[CurCount-class="num">2].Bar; class="type">int i5=PeackTrough[CurCount-class="num">1].Bar; if(CurLastSellSig!=i4){ class="type">class="kw">double d1=K1*(v1-v2); class=class="str">"cmt">// 峰值 v1 高于峰值 v2 if(v3>v1+d1){ class=class="str">"cmt">// 峰值 v3 高于峰值 v1 if(v4<v1-d1){ class=class="str">"cmt">// 峰值 v4 低于峰值 v1 class="type">class="kw">double d2=K2*(v3-v2); class=class="str">"cmt">// 峰值 v3 高于峰值 v2 if(v4>v2+d2){ class=class="str">"cmt">// 峰值 v4 高于峰值 v2 class="type">class="kw">double v5l=y3(i1,v1,i3,v3,i); if(v5>v5l){ class=class="str">"cmt">// 之字折线突破线 class="num">1-class="num">3 向上 class="type">class="kw">double v4x=y3(i1,v1,i3,v3,i4); class="type">class="kw">double v2x=y3(i1,v1,i3,v3,i2); class="type">class="kw">double h4=v4x-v4; class=class="str">"cmt">// 点 class="num">4&class="macro">#x27; 高于点 class="num">4 class="type">class="kw">double h2=v2x-v2; class=class="str">"cmt">// 点 class="num">2&class="macro">#x27; 高于点 class="num">2 if(h2-h4>K3*h2){ class="type">class="kw">double tb=TwoLinesCrossX(i1,v1,i3,v3,i2,v2,i4,v4); class="type">class="kw">double tv=y3(i1,v1,i4,v4,tb); DnArrowBuffer[i]=high[i]; DnDotBuffer[i]=tv; CurLastSellSig=i4; if(_DrawWaves){ class=class="str">"cmt">// 用其它颜色绘制 DrawObjects(SellColor,SellTargetColor,v1,v2,v3,v4,v5l,i1,i2,i3,i4,i5,time,i,tb,tv,rates_total); } } } } } } } class=class="str">"cmt">// 没有足够的峰值, 或并非指向上方 if(CurCount<class="num">5 || CurDir!=class="num">1){ class="kw">return; } class="type">class="kw">double d1=K1*(v1-v2); class=class="str">"cmt">// 峰值 v1 高于峰值 v2 if(v3>v1+d1){ class=class="str">"cmt">// 峰值 v3 高于峰值 v1 if(v4<v1-d1){ class=class="str">"cmt">// 峰值 v4 低于峰值 v1 class="type">class="kw">double d2=K2*(v3-v2); class=class="str">"cmt">// 峰值 v3 高于峰值 v2 if(v4>v2+d2){ class=class="str">"cmt">// 峰值 v4 高于峰值 v2 if(v5>v5l){ class=class="str">"cmt">// 之字折线突破线 class="num">1-class="num">3 向上 class="type">class="kw">double h4=v4x-v4; class=class="str">"cmt">// 点 class="num">4&class="macro">#x27; 高于点 class="num">4