研究烛条分析技术(第二部分):自动搜索新形态(基础篇)
📘

研究烛条分析技术(第二部分):自动搜索新形态(基础篇)

第 1/3 篇

「烛条形态自动识别从哪起步」

把烛条分析做成可复用的工具,第一步不是写指标,而是先定义「哪些形态算新形态」。2019 年 MT5 社区里一篇实测帖用 3598 次浏览验证了这一点:人工标注形态再交给程序比对,比纯算法盲扫更省算力。 判定任务要落到具体字段:实体长度、上下影线比例、与前一根的关系。这些参数不先固化,后面搜索逻辑就会变成黑箱。 界面原型别一上来就做复杂面板。先能在图表上标出候选形态,交易者肉眼复核通过率,再谈自动化。外汇与贵金属波动受事件驱动明显,这种人工+程序双校验能降低误报概率。

为什么现成形态不能直接拿来用

前一篇已经拆过市面上常见的烛条分析法,结论很直接:它们不通用,套到某个品种或周期上之前,必须做额外验证。也就是说,某种形态只在特定条件组合下才值得看。 我们挑了 14 种形态做专项分析,不是所有形态都塞进来。原因很简单——已分析的形态里,4 种是单根烛条,10 种是双根烛条,底层只由 6 类烛条的不同序列构成,抓组成特征比穷举高效。 老形态最大的坑是:它们诞生的市场环境和现在不一样,而价格行为、波动节奏一直在变。所以本文不重复验证旧形态,而是搭一套系统,基于已知的 6 类烛条去搜、去测新的可能形态。 想在 MT5 里复现思路,可以先把单根/双根的分类计数写出来,统计你关心品种上各类序列的出现频率,再谈概率。外汇和贵金属杠杆高、跳空频繁,任何形态信号都只是概率倾向,不是确定性。

◍ 先框定形态池的组装规则

要写一套新的烛条形态生成算法,第一步不是找信号,而是先把「零件」和「拼法」钉死。零件只有 11 种基础烛条:长烛条、短烛条、尖顶、十字星、marubozu、锤子,各自按多空方向切分,十字星不区分方向。 拼装约束很硬:任意形态只由 1~3 根简单烛条构成,允许同种类型反复出现,比如「空頭长烛条 + 空頭长烛条」就算一个合法形态。这意味着形态池不是无限组合,而是受长度与重复规则约束的有限集合。 这套池子搭好后,后续生成的形态会沿用第一篇文章里讲过的分析原理去做判定。你在 MT5 里验证时,可以先把 11 种基础类型枚举出来,再按 1~3 根、可重复的规则暴力穷举,看实际覆盖了多少种组合。

「形态操控与设置选项卡的界面改动」

生成形态的操控被挪到了独立选项卡,元素布局与原有“分析”选项卡接近,但首列改名 Set,且表格不再固定行高,方便随形态数量伸缩。 第三个“设置”选项卡做了大幅重构,参数配置是否到位直接影响形态识别结果,所以这一页值得逐行核对。 界面新增了简单烛条类型,并给每种类型标了编号,这样能直接和反推用的“所用蜡烛”列表对上号,不用靠肉眼猜。 语言切换也补上了,目前支持俄语和英语两种界面显示。 “所用蜡烛”列表就是形态的参与者,每行带复选框,勾选即决定该类型是否进入测试池。 一组互斥切换按钮保证 AutoSearch 里不会重复加载同一形态集:只能单选一个位置。另有“反复(叠加)”双按钮,开启后形态内只允许一种烛条类型,例如三根空头 Marubozu 组合;不开启时则可出现尖顶-Marubozu-Marubozu 这类混搭。

AutoSearch 面板的索引迁移与控件落地

给原有程序加一个 AutoSearch 选项卡后,选项卡序号整体后移:原本占索引 1 的“设置”页变成索引 2,所有挂在其下的子元素链接索引都得从 1 改成 2,否则界面绑定会错位。AutoSearch 页的子元素基本复用“分析”页的逻辑,只是第一列名称和配色不同,用来在做视觉区分时少写一套代码。 “设置”页里新增了烛条参数图形资源和 CreateNameCandle() 创建的控件;语言切换支持俄/英两种,靠 ChangeLanguage() 替换文本组件,组合框选项变更时读下拉索引设语言。简单烛条类型列表用 CreateListView() 画带复选框的 11 类名称,反复开关由 CreateDualButton() 生成,左键事件里跟踪状态——反复模式只作用于“单烛条类型组成的形态”,与其尺寸无关。 跑分析前先在设置里选好简单烛条类型、是否开反复、形态含几根烛条(1/2/3 根)。若想生成 2 或 3 根形态却只勾了 1 类烛条,程序直接报错,不会偷偷跑。切到 AutoSearch 输品种(支持 Major 预短语、逗号分隔、取消勾选看全部市场观察品种),选时间帧和样本根数,点当前品种即触发 ChangeSymbol2()。 以 EURUSD、M15、8000 根 15 分钟烛条为例,结果表第一列 Set 显示如 [1,1,2],方括号内三个数字即三烛条形态用的简单烛条编号与顺序,对应“设置”里“用过的蜡烛”列表。点击品种单元格调用 ChangeSymbol2(),里面先后跑 BuildingAutoSearchTable()(按勾选生成形态写进 m_total_combitaion[] 字符串数组并显示第一列)和 GetPatternType() 重载版(拿生成形态去图表上识别、评估效率)。 效率评估把原数组改成 RATING_SET 结构,省代码且每形态带 A/B/C 评级。形态字符串先去方括号、按逗号 Split 填 elements[];单烛条无逗号只去括号。循环查形态时停在第 6 根烛条——因为除零号未闭合烛条外,还要往后看 3 根判价格走向,三烛条形态首根最小索引即为 6。CoefCalculation() 接 m_table2、行号 i、ratings[]、m_pattern_total[] 把发现数和评级算成系数写回表格。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 创建一个选项卡组                                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::CreateTabs(const class="type">int x_gap,const class="type">int y_gap)
  {
class="macro">#define TABS1_TOTAL class="num">3
class=class="str">"cmt">//--- 将指针存储到主控件
   m_tabs1.MainPointer(m_window1);
class=class="str">"cmt">//--- 属性
   m_tabs1.IsCenterText(true);
   m_tabs1.PositionMode(TABS_TOP);
   m_tabs1.AutoXResizeMode(true);
   m_tabs1.AutoYResizeMode(true);
   m_tabs1.AutoXResizeRightOffset(class="num">3);
   m_tabs1.AutoYResizeBottomOffset(class="num">25);
class=class="str">"cmt">//--- 添加指定属性的选项卡
   class="type">class="kw">string tabs_names[TABS1_TOTAL]={"Analysis","Auto search","Settings"};
   for(class="type">int i=class="num">0; i<TABS1_TOTAL; i++)
      m_tabs1.AddTab(tabs_names[i],class="num">150);
class=class="str">"cmt">//--- 创建控件
   if(!m_tabs1.CreateTabs(x_gap,y_gap))
      class="kw">return(false);
class=class="str">"cmt">//--- 将对象添加到公共对象组数组中
   CWndContainer::AddToElementsArray(class="num">0,m_tabs1);
   class="kw">return(true);
   }

◍ 窗体初始化与双选卡布局

在 CProgram 类里,CreateWindow 负责把整个 GUI 骨架一次性搭起来。先通过 CWndContainer::AddWindow 把 m_window1 注册进窗口容器,再给主窗体定尺寸:宽 750 像素、高 500 像素、字号 9,同时开启可拖动、关闭、折叠、全屏和提示按钮——这些开关直接决定用户在 MT5 图表上怎么摆弄面板。 窗体本体用 m_window1.CreateWindow 在坐标 (5,5) 生成,失败就返回 false 中断。紧接着 CreateTabs(3,43) 建出 3 个选卡、顶部偏移 43 像素,其中两个核心选卡“分析”和“AutoSearch”各自克隆了一套控件:符号过滤框、搜索框、区间框、周期下拉框,外加品种表与结果表,坐标参数完全对称(如过滤框都在 x=10,y=10,结果表都在 x=120,y=50)。 这种镜像布局意味着你改一处控件间距,另一选卡最好同步,否则肉眼能看出错位。开 MT5 挂上 EA 后,若发现第二个选卡表格超出窗体右边界,优先查 CreateTable2 的 x 参数是否被 750 宽度限制卡住。

MQL5 / C++
class="type">bool CProgram::CreateWindow(const class="type">class="kw">string caption_text)
  {
class=class="str">"cmt">//--- 将指针添加到窗口数组
   CWndContainer::AddWindow(m_window1);
class=class="str">"cmt">//--- 属性
   m_window1.XSize(class="num">750);
   m_window1.YSize(class="num">500);
   m_window1.FontSize(class="num">9);
   m_window1.IsMovable(true);
   m_window1.CloseButtonIsUsed(true);
   m_window1.CollapseButtonIsUsed(true);
   m_window1.FullscreenButtonIsUsed(true);
   m_window1.TooltipsButtonIsUsed(true);
class=class="str">"cmt">//--- 创建窗体
   if(!m_window1.CreateWindow(m_chart_id,m_subwin,caption_text,class="num">5,class="num">5))
      class="kw">return(false);
class=class="str">"cmt">//--- 选卡
   if(!CreateTabs(class="num">3,class="num">43))
      class="kw">return(false);
class=class="str">"cmt">//--- “分析” 选卡
class=class="str">"cmt">//--- 可编辑字段
   if(!CreateSymbolsFilter(m_symb_filter1,class="num">10,class="num">10,"Symbols",class="num">0))
      class="kw">return(false);
   if(!CreateRequest(m_request1,class="num">250,class="num">10,"Search",class="num">0))
      class="kw">return(false);
   if(!CreateRange(m_range1,class="num">485,class="num">10,"Range",class="num">0))
      class="kw">return(false);
class=class="str">"cmt">//--- 组合框
   if(!CreateComboBoxTF(m_timeframes1,class="num">350,class="num">10,"Timeframe",class="num">0))
      class="kw">return(false);
class=class="str">"cmt">//--- 创建品种表格
   if(!CreateSymbTable(m_symb_table1,class="num">10,class="num">50,class="num">0))
      class="kw">return(false);
class=class="str">"cmt">//--- 创建结果表格
   if(!CreateTable1(m_table1,class="num">120,class="num">50,class="num">0))
      class="kw">return(false);
class=class="str">"cmt">//--- “AutoSearch” 选卡
class=class="str">"cmt">//--- 可编辑字段
   if(!CreateSymbolsFilter(m_symb_filter2,class="num">10,class="num">10,"Symbols",class="num">1))
      class="kw">return(false);
   if(!CreateRequest(m_request2,class="num">250,class="num">10,"Search",class="num">1))
      class="kw">return(false);
   if(!CreateRange(m_range2,class="num">485,class="num">10,"Range",class="num">1))
      class="kw">return(false);
class=class="str">"cmt">//--- 组合框
   if(!CreateComboBoxTF(m_timeframes2,class="num">350,class="num">10,"Timeframe",class="num">1))
      class="kw">return(false);
class=class="str">"cmt">//--- 创建品种表格
   if(!CreateSymbTable(m_symb_table2,class="num">10,class="num">50,class="num">1))
      class="kw">return(false);
class=class="str">"cmt">//--- 创建结果表格
   if(!CreateTable2(m_table2,class="num">120,class="num">50,class="num">1))
      class="kw">return(false);
  }

常见问题

先别急着写识别逻辑,从框定形态池的组装规则起步,把要识别的烛条组合范围用明确参数定死,再谈代码实现。
现成形态往往带固定阈值和品种偏好,换到外汇或贵金属上误报率高;高风险品种尤其要重设规则,不能直接套用。
可以。小布能按你框定的形态池规则跑自动搜索,把疑似新形态标出来,你再人工确认,省去重复翻图的劳动。
界面改动主要影响控件布局,老模板的参数逻辑若没碰底层规则通常还能加载,但建议重存一次配置避免索引错位。
窗体初始化时按双选卡布局重排即可,索引迁移只改数据指向,控件落地照常拖入容器,不影响交互。