DoEasy.服务功能(第 1 部分):价格形态(基础篇)
📘

DoEasy.服务功能(第 1 部分):价格形态(基础篇)

第 1/3 篇

「给价格形态建个抽象基类」

做一套能复用的形态识别,第一步不是写 Pin Bar,而是先抽象出「形态」这件事本身。把共性——比如形态的起止柱、方向、有效性判定接口——塞进一个抽象基类,后面每加一种形态都只是派生,不改底层调用。 原文给出的系列起点很实在:先搭服务功能,再谈具体 Pin Bar。抽象形态类负责定义「什么是形态」,形态控制类负责在行情里扫描并调度这些派生类。这样 MT5 脚本里只要挂一个控制类,就能批量识别多种形态。 高风险提醒:外汇与贵金属杠杆品种里,形态识别只是概率辅助,任何形态失败率都不低,实盘前务必在 MT5 策略测试器用历史数据跑一遍。

把形态搜索塞进通用库的底层思路

DoEasy 库最初定位就是一套从交易环境取数的工具层:它能对任意数据列表做排序,也允许只挑出带特定参数的子集。在这个基础上逐步叠标准功能,用户写 EA 或指标时可以直接调库,不用每次从零解析行情。 这一节先给价格形态找好容器。时间序列类已经能从任意周期、任意品种快速拉数据,我们在此之上加形态搜索与显示工具。任何形态都带一组通用参数,先收进一个抽象基类,再按形态类型派生子类——找到的形态会挂到对应的基础柱上,一根柱可能同时背着好几种形态。 显示上不给图表硬塞图标,按程序指令才画,避免视觉污染。同一种形态允许用不同参数建多个实例,比如斜率阈值一个紧一个松,搜出来都进统一列表,先按类型捞全部、再按参数细分比对。 关键点在于:所有交易品种、所有周期搜出的形态共用一张总表,不用先倒腾到同一列表就能跨数据找共性。外汇与贵金属波动受杠杆和消息驱动,形态失效概率不低,这套结构只是方便你快速验证想法,不是信号保真。

◍ 给形态识别打地基:库类要改哪些地方

做形态识别前,得先把手里的 MQL5 通用库扩一层。核心是在 \MQL5\Include\DoEasy\Defines.mqh 里加形态相关的宏与对象类型:把「形态对象」和「形态管理对象」分开,前者描述单个形态,后者负责在时间序列里搜同类型形态并持有控制对象列表。 柱形属性这次加了烛形比例参数——即实体占整根蜡烛长度的比、上下影线各自占的比。整数参数总数从 10 扩到 13,靠这三个比例就能粗略刻画任意一根 K 线的外观,后续按比值筛候选蜡烛会方便很多。外汇与贵金属波动大、滑点随机,这个比例法只解决「长得像不像」,不解决「走了之后赚不赚」。 事件通道也要留口子:在时间序列事件枚举里补「发现新形态」的代码,并把下一个事件基数从 Skipped bars+1 改成 Pattern+1,保证后续事件号不撞车。Data.mqh 中写入新库信息索引与对应文本,Bar.mqh 私有段写计算/返回比例的方法,公有段暴露简化访问,设参和取描述两处同步接上新属性。 下面这段是集合列表 ID 的宏替换,新增的 COLLECTION_SERIES_PATTERNS_ID(0x7780)就是给时间序列形态列表留的槽位,渲染层可直接抄进 Include:

MQL5 / C++
class=class="str">"cmt">//--- Collection list IDs
class="macro">#define COLLECTION_HISTORY_ID(0x777A)             class=class="str">"cmt">// Historical collection list ID
class="macro">#define COLLECTION_MARKET_ID(0x777B)             class=class="str">"cmt">// Market collection list ID
class="macro">#define COLLECTION_EVENTS_ID(0x777C)             class=class="str">"cmt">// Event collection list ID
class="macro">#define COLLECTION_ACCOUNT_ID(0x777D)             class=class="str">"cmt">// Account collection list ID
class="macro">#define COLLECTION_SYMBOLS_ID(0x777E)             class=class="str">"cmt">// Symbol collection list ID
class="macro">#define COLLECTION_SERIES_ID(0x777F)             class=class="str">"cmt">// Timeseries collection list ID
class="macro">#define COLLECTION_SERIES_PATTERNS_ID(0x7780)             class=class="str">"cmt">// Timeseries pattern list ID
class="macro">#define COLLECTION_BUFFERS_ID(0x7781)             class=class="str">"cmt">// Indicator buffer collection list ID
class="macro">#define COLLECTION_INDICATORS_ID(0x7782)             class=class="str">"cmt">// Indicator collection list ID
class="macro">#define COLLECTION_INDICATORS_DATA_ID(0x7783)             class=class="str">"cmt">// Indicator data collection list ID
class="macro">#define COLLECTION_TICKSERIES_ID(0x7784)             class=class="str">"cmt">// Tick series collection list ID
class="macro">#define COLLECTION_MBOOKSERIES_ID(0x7785)             class=class="str">"cmt">// DOM series collection list ID
class="macro">#define COLLECTION_MQL5_SIGNALS_ID(0x7786)             class=class="str">"cmt">// MQL5 signals collection list ID
class="macro">#define COLLECTION_CHARTS_ID(0x7787)             class=class="str">"cmt">// Chart collection list ID

「对象集合与K线属性的底层枚举」

在 MT5 自建指标或图形对象管理模块时,先给集合和对象类型分配固定 ID 能避免运行时冲突。下面这组宏把图表窗口列表定为 0x7788、图形对象集合定为 0x7789,并以图形对象集合 ID 作为枚举终点,相当于给后续 pending 请求类型划了一条边界。 待处理请求类型覆盖了 BAR、周期序列、品种序列,以及容易被忽略的 PATTERN 相关对象(OBJECT_DE_TYPE_SERIES_PATTERN 到 OBJECT_DE_TYPE_SERIES_PATTERNS_CONTROLLERS)。如果你要在 EA 里批量识别形态,这几个类型 ID 必须进自己的分发逻辑,否则图形对象事件会漏处理。 真实 K 线属性走 ENUM_BAR_PROP_DOUBLE 枚举,起点挂在 BAR_PROP_INTEGER_TOTAL 之后。除了 OHLC 四个基础价,还拆出了蜡烛整体大小、实体大小、实体上下沿以及上影线长度——BAR_PROP_CANDLE_SIZE_SHADOW_UP 单独拎出来,意味着你算 Pin Bar 影线占比时不用自己减高低点。 把这些枚举直接贴进头文件,开 MT5 用 iBarShift 配合 BAR_PROP_HIGH/LOW 回读几根 EURUSD 的 M5 蜡烛,验证上影线字段和你手算的差值是否恒为 0。外汇与贵金属杠杆高,这类底层字段接实盘前务必在策略测试器跑通。

MQL5 / C++
class="macro">#define COLLECTION_CHART_WND_ID(0x7788)                 class=class="str">"cmt">// Chart window list ID
class="macro">#define COLLECTION_GRAPH_OBJ_ID(0x7789)                 class=class="str">"cmt">// Graphical object collection list ID
class="macro">#define COLLECTION_ID_LIST_END(COLLECTION_GRAPH_OBJ_ID) class=class="str">"cmt">// End of collection ID list
class=class="str">"cmt">//--- Pending request type IDs
  OBJECT_DE_TYPE_SERIES_BAR,                                            class=class="str">"cmt">// "Bar" object type
  OBJECT_DE_TYPE_SERIES_PERIOD,                                         class=class="str">"cmt">// "Period timeseries" object type
  OBJECT_DE_TYPE_SERIES_SYMBOL,                                         class=class="str">"cmt">// "Symbol timeseries" object type
  OBJECT_DE_TYPE_SERIES_PATTERN,                                        class=class="str">"cmt">// "Pattern" object type
  OBJECT_DE_TYPE_SERIES_PATTERN_CONTROL,                                class=class="str">"cmt">// "Pattern management" object type
  OBJECT_DE_TYPE_SERIES_PATTERNS_CONTROLLERS,                           class=class="str">"cmt">// "Patterns management" object type
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Real bar properties                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_BAR_PROP_DOUBLE
  {
class=class="str">"cmt">//--- bar data
  BAR_PROP_OPEN = BAR_PROP_INTEGER_TOTAL,                              class=class="str">"cmt">// Bar open price
  BAR_PROP_HIGH,                                                       class=class="str">"cmt">// Highest price for the bar period
  BAR_PROP_LOW,                                                        class=class="str">"cmt">// Lowest price for the bar period
  BAR_PROP_CLOSE,                                                      class=class="str">"cmt">// Bar close price
class=class="str">"cmt">//--- candle data
  BAR_PROP_CANDLE_SIZE,                                                class=class="str">"cmt">// Candle size
  BAR_PROP_CANDLE_SIZE_BODY,                                           class=class="str">"cmt">// Candle body size
  BAR_PROP_CANDLE_BODY_TOP,                                            class=class="str">"cmt">// Candle body top
  BAR_PROP_CANDLE_BODY_BOTTOM,                                         class=class="str">"cmt">// Candle body bottom
  BAR_PROP_CANDLE_SIZE_SHADOW_UP,                                      class=class="str">"cmt">// Candle upper wick size
  };

K线比例与形态枚举的底层定义

在 MT5 里做价格行为识别,第一步是把单根 BAR 的几何特征量化。下面这组枚举把下影线长度、实体占整根蜡烛的百分比、上下影线各自占比都拆成了独立属性,后续排序和模式匹配直接读这些字段即可。 BAR_PROP_RATIO_BODY_TO_CANDLE_SIZE 给出实体相对全长的百分比,BAR_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE 与 BAR_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE 则分别锁定上下影线占比。实盘里若下影线占比连续 3 根超过 60%,价格倾向在外汇或贵金属上出现短线反弹,但杠杆品种高风险,须结合止损。 宏定义里 BAR_PROP_DOUBLE_TOTAL 写死为 13,代表参与计算的真实 BAR 属性总数;BAR_PROP_DOUBLE_SKIP 为 0 表示没有属性被排除在排序之外。你可以开 MT5 的 MetaEditor 全局搜这两个宏,确认自己用的标准库版本是否一致。 形态侧用三个枚举收口:ENUM_PATTERN_STATUS 区分裸蜡烛(JC)与价格行为组合(PA);ENUM_PATTERN_DIRECTION 标买 / 卖 / 双向;ENUM_PATTERN_TYPE 则用十六进制位标记 Harami(0x0)、Harami Cross(0x1)、Tweezer(0x2)、Piercing Line(0x4)。位偏移设计方便用按位或做复合形态判定。

MQL5 / C++
  BAR_PROP_CANDLE_SIZE_SHADOW_DOWN,                                              class=class="str">"cmt">// Candle lower wick size
class=class="str">"cmt">//--- candle proportions
  BAR_PROP_RATIO_BODY_TO_CANDLE_SIZE,                                              class=class="str">"cmt">// Percentage ratio of the candle body to the full size of the candle
  BAR_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,                                      class=class="str">"cmt">// Percentage ratio of the upper shadow size to the candle size
  BAR_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,                                      class=class="str">"cmt">// Percentage ratio of the lower shadow size to the candle size
  };
class="macro">#define BAR_PROP_DOUBLE_TOTAL(class="num">13)                                                class=class="str">"cmt">// Total number of real bar properties
class="macro">#define BAR_PROP_DOUBLE_SKIP(class="num">0)                                                 class=class="str">"cmt">// Number of bar properties not used in sorting
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Abstract pattern status                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_PATTERN_STATUS
  {
  PATTERN_STATUS_JC,                                                               class=class="str">"cmt">// Candles
  PATTERN_STATUS_PA,                                                               class=class="str">"cmt">// Price Action formations
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Pattern type by direction(buy/sell)                             |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_PATTERN_DIRECTION
  {
  PATTERN_DIRECTION_BULLISH,                                                       class=class="str">"cmt">// Buy pattern
  PATTERN_DIRECTION_BEARISH,                                                       class=class="str">"cmt">// Sell pattern
  PATTERN_DIRECTION_BOTH,                                                          class=class="str">"cmt">// Bidirectional pattern
  };
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_HARAMI          =  0x0,                                             class=class="str">"cmt">// Harami
  PATTERN_TYPE_HARAMI_CROSS    =  0x1,                                             class=class="str">"cmt">// Harami Cross
  PATTERN_TYPE_TWEEZER         =  0x2,                                             class=class="str">"cmt">// Tweezer
  PATTERN_TYPE_PIERCING_LINE   =  0x4,                                             class=class="str">"cmt">// Piercing Line

◍ 蜡烛与价格行为模式的位掩码定义

在 MT5 的自定义指标或 EA 里,常见做法是把几十种 K 线形态塞进一个整型枚举,用十六进制位掩码来标记。下面这段定义覆盖了从经典吞没变体到价格行为专用结构,总共 26 个常量,最高位用到 0x800000,也就是第 24 位。 看数值排布能发现规律:0x8 到 0x10000 是传统蜡烛形态(乌云盖顶、三白兵、三乌鸦、流星、锤子、十字星家族、晨星暮星等),从 0x80000 开始切到 Price Action 分支——枢轴反转、外包线、内包线、Pin Bar、Rails 各占一段连续位宽。 这种位掩码写法让你在运行时用一个 int 变量就能同时记录多个形态命中。比如某根棒同时满足 Inside Bar(0x200000) 和 Pin Bar(0x400000),按位或之后得到 0x600000,传给小布这类 AIGC 扫描模块做过滤就很轻量。 外汇和贵金属市场波动剧烈,形态命中只代表概率倾向,实盘前务必在 MT5 策略测试器里用历史数据回看命中后的胜率分布,别把位掩码当信号圣杯。

MQL5 / C++
  PATTERN_TYPE_DARK_CLOUD_COVER     = 0x8,           class=class="str">"cmt">// Dark Cloud Cover
  PATTERN_TYPE_THREE_WHITE_SOLDIERS= 0x10,           class=class="str">"cmt">// Three White Soldiers
  PATTERN_TYPE_THREE_BLACK_CROWS   = 0x20,           class=class="str">"cmt">// Three Black Crows
  PATTERN_TYPE_SHOOTING_STAR       = 0x40,           class=class="str">"cmt">// Shooting Star
  PATTERN_TYPE_HAMMER              = 0x80,           class=class="str">"cmt">// Hammer
  PATTERN_TYPE_INVERTED_HAMMER     = 0x100,          class=class="str">"cmt">// Inverted Hammer
  PATTERN_TYPE_HANGING_MAN         = 0x200,          class=class="str">"cmt">// Hanging Man
  PATTERN_TYPE_DOJI                = 0x400,          class=class="str">"cmt">// Doji
  PATTERN_TYPE_DRAGONFLY_DOJI      = 0x800,          class=class="str">"cmt">// Dragonfly Doji
  PATTERN_TYPE_GRAVESTONE_DOJI     = 0x1000,         class=class="str">"cmt">// Gravestone Doji
  PATTERN_TYPE_MORNING_STAR        = 0x2000,         class=class="str">"cmt">// Morning Star
  PATTERN_TYPE_MORNING_DOJI_STAR   = 0x4000,         class=class="str">"cmt">// Morning Doji Star
  PATTERN_TYPE_EVENING_STAR        = 0x8000,         class=class="str">"cmt">// Evening Star
  PATTERN_TYPE_EVENING_DOJI_STAR   = 0x10000,        class=class="str">"cmt">// Evening Doji Star
  PATTERN_TYPE_THREE_STARS         = 0x20000,        class=class="str">"cmt">// Three Stars
  PATTERN_TYPE_ABANDONED_BABY      = 0x40000,        class=class="str">"cmt">// Abandoned Baby
class=class="str">"cmt">//--- Price Action
  PATTERN_TYPE_PIVOT_POINT_REVERSAL= 0x80000,        class=class="str">"cmt">// Price Action Reversal Pattern
  PATTERN_TYPE_OUTSIDE_BAR         = 0x100000,       class=class="str">"cmt">// Price Action Outside Bar
  PATTERN_TYPE_INSIDE_BAR          = 0x200000,       class=class="str">"cmt">// Price Action Inside Bar
  PATTERN_TYPE_PIN_BAR             = 0x400000,       class=class="str">"cmt">// Price Action Pin Bar
  PATTERN_TYPE_RAILS               = 0x800000,       class=class="str">"cmt">// Price Action Rails
  };

常见问题

先建一个抽象基类把形态的共性(如起止K线、判定接口)抽出来,再往通用库底层塞搜索逻辑,别直接在EA里硬写。
所有品种和周期共用一套识别代码,改一次全库生效,不用每个策略重复造轮子,回测也更快。
可以,小布盯盘的AIGC会直接标注常见价格行为形态,打开对应品种页就能看到,不用自己写代码跑。
用独立枚举列明形态类型和K线缩放比例,配合位掩码标记蜡烛属性,避免后面扩展时命名冲突。
至少补上单根K线的实体比例、上下影线长度、以及与前一根的相对位置,底层枚举齐了上层才好写判定。