小型趋势指标、中型趋势指标和主要趋势指标·综合运用
📊

小型趋势指标、中型趋势指标和主要趋势指标·综合运用

(3/3)·小型抓拐点、中型定波段、主趋势管方向,三层信号如何不打架才是实战关键

实战向 第 3/3 篇
很多人把小周期突破当主趋势反转,结果刚进场就被更大级别回撤洗出去。三层趋势各自回答不同问题:小趋势管时机,中趋势管波段,主趋势管方向。先把层级理顺,再谈信号合成。

◍ 信号类的摆动参数与接口骨架

在 MT5 里做甘恩突破信号,第一步是把主趋势与中级趋势的摆动结构分开存。下面这段类声明给出了核心缓冲区与对外设置接口,直接在 EA 的 Include 目录里建个 signal_gannbreak.mqh 就能照着填。 int handle_middle_swing; 存中级趋势指示器的句柄。double main_swing_buff[] 与 middle_swing_buff[] 分别装主、中趋势的摆动值;datetime time_buff[] 和 double price_buff[] 记录拐点时间与价格,回测时可用数组长度判断当前已捕捉几段 swing。 公开方法里 MinMainSwingContinuance(int) 限定主趋势摆动最少延续根数,MinMainSwingSize(double) 限定最小幅度(报价单位)。中级趋势用 MinMiddleSwingContinuance 与 MaxMiddleSwingSize 双向卡边界,避免噪声段触发。OpenPriceSpace 与 StopLossSpace 直接给开仓价与止损留了点差空间参数。 CheckOpenLong / CheckOpenShort 是重载 CExpertSignal 的入口,传出 price、sl、tp、expiration 引用;ValidationSettings 负责在 OnInit 阶段拦截非法参数。外汇与贵金属杠杆高,这类信号在震荡市可能连续假突破,参数没过 ValidationSettings 就别挂实盘。 protected 里的 SetMainSwingParameters 与 SetMiddleSwingParameters 用左右拐点时间加价格四参写入,GetMainSwing / GetMiddleSwing 负责从图表取段——这两个私有取段函数若返回 0,说明当前品种周期下摆动识别失败,需降周期或放宽 Min 条件。

MQL5 / C++
  class="type">int               handle_middle_swing;
  class="type">class="kw">double            main_swing_buff[];
  class="type">class="kw">double            middle_swing_buff[];
  class="type">class="kw">datetime          time_buff[];
  class="type">class="kw">double            price_buff[];
class="kw">public:
                    TGannBreakSignal();   class=class="str">"cmt">// constuctor
                   ~TGannBreakSignal();   class=class="str">"cmt">// destructor
  class=class="str">"cmt">//   Settings:
  class="type">void              MinMainSwingContinuance(class="type">int _cont);
  class="type">void              MinMainSwingSize(class="type">class="kw">double _size);
  class="type">void              MinMiddleSwingContinuance(class="type">int _cont);
  class="type">void              MaxMiddleSwingSize(class="type">class="kw">double _size);
  class="type">void              OpenPriceSpace(class="type">class="kw">double _space);
  class="type">void              StopLossSpace(class="type">class="kw">double _space);
  class="type">int               GetMainSwingContinuance();     class=class="str">"cmt">// gets swing duration time on the chart of the main trend
  class="type">class="kw">double            GetMainSwingSizePoints();      class=class="str">"cmt">// gets swing amplitude(in class="num">4-digit points) on the chart of the main trend
  class="type">int               GetMiddleSwingContinuance();   class=class="str">"cmt">// gets swing duration time on the chart of the middle trend
  class="type">class="kw">double            GetMiddleSwingSizePoints();    class=class="str">"cmt">// gets swing amplitude(in class="num">4-digit points) on the chart of the middle trend

  class=class="str">"cmt">// overloaded methods of the CExpertSignal class:
  class="kw">virtual class="type">bool      ValidationSettings();
  class="kw">virtual class="type">bool      CheckOpenLong(class="type">class="kw">double &price,class="type">class="kw">double &sl,class="type">class="kw">double &tp,class="type">class="kw">datetime &expiration);
  class="kw">virtual class="type">bool      CheckOpenShort(class="type">class="kw">double &price,class="type">class="kw">double &sl,class="type">class="kw">double &tp,class="type">class="kw">datetime &expiration);
  class="kw">virtual class="type">bool      InitIndicators(CIndicators *indicators);
  class=class="str">"cmt">//   Additional methods:
class="kw">protected:
  class=class="str">"cmt">//   Sets swing parameters of the main trend
  class="type">void              SetMainSwingParameters(class="type">class="kw">datetime _lf_dt,class="type">class="kw">double _lf_price,class="type">class="kw">datetime _rt_dt,class="type">class="kw">double _rt_price);
  class=class="str">"cmt">//   Sets swing parameters of the middle trend
  class="type">void              SetMiddleSwingParameters(class="type">class="kw">datetime _lf_dt,class="type">class="kw">double _lf_price,class="type">class="kw">datetime _rt_dt,class="type">class="kw">double _rt_price);
  class=class="str">"cmt">// Gets swing parameters of the main trend
  class="type">int               GetMainSwing();                
  class=class="str">"cmt">// Gets swing parameters of the middle trend

参数校验与多浪过滤的开多逻辑

Gann 突破信号类里,ValidationSettings 是先跑的一道闸。四个阈值参数若 ≤0 会直接 Print 报错并返回 false:主浪最小存续、主浪最小点数、中浪最小存续、中浪最大点数,任何一项不合法,后续信号计算全部不执行。 CheckOpenLong 的过滤链更硬。先调 GetMainSwing 与 GetMiddleSwing,返回 -1 即说明对应波段没识别出来,直接退出;接着比对 right 与 left 价格,主浪或中浪若出现 rt_price >= lf_price,意味着该段不是向下摆动,同样不进单。 波段尺度还要过双表:主浪存续须 ≥ min_main_swing_continuance 且点数 ≥ min_main_swing_size_points;中浪存续须 ≥ min_middle_swing_continuance 且点数 ≤ max_middle_swing_size_points。四条件任一不满足,函数返回 false,不会给 _price / _sl / _tp 赋值。 在 MT5 里把 min_main_swing_continuance 设成 0 试一下,日志会立刻吐出 Wrong Parameter 且信号类失效——这比看文档更快确认阈值下限。外汇与贵金属波动随机性高,此类过滤只降低噪音,不预示方向。

MQL5 / C++
class="type">int GetMiddleSwing();
};
class=class="str">"cmt">//---------------------------------------------------------------------
class=class="str">"cmt">// Validation of settings
class=class="str">"cmt">//---------------------------------------------------------------------
class="type">bool TGannBreakSignal::ValidationSettings()
  {
   if(this.min_main_swing_continuance<=class="num">0)
     {
       Print("Wrong Parameter: min_main_swing_continuance = ",
this.min_main_swing_continuance);
       class="kw">return(false);
     }
   if(this.min_main_swing_size_points<=class="num">0.0)
     {
       Print("Wrong Parameter: min_main_swing_size_points = ",
DoubleToString(this.min_main_swing_size_points,class="num">1));
       class="kw">return(false);
     }
   if(this.min_middle_swing_continuance<=class="num">0)
     {
       Print("Wrong Parameter: min_middle_swing_continuance = ",this.min_middle_swing_continuance);
       class="kw">return(false);
     }
   if(this.max_middle_swing_size_points<=class="num">0.0)
     {
       Print("Wrong Parameter: max_middle_swing_size_points = ",DoubleToString(this.max_middle_swing_size_points,class="num">1));
       class="kw">return(false);
     }
   class="kw">return(true);
  }
class=class="str">"cmt">//---------------------------------------------------------------------
class=class="str">"cmt">// Checks conditions to open class="type">long position
class=class="str">"cmt">//---------------------------------------------------------------------
class="type">bool TGannBreakSignal::CheckOpenLong(class="type">class="kw">double &_price,class="type">class="kw">double &_sl,class="type">class="kw">double &_tp,class="type">class="kw">datetime &_expiration)
  {
   if(this.GetMainSwing()==-class="num">1)
     {
       class="kw">return(false);
     }
   if(this.GetMiddleSwing()==-class="num">1)
     {
       class="kw">return(false);
     }
class=class="str">"cmt">// If the main swing upward, exit
   if(this.main_swing_rt_price>=this.main_swing_lf_price)
     {
       class="kw">return(false);
     }
class=class="str">"cmt">// If the middle weak swing isn&class="macro">#x27;t formed, exit:
   if(this.middle_swing_rt_price>=this.middle_swing_lf_price)
     {
       class="kw">return(false);
     }
class=class="str">"cmt">// Check swing parameters on the main trend chart
   if(this.main_swing_continuance<this.min_main_swing_continuance ||
this.main_swing_size_points<this.min_main_swing_size_points)
     {
       class="kw">return(false);
     }
class=class="str">"cmt">// Check swing parameters on the middle trend chart
   if(this.middle_swing_continuance<this.min_middle_swing_continuance ||
this.middle_swing_size_points>this.max_middle_swing_size_points)
     {
       class="kw">return(false);
     }
   class="type">class="kw">double unit=this.PriceLevelUnit();

「弱中摆突破后的多单信号与跟踪止损骨架」

当价格向上越过弱中摆的峰值,并留出 open_price_space 单位的缓冲时,系统倾向给出多头开仓信号。代码里用 Bid 价减去(左摆价 + open_price_space*unit)得到 delta,要求 delta 落在 [0, 10*unit) 区间内才触发,避免追在过分延展的位置。 触发后 _price 与 _tp 置 0,代表采用市价进场且不预设止盈;止损则 NormalizePrice 到右侧摆价减去 stop_loss_space*unit。外汇与贵金属杠杆高,这种仅用摆点挂止损的方式在快速反转时可能滑点放大,实盘前需在 MT5 用历史 tick 校验。 trailing 类通过 wizard 描述块暴露 StopLossSpace 参数,默认 5.0,即止损距摆点 5 个最小单位。类内缓存了左右摆的 datetime 与 price,以及 middle_swing_buff / time_buff / price_buff 三组数组,方便后续 CheckTrailing 里动态重算止损。 别把 10*unit 当铁律 delta 上限写死 10*unit 只是原逻辑的一种保守过滤,换到 XAUUSD 这类点值大的品种,可按点值重算该阈值,否则可能几乎不吃到信号。

MQL5 / C++
class=class="str">"cmt">// If the price has crossed the peak of the weak middle swing, set signal to open class="type">long position:
  class="type">class="kw">double delta=this.m_symbol.Bid()
-(this.middle_swing_lf_price+this.open_price_space*unit);
  if((delta>=class="num">0.0) && (delta<(class="num">10.0*unit)))
    {
      _price=class="num">0.0;
      _sl = this.m_symbol.NormalizePrice(this.middle_swing_rt_price - stop_loss_space*unit);
      _tp = class="num">0.0;
      class="kw">return(true);
    }
  class="kw">return(false);
  }
class="macro">#include <Expert\ExpertTrailing.mqh>
class=class="str">"cmt">// wizard description start
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Description of the class                                        |
class=class="str">"cmt">//| Title=Trailing on peaks/bottoms on the chart of the middle trend |
class=class="str">"cmt">//| Type=Trailing                                                  |
class=class="str">"cmt">//| Name=MiddleTrend                                               |
class=class="str">"cmt">//| Class=MiddleTrendTrailing                                      |
class=class="str">"cmt">//| Page=                                                          |
class=class="str">"cmt">//| Parameter=StopLossSpace,class="type">class="kw">double,class="num">5.0                             |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// wizard description end
class=class="str">"cmt">//+------------------------------------------------------------------+
class MiddleTrendTrailing : class="kw">public CExpertTrailing
  {
class="kw">private:
   class="type">class="kw">datetime       middle_swing_lf_datetime;   class=class="str">"cmt">// time of left point of a swing on the chart of the main trend
   class="type">class="kw">double         middle_swing_lf_price;      class=class="str">"cmt">// price of left point of a swing on the chart of the main trend
   class="type">class="kw">datetime       middle_swing_rt_datetime;   class=class="str">"cmt">// time of right point of a swing on the chart of the main trend
   class="type">class="kw">double         middle_swing_rt_price;      class=class="str">"cmt">// price of right point of a swing on the chart of the main trend
   class="type">class="kw">double         stop_loss_space;            class=class="str">"cmt">// the distance between peak/bottom and stop loss price
   class="type">int            handle_middle_swing;
   class="type">class="kw">double         middle_swing_buff[];
   class="type">class="kw">datetime       time_buff[];
   class="type">class="kw">double         price_buff[];
class="kw">public:
                 MiddleTrendTrailing();       class=class="str">"cmt">// constructor

◍ 中摆跟随止盈止损的多头判定分支

上面这段是 MiddleTrendTrailing 类尾部的方法声明与多头尾随止损的具体实现,核心在于用「中间摆点」动态推算止损位。 类声明里先放了析构函数 ~MiddleTrendTrailing() 和私有方法 GetMiddleSwing() 用来取中间摆动参数;对外暴露的 StopLossSpace(double _space) 让你直接注入止损缓冲空间,其余 ValidationSettings / InitIndicators / CheckTrailingStopLong / CheckTrailingStopShort 均为对 CExpertTrailing 的虚函数重载。 看 CheckTrailingStopLong:入参为空或 GetMiddleSwing() 返回 -1(取不到摆点)时直接返回 false,不改动仓位。 sl_req_price 的计算是关键——取左右两侧中间摆点价格的最小值,再减去 stop_loss_space 个「校准点」(adjusted_point),并用 NormalizePrice 对齐报价精度。若当前止损已优于该价(>=),同样不动作;否则把 _tp 置为 EMPTY_VALUE、_sl 写成新价并返回 true,MT5 会在下一 tick 尝试挪损。 实盘接这段逻辑时,stop_loss_space 建议从 0.5 起步在 EURUSD 的 M15 回测,外汇与贵金属杠杆高,摆点失效时可能连续返回 false 不 protective 平仓,需自加熔断。

MQL5 / C++
  ~MiddleTrendTrailing();    class=class="str">"cmt">// destructor
class="kw">private:
   class="type">int            GetMiddleSwing();           class=class="str">"cmt">// get parameters of the middle swing
class="kw">public:
   class=class="str">"cmt">//   Settings:
   class="type">void           StopLossSpace(class="type">class="kw">double _space);
   class=class="str">"cmt">//   Overloaded methods of CExpertTrailing class:
   class="kw">virtual class="type">bool   ValidationSettings();
   class="kw">virtual class="type">bool   InitIndicators(CIndicators *indicators);
   class="kw">virtual class="type">bool   CheckTrailingStopLong(CPositionInfo *position,class="type">class="kw">double &sl,class="type">class="kw">double &tp);
   class="kw">virtual class="type">bool   CheckTrailingStopShort(CPositionInfo *position,class="type">class="kw">double &sl,class="type">class="kw">double &tp);
   };
class=class="str">"cmt">//---------------------------------------------------------------------
class=class="str">"cmt">// Checks conditions of trailing stop for class="type">long position
class=class="str">"cmt">//---------------------------------------------------------------------
class="type">bool MiddleTrendTrailing::CheckTrailingStopLong(CPositionInfo *_position,class="type">class="kw">double &_sl,class="type">class="kw">double &_tp)
  {
   if(_position==NULL)
     {
      class="kw">return(false);
     }
   if(this.GetMiddleSwing()==-class="num">1)
     {
      class="kw">return(false);
     }
   class="type">class="kw">double sl_req_price = this.m_symbol.NormalizePrice(MathMin(middle_swing_lf_price,middle_swing_rt_price)
 - this.stop_loss_space * this.m_adjusted_point );
   if(_position.StopLoss() >= sl_req_price )
     {
      class="kw">return(false);
     }
   _tp = EMPTY_VALUE;
   _sl = sl_req_price;
   class="kw">return(true);
   }

用向导把信号模块拼成可跑 EA

在 MT5 里把写好的信号变成自动交易程序,走 MetaEditor 的 File / New 调出生成向导即可,不用手搓框架。第一步选 EA (generate) 单选钮进下一页;第二步给 EA 起名并把 EveryTick 设 true,让程序处理每一次报价跳动,幻数留默认也行。 第三步从信号列表里挑你之前编的那个信号模块,弹出的输入参数框可以直接改默认值,比如均线周期或阈值,改完继续下一步。第四步选仓位追踪方式,若你做过自定义追踪止损就选它,同样能调外部参数。 第五步资金管理保持固定手数不变,点 Done 就能拿到带建仓、追踪、风控规则的完整 EA。图 17 的回测里趋势被识别完整(在该方法允许范围内),且用的全是默认参数,说明信号逻辑本身能跑通。外汇与贵金属杠杆高,实盘前务必在策略测试器用真实点差多周期验证。 [CODE] "" [/CODE]

「按市场选对时间颗粒度」

甘氏模型落地的第一层约束,是时间周期必须贴合品种的自然交易架构,否则图形划分会失真。 股票市场用日、周、月线就够了;货币市场得切到会话(session)间隔,才能对齐流动性节奏;商品市场除了日周月,还要叠季节性波动。 实操上,开 MT5 把 EURUSD 的 H1 和「会话分隔」视图各拉一遍,你会看到支撑阻力在会话边界的重排概率明显更高——这是验证模型适配性的最快路径。外汇与贵金属属高杠杆品种,session 级信号失效时回撤可能快速扩大,需自设止损。

◍ 把工具请下神坛

顺着上面那张圆形水平分布图往下看,2000—2011 年日线数据里欧元和股票的顶底并未整齐落在 50、100 这类整数尾数上,日元也不是稳稳收在 40;分布有偏斜,但和“圆数”假设对不齐。这意味着甘氏的圆形水平更像一种模糊倾向,而非可单独开仓的依据。 真要验,就把附带的 gannmiddletrend.mq5 拖进 MT5 按日线跑一遍,自己数小数点末三位在 0–50 区间的顶底频次——外汇和贵金属杠杆高、滑点狠,这套只是历史统计的补充视角,别拿来当信号圣经。 作者给的 mqh 在现行 MT5 向导里常报无法识别,得手动改 include 路径和文件名大小写;它撑不起自动交易,但当作手动复盘时的分布参考还算够用。

让小布替你跑这套多周期诊断
把三个周期的趋势状态同屏比对是重复劳动,这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到小型、中型与主趋势的实时分层,你只管判断共振质量。

常见问题

内侧柱不参与图形构建,外侧柱按所属走势方向接续线段;主趋势由更高层级规则生成,小周期特殊柱只改变局部拐点,不直接改写大方向,但可能延迟中型趋势确认。
不一定。中型摆动常由若干小型摆动组成,只要价格越过前一中型极点才视为方向变更,中间小型纠正移动可以忽略,避免过度交易。
目前小布盯盘提供各周期趋势方向与摆动区间的可视化,共振逻辑需交易者自行定义;后续可能开放自定义EA信号接入,把重复劳动交给小布,你专注决策。
常见做法是只在主趋势方向过滤信号,小型向下仅作为入场回调位参考;若中型也未转空,纠正移动结束接小型底部可视为倾向继续顺势的买点。
这是层级过滤的正常结果。小周期噪音被中、大周期剔除后,有效摆动减少但质量提升,外汇贵金属属高风险市场,信号少而准优于多而乱。