孕线形态引擎基础:从双柱嵌套逻辑到库类扩展(基础篇)
📐

孕线形态引擎基础:从双柱嵌套逻辑到库类扩展(基础篇)

(1/3)·只懂 Pin Bar 单柱判定的人,面对 Inside Bar 母柱与多定义柱嵌套时往往无从下手

偏理论进阶 第 1/3 篇
很多人把 Inside Bar 简单理解成“小柱子包在大柱子里面”,但实际图表里会出现一连串相互嵌套的定义柱,母柱只有最左边一根。若只比较相邻两柱比例,会漏掉整组结构和真实包含柱数。

「给库加上孕线形态识别」

这一节把「孕线」(Inside Bar)作为一个独立类塞进 DoEasy 库,目标是让 EA 在 MT5 上直接调用,而不是每次都手写 K 线包含逻辑。孕线本身定义很硬:后一根 K 线的全部价格区间被前一根完全包住,即母线的 high 高于子线 high、母线的 low 低于子线 low。 原文给出的示例发布于 2024 年 11 月 11 日,属于系列第 2 部分的开篇,配套代码里先建了位图图形元素类做可视化铺垫,再落地孕线类。对读者来说,开 MT5 把这类挂上图表,就能在 EURUSD 这类高波动品种上肉眼核对库识别得准不准。 外汇与贵金属杠杆高、滑点大,孕线只是概率倾向的停顿信号,绝不是反转保证;实盘前务必用策略测试器跑一遍历史数据看识别漏报率。

孕线形态的双柱结构与嵌套逻辑

针形柱是单根 K 线按比例识别,而孕线(Inside Bar)必须由两根 K 线构成:左侧母柱与右侧子柱,子柱的整个实体与影线都落在母柱波幅之内。 实际图表里孕线常出现连续嵌套——多根子柱依次被前一根包含,此时最左侧那根才是真正母柱,右侧每一根都算定义柱。按母柱与最右定义柱的开盘时间差,就能算出这套嵌套吞掉了几根 K 线,这个计数直接决定图表框选范围。 我们在形态属性里新增“母柱开启时间”字段,搜索函数据此回溯定位。除打点标记外,还能沿嵌套区间画矩形框,肉眼一眼分清单根孕线和成排嵌套。该字段与通用搜索框架也为后续其他双柱类形态留了接口。

◍ 改进库类

在开始执行下一个形态的代码之前,让我们先完成现成的文件和库类。 在 \MQL5\Include\DoEasy\ Defines.mqh 中,将 "位图" 对象类型添加到库对象类型列表中 : OBJ_BITMAP 类型的对象可以附加一个 bmp 资源 ,并在其上绘制各种基本元素。这种对象与柱的时间和价格挂钩。我们将用它们来勾勒出带有框架的形态柱。 除了形态对象会存储形成形态的柱形的时间外,我们还将在库的柱形对象中添加在其上发现的形态类型。由于形态类型是位标志,一个变量中可以存储多种不同类型的形态。然后,从这个变量的值中,我们可以随时提取出柱形上所有形态的类型和名称。 当从用户程序中搜索要处理的形态时,这样做非常方便:我们获取一个柱形对象,检查在其上找到的形态类型,然后处理那些标记被写入变量的模式。 在柱形对象的整数属性中 再添加一个属性 ,将 柱形对象的整数属性从 13 个增加到 14 个 : 在使用时间序列列表搜索形态并在柱形上找到形态时,我们会将找到的形态类型添加到柱形对象中的这个变量中。根据搜索不同类型形态的结果,可以在一个柱形中记录所发现的不同类型形态的标志。 在可能的柱形对象排序条件列表中 添加按柱形上的形态类型 排序: 以前,在形态类型列表中为 Harami 形态指定的值为 0。这并不完全正确。如果 0 表示柱形上没有形态 则更好。 让我们来解决这个问题 ,并 添加一个宏替换,显示库中可供搜索的形态总数 : 在形态的整数属性列表中 添加一个新属性,存储母柱的时间 ,并 将形态整数属性的数量从 9 个增加到 10 个 : 在可能的形态排序条件列表中添加新属性排序 : 在图形元素类型列表中 添加新类型(位图对象) : 这是一种与价格/时间坐标绑定的新型图库图形对象,允许您以与图库图形用户界面元素相同的方式在其上绘图。因此,它被列入了这个列表。除了在价格图表上勾画形态柱形外,我们可能还会将其用于满足库的其他需求。 在 \MQL5\Include\DoEasy\ Data.mqh 库文件中 ,添加新库消息的索引 : ... ... ... ... 及 与新增索引相对应的消息 : ... ... ... ... 通常需要检查传递给函数和方法的交易品种和图表周期值的有效性。为避免代码重复,请在 \MQL5\Include\DoEasy\Services\ DELib.mqh 中执行返回正确交易品种名称和图表周期的函数: 如果传递的图表周期为 NULL 值、空字符串、0 或 PERIOD_CURRENT ,函数将返回当前交易品种或时间框架。在其他任何情况下,它们都会返回传递给函数的值。因此,我们将逐步用这些函数替换库中所有需要对传递给方法的值的有效性进行类似检查的代码。 我们还将在此添加返回形态说明的函数: 根据传递给函数的形态类型,将返回相应的文本描述。 返回 ulong 变量中形态的数量和列表的函数: 该函数获取包含形态标志的变量和一个数组,从该变量中提取的形态类型将写入数组。由于每个标志的大小是前一个标志的两倍,因此很容易根据循环索引的值形成循环中的标志值,然后在变量值中查找是否存在这样的标志。如果将该标记写入变量,则形态类型将写入数组,数组先前增加 1,以写入新的形态类型。在按形态类型循环结束时,以标志形式写入变量的所有形态都将被输入数组,然后可在程序中使用。 向日志发送 ulong 变量中形态类型描述的函数: 代码注释中完整描述了方法逻辑。 返回对 ulong 变量中形态类型描述的函数: 所有这些函数都可以从程序的任何地方访问,用户可以轻松

「K线整数属性的枚举拆解」

在 MT5 自定义图表引擎里,单根 K 线的整数维度被收进一个枚举,方便后续用统一接口取时间、成交量与形态标记。 下面这段枚举把 BAR_PROP_TIME 设为 0,作为起始偏移;随后依次排列类型、周期、点差、 tick 量、实盘量,以及年/月/日/时/分等时间分量,共 15 个成员。 最值得盯的是 BAR_PROP_PATTERNS_TYPE:它用位标志承载该 K 线上的价格行为形态(来自 ENUM_PATTERN_TYPE),意味着一根 Bar 可同时挂多个形态标记,而不是非此即彼的分类。 开 MT5 新建一个 include 把这段枚举贴进去,编译后可用 BAR_PROP_PATTERNS_TYPE 配合位运算快速筛出含特定形态的 Bar,外汇与贵金属波动大、形态失效概率不低,仅作辅助过滤。

MQL5 / C++
enum ENUM_BAR_PROP_INTEGER
  {
   BAR_PROP_TIME = class="num">0,                                                 class=class="str">"cmt">// Bar period start time
   BAR_PROP_TYPE,                                                     class=class="str">"cmt">// Bar type(from the ENUM_BAR_BODY_TYPE enumeration)
   BAR_PROP_PERIOD,                                                   class=class="str">"cmt">// Bar period(timeframe)
   BAR_PROP_SPREAD,                                                   class=class="str">"cmt">// Bar spread
   BAR_PROP_VOLUME_TICK,                                              class=class="str">"cmt">// Bar tick volume
   BAR_PROP_VOLUME_REAL,                                              class=class="str">"cmt">// Bar exchange volume
   BAR_PROP_TIME_DAY_OF_YEAR,                                         class=class="str">"cmt">// Bar day serial number in a year
   BAR_PROP_TIME_YEAR,                                                class=class="str">"cmt">// A year the bar belongs to
   BAR_PROP_TIME_MONTH,                                               class=class="str">"cmt">// A month the bar belongs to
   BAR_PROP_TIME_DAY_OF_WEEK,                                         class=class="str">"cmt">// Bar week day
   BAR_PROP_TIME_DAY,                                                 class=class="str">"cmt">// Bar day of month(number)
   BAR_PROP_TIME_HOUR,                                                class=class="str">"cmt">// Bar hour
   BAR_PROP_TIME_MINUTE,                                              class=class="str">"cmt">// Bar minute
   BAR_PROP_PATTERNS_TYPE,                                            class=class="str">"cmt">// Pattern types on the bar(pattern flags from the ENUM_PATTERN_TYPE enumeration)
   };

K线排序枚举的字段边界

在 MT5 里做自定义 K 线排序,第一步是把可排序的字段列清楚。源码用宏把整型属性总数钉死为 14 个:BAR_PROP_INTEGER_TOTAL 定义为 14,意味着时间、类型、周期、点差、成交量等整数类字段就这么多,超了编译器会直接报错。 排序枚举 ENUM_SORT_BAR_MODE 从 0 开始排:SORT_BY_BAR_TIME 是 0,依次到 SORT_BY_BAR_PATTERN_TYPE,覆盖了从开盘时间到形态标记(ENUM_PATTERN_TYPE 标志位)的整型维度。双精度属性则从 FIRST_BAR_DBL_PROP 起算,它等于整型总数减去跳过项后的偏移,SORT_BY_BAR_OPEN 就挂在这个基址上。 实操上,如果你要在 EA 里按「小时 + 形态类型」做二维排序,直接引用 SORT_BY_BAR_TIME_HOUR 和 SORT_BY_BAR_PATTERN_TYPE 两个枚举值即可,不用自己解析时间结构体。外汇和贵金属波动受消息面影响大,这类排序只描述历史 K 线分布,不代表后续方向概率。

MQL5 / C++
class="macro">#define BAR_PROP_INTEGER_TOTAL(class="num">14)              class=class="str">"cmt">// Total number of integer bar properties
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Possible bar sorting criteria                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define FIRST_BAR_DBL_PROP(BAR_PROP_INTEGER_TOTAL-BAR_PROP_INTEGER_SKIP)
class="macro">#define FIRST_BAR_STR_PROP(BAR_PROP_INTEGER_TOTAL-BAR_PROP_INTEGER_SKIP+BAR_PROP_DOUBLE_TOTAL-BAR_PROP_DOUBLE_SKIP)
enum ENUM_SORT_BAR_MODE
  {
class=class="str">"cmt">//--- Sort by integer properties
   SORT_BY_BAR_TIME = class="num">0,                                                      class=class="str">"cmt">// Sort by bar period start time
   SORT_BY_BAR_TYPE,                                                          class=class="str">"cmt">// Sort by bar type(from the ENUM_BAR_BODY_TYPE enumeration)
   SORT_BY_BAR_PERIOD,                                                        class=class="str">"cmt">// Sort by bar period(timeframe)
   SORT_BY_BAR_SPREAD,                                                        class=class="str">"cmt">// Sort by bar spread
   SORT_BY_BAR_VOLUME_TICK,                                                   class=class="str">"cmt">// Sort by bar tick volume
   SORT_BY_BAR_VOLUME_REAL,                                                   class=class="str">"cmt">// Sort by bar exchange volume
   SORT_BY_BAR_TIME_DAY_OF_YEAR,                                              class=class="str">"cmt">// Sort by bar day number in a year
   SORT_BY_BAR_TIME_YEAR,                                                     class=class="str">"cmt">// Sort by a year the bar belongs to
   SORT_BY_BAR_TIME_MONTH,                                                    class=class="str">"cmt">// Sort by a month the bar belongs to
   SORT_BY_BAR_TIME_DAY_OF_WEEK,                                              class=class="str">"cmt">// Sort by a bar week day
   SORT_BY_BAR_TIME_DAY,                                                      class=class="str">"cmt">// Sort by a bar day
   SORT_BY_BAR_TIME_HOUR,                                                     class=class="str">"cmt">// Sort by a bar hour
   SORT_BY_BAR_TIME_MINUTE,                                                   class=class="str">"cmt">// Sort by a bar minute
   SORT_BY_BAR_PATTERN_TYPE,                                                  class=class="str">"cmt">// Sort by pattern types on the bar(pattern flags from the ENUM_PATTERN_TYPE enumeration)
class=class="str">"cmt">//--- Sort by real properties
   SORT_BY_BAR_OPEN = FIRST_BAR_DBL_PROP,                                     class=class="str">"cmt">// Sort by bar open price

◍ K线形态与排序枚举的底层定义

在 MT5 的自定义形态识别模块里,排序维度先用一组枚举把每根 bar 的可比属性列干净。从最高价、最低价、收盘价,到实体大小、上下影线长度,都给了独立的 SORT_BY_* 常量,方便后续按波动结构而非时间顺序重排信号。 字符串类属性从 FIRST_BAR_STR_PROP 起算,目前只挂了 SORT_BY_BAR_SYMBOL,意味着多品种扫描时能把异种标的先归堆再比价。 形态侧用 ENUM_PATTERN_TYPE 做位标,Harami 是 0x1、Harami Cross 是 0x2、Tweezer 是 0x4,依次左移一位。Three Black Crows 到了 0x40,说明这套定义预留了至少 64 种组合位,实操中可用按位或拼出复合过滤条件。 开 MT5 新建一个 enum 测试脚本,把上面常量原样贴进编译器,能直接看到 0x20 对应三白兵、0x40 对应三黑鸦——验证完你就可以在自己的形态扫描器里复用这套位定义。

MQL5 / C++
  SORT_BY_BAR_HIGH,                                                                     class=class="str">"cmt">// Sort by the highest price for the bar period
  SORT_BY_BAR_LOW,                                                                       class=class="str">"cmt">// Sort by the lowest price for the bar period
  SORT_BY_BAR_CLOSE,                                                                     class=class="str">"cmt">// Sort by a bar close price
  SORT_BY_BAR_CANDLE_SIZE,                                                               class=class="str">"cmt">// Sort by a candle price
  SORT_BY_BAR_CANDLE_SIZE_BODY,                                                          class=class="str">"cmt">// Sort by a candle body size
  SORT_BY_BAR_CANDLE_BODY_TOP,                                                           class=class="str">"cmt">// Sort by a candle body top
  SORT_BY_BAR_CANDLE_BODY_BOTTOM,                                                        class=class="str">"cmt">// Sort by a candle body bottom
  SORT_BY_BAR_CANDLE_SIZE_SHADOW_UP,                                                     class=class="str">"cmt">// Sort by candle upper wick size
  SORT_BY_BAR_CANDLE_SIZE_SHADOW_DOWN,                                                   class=class="str">"cmt">// Sort by candle lower wick size
class=class="str">"cmt">//--- Sort by class="type">class="kw">string properties
  SORT_BY_BAR_SYMBOL = FIRST_BAR_STR_PROP,                                               class=class="str">"cmt">// Sort by a bar symbol
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Pattern type                                                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_PATTERN_TYPE
  {
class=class="str">"cmt">//--- Candle formations
  PATTERN_TYPE_NONE                                                        =  0x0,       class=class="str">"cmt">// None
  PATTERN_TYPE_HARAMI                                                      =  0x1,       class=class="str">"cmt">// Harami
  PATTERN_TYPE_HARAMI_CROSS                                                =  0x2,       class=class="str">"cmt">// Harami Cross
  PATTERN_TYPE_TWEEZER                                                     =  0x4,       class=class="str">"cmt">// Tweezer
  PATTERN_TYPE_PIERCING_LINE                                               =  0x8,       class=class="str">"cmt">// Piercing Line
  PATTERN_TYPE_DARK_CLOUD_COVER                                            =  0x10,      class=class="str">"cmt">// Dark Cloud Cover
  PATTERN_TYPE_THREE_WHITE_SOLDIERS                                        =  0x20,      class=class="str">"cmt">// Three White Soldiers
  PATTERN_TYPE_THREE_BLACK_CROWS                                           =  0x40,      class=class="str">"cmt">// Three Black Crows
把形态扫描交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到孕线嵌套的母柱与定义柱标记,你只管判断突破方向。

常见问题

Pin Bar 是单柱形态,只看一根柱的比例;Inside Bar 是双柱及以上嵌套形态,需比较母柱与一个或多个定义柱的包含关系,并用母柱开启时间差确定总柱数。
可以,小布盯盘对应品种页内置了基于价格行为的形态扫描,会区分母柱和定义柱并画出框架,省去手动在图表上数柱。
形态类型用位标志存储,一个整数变量可记录多种形态。获取柱形对象后读该变量就能提取全部形态类型,便于用户程序按需处理。
它可绑定 bmp 资源并随柱时间价格挂钩,用来在图表上给形态包含的所有柱画外框,比单点标记更直观。
本篇完成的库类与通用嵌套搜索功能,是后续实战篇做其他形态类型和可视化样式切换的底层支撑,详见《DoEasy.服务功能(第 2 部分):孕线形态·实战篇》。