基于 Merill(梅里尔) 形态的策略构建器·进阶篇
🛠️

基于 Merill(梅里尔) 形态的策略构建器·进阶篇

(2/3)· 前篇看懂了形态,这篇教你用界面把买/卖信号拼成能跑测试的策略

进阶 第 2/3 篇
很多人把梅里尔形态当成单点信号硬上,结果不同品种周期一换就失灵。其实形态能挂到 ATR、RSI 这类指标上组合使用,只是缺一个能快速试错的工具。这篇就给你那个工具箱的骨架。

「面板控件的坐标与默认值布局」

这段初始化逻辑把交易面板的各类控件按窗口尺寸动态排布,左列占 35% 宽度、右列占 75% 宽度,均扣掉固定的 150 像素边距再偏移。以 XSize=800 的窗口为例,右列起点横坐标约为 int(0.75*(800-150)-100)=387,左列约为 int(0.35*(800-150)-120)=95。 AppliedType4~6 三个下拉控件依次放在右列 y=80+ygap、y=116+ygap、y=149+ygap 处(50+33*2、50+33*3 推算),任一创建失败直接 return(false) 中断面板构建。 信号勾选框用 for(i=2;i<8) 循环生成 6 个:i<5 时落在左列(Signal 1~3),i>=5 时落在右列(Signal 1~3),纵向间隔 35 像素。 止盈止损编辑框左右各一对,默认值均设为 500、最小步长 0,说明该面板默认以点数(或小数位换算)方式输入,外汇与贵金属品种请自行核对点值风险。 最下方 CreateReportFrame 在左列 60+35*6+ygap 处留一块空报告区,后续由分析逻辑填数。

MQL5 / C++
  if(!AppliedType4(class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">100),class="num">80+ygap))
      class="kw">return(false);
  if(!AppliedType5(class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">100),class="num">50+class="num">33*class="num">2+ygap))
      class="kw">return(false);
  if(!AppliedType6(class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">100),class="num">50+class="num">33*class="num">3+ygap))
      class="kw">return(false);
class=class="str">"cmt">//--- Signal checkboxes
  for(class="type">int i=class="num">2; i<class="num">8; i++)
  {
    if(i<class="num">5)
      if(!CreateCheckBox(m_checkbox[i],class="type">int(class="num">0.35*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">50+class="num">35*(i-class="num">1)+ygap,"Signal "+class="type">class="kw">string(i-class="num">1)))
        class="kw">return(false);
    if(i>=class="num">5)
      if(!CreateCheckBox(m_checkbox[i],class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">50+class="num">35*(i-class="num">4)+ygap,"Signal "+class="type">class="kw">string(i-class="num">4)))
        class="kw">return(false);
  }
class=class="str">"cmt">//--- Take Profit and Stop Loss settings
  if(!CreateEditValue(m_takeprofit1,class="type">int(class="num">0.35*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">50+class="num">35*class="num">4+ygap,"Take Profit",class="num">500,class="num">0))
      class="kw">return(false);
  if(!CreateEditValue(m_stoploss1,class="type">int(class="num">0.35*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">50+class="num">35*class="num">5+ygap,"Stop Loss",class="num">500,class="num">0))
      class="kw">return(false);
  if(!CreateEditValue(m_takeprofit2,class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">50+class="num">35*class="num">4+ygap,"Take Profit",class="num">500,class="num">0))
      class="kw">return(false);
  if(!CreateEditValue(m_stoploss2,class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">50+class="num">35*class="num">5+ygap,"Stop Loss",class="num">500,class="num">0))
      class="kw">return(false);
class=class="str">"cmt">//--- Report
  if(!CreateReportFrame(m_frame[class="num">2],"",class="type">int(class="num">0.35*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">60+class="num">35*class="num">6+ygap))
      class="kw">return(false);

◍ 把报告标签和筛选框摆进界面

这段逻辑负责把 6 个文本标签按两列排布,并初始化一个带输入框的品种过滤器。循环里 i<3 的标签挂在左列,x 坐标取主窗口宽度减 150 后的 0.4 倍再减 120;i>=3 的挂在右列,用 0.75 倍系数,纵向间隔固定 35 像素,因此左右两列各占 3 行、行高一致。 CreateSymbolsFilter 里把复选框模式打开,文本框宽度设 100、字号 11,默认填 "USD"。注释里留了 "EUR,USD" 到多品种组合的写法,实盘接行情请求时可直接改这个值来缩减扫描范围,外汇与贵金属波动剧烈,过滤不当可能漏掉异动品种。 CreateSymbolsTable 目前只定义了 1 行,列宽数组写死 119、居中对齐、文本 X 偏移 5。想扩成多品种监控表,先把 ROWS1_TOTAL 和 width 数组长度改掉,否则后面挂数据会越界返回 false。

MQL5 / C++
for(class="type">int i=class="num">0; i<class="num">6; i++)
{
   if(i<class="num">3)
      if(!CreateTextLabel(m_report_text[i],class="type">int(class="num">0.4*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">60+class="num">35*(class="num">7+i)+ygap,"",class="num">0))
         class="kw">return(false);
   if(i>=class="num">3)
      if(!CreateTextLabel(m_report_text[i],class="type">int(class="num">0.75*(m_window[class="num">0].XSize()-class="num">150)-class="num">120),class="num">60+class="num">35*(class="num">7+i-class="num">3)+ygap,"",class="num">0))
         class="kw">return(false);
   m_report_text[i].IsCenterText(false);
}

class="type">bool CProgram::CreateSymbolsFilter(const class="type">int x_gap,const class="type">int y_gap)
{
   m_symb_filter.MainPointer(m_tabs1);
   m_tabs1.AddToElementsArray(class="num">0,m_symb_filter);
   m_symb_filter.CheckBoxMode(true);
   m_symb_filter.YSize(class="num">25);
   m_symb_filter.FontSize(class="num">11);
   m_symb_filter.XSize(class="num">200);
   m_symb_filter.GetTextBoxPointer().XGap(class="num">20);
   m_symb_filter.GetTextBoxPointer().XSize(class="num">100);
   m_symb_filter.GetTextBoxPointer().YSize(class="num">25);
   m_symb_filter.GetTextBoxPointer().AutoSelectionMode(true);
   m_symb_filter.SetValue("USD");
   if(!m_symb_filter.CreateTextEdit("",x_gap,y_gap))
      class="kw">return(false);
   m_symb_filter.IsPressed(true);
   CWndContainer::AddToElementsArray(class="num">0,m_symb_filter);
   if(!CreateRequest(x_gap+class="num">125,y_gap))
      class="kw">return(false);
   class="kw">return(true);
}

class="type">bool CProgram::CreateSymbolsTable(const class="type">int x_gap,const class="type">int y_gap)
{
class="macro">#define ROWS1_TOTAL   class="num">1
   m_table_symb.MainPointer(m_tabs1);
   m_tabs1.AddToElementsArray(class="num">0,m_table_symb);
   class="type">int width[class="num">1]= {class="num">119};
   ENUM_ALIGN_MODE align[class="num">1]= {ALIGN_CENTER};
   class="type">int text_x_offset[class="num">1]= {class="num">5};

用代码拼出面板里的表格与控件

在 MT5 自定义面板里,表格和按钮不是画出来的,是靠 CTable、CTextLabel、CButton 这几个类逐个属性喂出来的。下面这段配置把符号表格的宽度锁在 120 像素、字号 10、表头底色 C'0,130,255'(蓝),并开启斑马纹(clrWhiteSmoke)和自动纵向拉伸(底部留 3 像素),读者可以直接抄进自己的 EA 界面工程。 表格创建失败就直接 return(false),成功才通过 CWndContainer::AddToElementsArray(0,m_table_symb) 挂进全局元素数组——这意味着索引 0 通常是主容器,别在别处误用同一个槽位。 文本标签那边用了 Trebuchet 字体、字号 11、宽 200、居中、颜色 C'0,100,255',并绑定到指定 tab。按钮则固定 100×25 像素、aliceBlue 底、边框 C'0,100,255',标题写死 "Date range"。这三个 Create 函数都返回 bool,调用方必须判返回值,否则界面元素缺失也不会报错。 外汇与贵金属行情波动剧烈、杠杆风险高,这类界面只解决信息展示,不涉及任何方向判断。

MQL5 / C++
  m_table_symb.XSize(class="num">120);
  m_table_symb.TableSize(class="num">1,ROWS1_TOTAL);
  m_table_symb.ColumnsWidth(width);
  m_table_symb.TextAlign(align);
  m_table_symb.FontSize(class="num">10);
  m_table_symb.TextXOffset(text_x_offset);
  m_table_symb.ShowHeaders(true);
  m_table_symb.SelectableRow(true);
  m_table_symb.IsWithoutDeselect(true);
  m_table_symb.IsZebraFormatRows(clrWhiteSmoke);
  m_table_symb.AutoYResizeMode(true);
  m_table_symb.AutoYResizeBottomOffset(class="num">3);
  m_table_symb.HeadersColor(C&class="macro">#x27;class="num">0,class="num">130,class="num">255&class="macro">#x27;);
  m_table_symb.HeadersColorHover(clrCornflowerBlue);
  m_table_symb.HeadersTextColor(clrWhite);
  m_table_symb.BorderColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
class=class="str">"cmt">//--- Creating a control
  if(!m_table_symb.CreateTable(x_gap,y_gap))
     class="kw">return(false);
class=class="str">"cmt">//--- Add the object to the common array of object groups
  CWndContainer::AddToElementsArray(class="num">0,m_table_symb);
  class="kw">return(true);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Creates a text label in the first tab                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::CreateTextLabel(CTextLabel &text_label,const class="type">int x_gap,const class="type">int y_gap,class="type">class="kw">string label_text,class="type">int tab)
{
class=class="str">"cmt">//--- Save the window pointer
  text_label.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
  m_tabs1.AddToElementsArray(tab,text_label);
class=class="str">"cmt">//---
  text_label.Font("Trebuchet");
  text_label.FontSize(class="num">11);
  text_label.XSize(class="num">200);
  text_label.LabelColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
  text_label.IsCenterText(true);
class=class="str">"cmt">//--- Creation of a button
  if(!text_label.CreateTextLabel(label_text,x_gap,y_gap))
     class="kw">return(false);
class=class="str">"cmt">//--- Add the element pointer to the data base
  CWndContainer::AddToElementsArray(class="num">0,text_label);
  class="kw">return(true);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Creates a button to show the date range selection window         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::CreateButton(CButton &button,const class="type">int x_gap,const class="type">int y_gap)
{
class=class="str">"cmt">//--- Save the pointer to the main control
  button.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
  m_tabs1.AddToElementsArray(class="num">0,button);
class=class="str">"cmt">//--- Properties
  button.XSize(class="num">100);
  button.YSize(class="num">25);
  button.FontSize(class="num">11);
  button.IsHighlighted(false);
  button.IsCenterText(true);
  button.BorderColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
  button.BackColor(clrAliceBlue);
class=class="str">"cmt">//--- Creating a control
  if(!button.CreateButton("Date range",x_gap,y_gap))
     class="kw">return(false);
class=class="str">"cmt">//--- Add the element pointer to the data base
  CWndContainer::AddToElementsArray(class="num">0,button);
  class="kw">return(true);
}

「周期下拉与勾选控件的挂载细节」

在自定义面板里塞周期选择器,核心是把 21 个周期字符串先写死进数组再灌给 combobox。MQL5 标准库里从 M1 到 MN 正好 21 档,代码里 timeframe_names[21] 的长度和 ItemsTotal(21) 必须对上,少一个就会在 SetValue 循环里越界。 下拉框本体尺寸定成宽 50 高 25、字号 12,按钮字号压到 10、背景用 clrAliceBlue,悬停高亮靠 lv.LightsHover(true) 打开。默认选中第 0 项即 M1,若想面板一开就停在当前图表周期,得把 SelectItem(0) 换成对应索引。 复选框走另一套 CreateCheckBox:挂到同一个 tab 容器后,设 GreenCheckBox(true)IsPressed(true) 让它默认勾上,标签色用 C'0,100,255' 的蓝。两个控件都通过 CWndContainer::AddToElementsArray(0,...) 进总组,参数 0 代表第一个标签页——外汇和贵金属品种上挂这类 UI 属于轻量改造,但 MT5 自定义面板在实盘重载时可能丢状态,高风险操作前先于模拟盘验证。

MQL5 / C++
class="type">bool CProgram::CreateTimeframe1(const class="type">int x_gap,const class="type">int y_gap)
{
class=class="str">"cmt">//--- Pass the object to the panel
   m_timeframe1.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
   m_tabs1.AddToElementsArray(class="num">0,m_timeframe1);
class=class="str">"cmt">//--- Array of the item values in the list view
   class="type">class="kw">string timeframe_names[class="num">21]=
   {
      "M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30",
      "H1","H2","H3","H4","H6","H8","H12","D1","W1","MN"
   };
class=class="str">"cmt">//--- Set properties before creation
   m_timeframe1.XSize(class="num">50);
   m_timeframe1.YSize(class="num">25);
   m_timeframe1.ItemsTotal(class="num">21);
   m_timeframe1.FontSize(class="num">12);
   m_timeframe1.LabelColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
   CButton *but=m_timeframe1.GetButtonPointer();
   but.FontSize(class="num">10);
   but.XSize(class="num">50);
   but.BackColor(clrAliceBlue);
   but.XGap(class="num">1);
   m_timeframe1.GetListViewPointer().FontSize(class="num">10);
class=class="str">"cmt">//--- Save the item values in the combobox list view
   for(class="type">int i=class="num">0; i<class="num">21; i++)
      m_timeframe1.SetValue(i,timeframe_names[i]);
class=class="str">"cmt">//--- Get the list view pointer
   CListView *lv=m_timeframe1.GetListViewPointer();
class=class="str">"cmt">//--- Set the list view properties
   lv.LightsHover(true);
   m_timeframe1.SelectItem(class="num">0);
class=class="str">"cmt">//--- Creating a control
   if(!m_timeframe1.CreateComboBox("",x_gap,y_gap))
      class="kw">return(false);
class=class="str">"cmt">//--- Add the object to the common array of object groups
   CWndContainer::AddToElementsArray(class="num">0,m_timeframe1);
   class="kw">return(true);
}
class="type">bool CProgram::CreateCheckBox(CCheckBox &checkbox,const class="type">int x_gap,const class="type">int y_gap,const class="type">class="kw">string text)
{
class=class="str">"cmt">//--- Save the pointer to the main control
   checkbox.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
   m_tabs1.AddToElementsArray(class="num">0,checkbox);
class=class="str">"cmt">//--- Properties
   checkbox.YSize(class="num">25);
   checkbox.GreenCheckBox(true);
   checkbox.IsPressed(true);
   checkbox.FontSize(class="num">12);
   checkbox.LabelColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
   checkbox.LabelColorPressed(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
class=class="str">"cmt">//--- Creating a control
   if(!checkbox.CreateCheckBox(text,x_gap,y_gap))
      class="kw">return(false);
class=class="str">"cmt">//--- Add the element pointer to the data base
   CWndContainer::AddToElementsArray(class="num">0,checkbox);
   class="kw">return(true);
}

◍ 下拉框里塞进 32 种形态与 9 类信号源

在 MT5 自定义面板里做形态筛选器,核心是先建两个组合框:一个装形态名,一个装信号源。第一段代码 PatternType1 用 ITEMS_TOTAL1 宏写死 32 个选项,M1–M16 与 W1–W16 分别覆盖分钟与周线级别的形态标签,下拉列表宽度 200、行高 25,字体 10 号,按钮底色 clrAliceBlue。 循环里把 pattern_names 数组逐项写进组合框列表视图,再用 SelectItem(0) 默认勾中第一项 M1;列表视图开了 LightsHover(true),鼠标悬停会高亮。CreateComboBox 失败直接返回 false,成功才挂到对象容器,这套写法能保证面板初始化时不卡壳。 第二个函数 AppliedType1 只放 9 个信号源:Price、ATR、CCI、DeMarker、Force Ind、WPR、RSI、Momentum、Custom。它绑到 tab 0,尺寸和字体设置和形态框一致,方便交易者在同一行对照「形态 × 信号源」做条件组合。外汇与贵金属波动剧烈,这类面板只是辅助筛样,实盘信号仍需人工复核,杠杆品种高风险不可忽视。

MQL5 / C++
class="type">bool CProgram::PatternType1(const class="type">int x_gap,const class="type">int y_gap,const class="type">int tab)
{
class=class="str">"cmt">//--- Total number of the list items
class="macro">#define ITEMS_TOTAL1 class="num">32
class=class="str">"cmt">//--- Pass the object to the panel
   m_combobox1.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
   m_tabs1.AddToElementsArray(tab,m_combobox1);
class=class="str">"cmt">//--- Array of the item values in the list view
   class="type">class="kw">string pattern_names[ITEMS_TOTAL1]=
   {
      "M1","M2","M3","M4","M5","M6","M7","M8",
      "M9","M10","M11","M12","M13","M14","M15","M16",
      "W1","W2","W3","W4","W5","W6","W7","W8",
      "W9","W10","W11","W12","W13","W14","W15","W16"
   };
class=class="str">"cmt">//--- Set properties before creation
   m_combobox1.XSize(class="num">200);
   m_combobox1.YSize(class="num">25);
   m_combobox1.ItemsTotal(ITEMS_TOTAL1);
   m_combobox1.GetButtonPointer().FontSize(class="num">10);
   m_combobox1.GetButtonPointer().BackColor(clrAliceBlue);
   m_combobox1.GetListViewPointer().FontSize(class="num">10);
class=class="str">"cmt">//--- Save the item values in the combobox list view
   for(class="type">int i=class="num">0; i<ITEMS_TOTAL1; i++)
      m_combobox1.SetValue(i,pattern_names[i]);
class=class="str">"cmt">//--- Get the list view pointer
   CListView *lv=m_combobox1.GetListViewPointer();
class=class="str">"cmt">//--- Set the list view properties
   lv.LightsHover(true);
   m_combobox1.SelectItem(class="num">0);
class=class="str">"cmt">//--- Creating a control
   if(!m_combobox1.CreateComboBox("",x_gap,y_gap))
      class="kw">return(false);
class=class="str">"cmt">//--- Add the object to the common array of object groups
   CWndContainer::AddToElementsArray(class="num">0,m_combobox1);
   class="kw">return(true);
}
class="type">bool CProgram::AppliedType1(const class="type">int x_gap,const class="type">int y_gap)
{
class=class="str">"cmt">//--- Pass the object to the panel
   m_applied1.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
   m_tabs1.AddToElementsArray(class="num">0,m_applied1);
class=class="str">"cmt">//--- Array of the item values in the list view
   class="type">class="kw">string pattern_names[class="num">9]=
   {
      "Price","ATR","CCI","DeMarker","Force Ind","WPR","RSI","Momentum","Custom"
   };
class=class="str">"cmt">//--- Set properties before creation
   m_applied1.XSize(class="num">200);
   m_applied1.YSize(class="num">25);
   m_applied1.ItemsTotal(class="num">9);
   m_applied1.GetButtonPointer().FontSize(class="num">10);
   m_applied1.GetButtonPointer().BackColor(clrAliceBlue);
   m_applied1.GetListViewPointer().FontSize(class="num">10);

把控件塞进标签页的实操写法

下拉框这里先循环把 9 个形态名写进列表,再拿 CListView 指针开 hover 高亮,默认选中第 0 项。CreateComboBox 失败直接返回 false,成功才丢进公共元素数组,这套顺序在 MT5 自定义面板里少一步都会白屏。 文本输入框的宽度锁在 210、高度 24,标签色用 C'0,100,255',字号 12;边界值设了 MinValue(10) 和 MaxValue(1000),SpinEditMode 开true 后用户能用箭头调参,TextBox 的 XGap 给了 100 像素避免和标签重叠。 Frame 容器挂到 tab 索引 1,尺寸 350×500,开了 AutoYResizeMode 且底部留 100 偏移,文本标签宽度单独设 250。外汇和贵金属图表加载这类 UI 高风险,参数越界可能让 EA 在实盘挂掉,建议先在策略测试器里跑一遍。 下面三段是可直接抄的构建函数,改 x_gap/y_gap 就能挪位置,不用动整体结构。

MQL5 / C++
class=class="str">"cmt">//--- Save the item values in the combobox list view
  for(class="type">int i=class="num">0; i<class="num">9; i++)
    m_applied1.SetValue(i,pattern_names[i]);
class=class="str">"cmt">//--- Get the list view pointer
  CListView *lv=m_applied1.GetListViewPointer();
class=class="str">"cmt">//--- Set the list view properties
  lv.LightsHover(true);
  m_applied1.SelectItem(class="num">0);
class=class="str">"cmt">//--- Creating a control
  if(!m_applied1.CreateComboBox("",x_gap,y_gap))
    class="kw">return(false);
class=class="str">"cmt">//--- Add the object to the common array of object groups
  CWndContainer::AddToElementsArray(class="num">0,m_applied1);
  class="kw">return(true);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Creates an input field                                          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::CreateEditValue(CTextEdit &text_edit,const class="type">int x_gap,const class="type">int y_gap,const class="type">class="kw">string label_text,const class="type">int value,const class="type">int tab)
{
class=class="str">"cmt">//--- Save the pointer to the main control
  text_edit.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
  m_tabs1.AddToElementsArray(tab,text_edit);
class=class="str">"cmt">//--- Properties
  text_edit.XSize(class="num">210);
  text_edit.YSize(class="num">24);
  text_edit.LabelColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
  text_edit.FontSize(class="num">12);
  text_edit.MaxValue(class="num">1000);
  text_edit.MinValue(class="num">10);
  text_edit.SpinEditMode(true);
  text_edit.SetValue((class="type">class="kw">string)value);
  text_edit.GetTextBoxPointer().AutoSelectionMode(true);
  text_edit.GetTextBoxPointer().XGap(class="num">100);
class=class="str">"cmt">//--- Creating a control
  if(!text_edit.CreateTextEdit(label_text,x_gap,y_gap))
    class="kw">return(false);
class=class="str">"cmt">//--- Add the object to the common array of object groups
  CWndContainer::AddToElementsArray(class="num">0,text_edit);
  class="kw">return(true);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::CreateFrame(CFrame &frame,const class="type">class="kw">string text,const class="type">int x_gap,const class="type">int y_gap)
{
class=class="str">"cmt">//--- Save the pointer to the main control
  frame.MainPointer(m_tabs1);
class=class="str">"cmt">//--- Attach to tab
  m_tabs1.AddToElementsArray(class="num">1,frame);
class=class="str">"cmt">//---
  frame.XSize(class="num">350);
  frame.YSize(class="num">500);
  frame.LabelColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
  frame.BorderColor(C&class="macro">#x27;class="num">0,class="num">100,class="num">255&class="macro">#x27;);
  frame.FontSize(class="num">11);
  frame.AutoYResizeMode(true);
  frame.AutoYResizeBottomOffset(class="num">100);
  frame.GetTextLabelPointer().XSize(class="num">250);
class=class="str">"cmt">//--- Creating a control
  if(!frame.CreateFrame(text,x_gap,y_gap))
    class="kw">return(false);
class=class="str">"cmt">//--- Add the object to the common array of object groups
  CWndContainer::AddToElementsArray(class="num">0,frame);
  class="kw">return(true);
}
把形态扫描交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到多周期梅里尔形态与指标叠加状态,你只管在构建器里调组合。

常见问题

因为同一套梅里尔形态与指标组合既要验证做多也要验证做空,对称结构方便对照测试,避免两套逻辑漂移。
目前小布盯盘内置常见指标与形态识别,自定义 iCustom 路径需你在终端配置好,小布侧主要做可视化与多周期预警,不替代构建器回测。
不是。任一信号触发即可执行入场,也可以在界面里单独禁用其中信号,只留一个跑。外汇贵金属波动剧烈,这种柔性设定有助于控制试错成本。
iCustom 调用会找不到指标,信号分区下拉选自定义后无数据返回,策略测试可能空跑或报错,务必按 MQL5/Indicators 相对路径写双反斜杠。