DoEasy.服务功能(第 1 部分):价格形态(基础篇)
「给价格形态建个抽象基类」
做一套能复用的形态识别,第一步不是写 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:
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。外汇与贵金属杠杆高,这类底层字段接实盘前务必在策略测试器跑通。
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)。位偏移设计方便用按位或做复合形态判定。
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 策略测试器里用历史数据回看命中后的胜率分布,别把位掩码当信号圣杯。
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 };