可视化使用选定标准优化的结果·综合运用
📊

可视化使用选定标准优化的结果·综合运用

(3/3)·把多品种余额、回撤与收藏曲线塞进同一张 GUI,优化结果不再靠肉眼翻表

进阶 第 3/3 篇
很多人优化完只看默认排序的表格,最佳参数藏在第十几行就被略过了。用鼠标逐行点选高亮太慢,遇到多品种回撤对比更是乱成一团。本篇把键盘控行和合并页面做进界面,少做重复操作才能更快定位真信号。

「GUI 交互事件的三种触发路径」

在 MT5 自定义优化分析面板里,图形界面的响应靠的是自定义事件和图表事件两套机制。鼠标点表格行、下拉框换标准都走 ON_CLICK_LIST_ITEM 自定义事件;键盘选行则依赖 CHARTEVENT_KEYDOWN。事件处理函数里按元件 ID 逐一匹配,命中即返回 true,否则继续往下查。 点行高亮时,程序先用 element_id 比对主表格 ID,不一致直接退出。匹配后从第一列取 pass 索引,再调 CFrameGenerator::GetFrameData 展开该 pass 对应的品种与权益数据,最后在结果图里高亮对应余额曲线。下拉框有三个标准可选:自定义回测返回值、总利润、采收率,选中项索引会映射成列号 1、2 或 5。 键盘选行由 CProgram::SelectingResultsUsingKeys 处理,接收按键代码。KEY_UP / KEY_DOWN 做行号 ±1,KEY_HOME / KEY_END 跳首末行;若已无高亮、重复选中或越界则退出。通过检查后才重绘高亮并补滚动条。外汇与贵金属优化结果受点差跳空影响大,这类交互仅辅助筛参,实盘前仍需手动复核高风险品种。 下面代码是三处核心逻辑的原样片段,黄底行即事件分发与列映射的关键调用。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 通过鼠标左键点击突出显示表格行                                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::TableRowSelection(class="kw">const class="type">long element_id)
  {
class=class="str">"cmt">//--- 突出显示表格行
   if(element_id!=m_table_main.Id())
      class="kw">return(class="kw">false);
class=class="str">"cmt">//--- 从表格中取得通过索引
   class="type">class="kw">ulong pass=(class="type">class="kw">ulong)m_table_main.GetValue(class="num">0,m_table_main.SelectedItem());
class=class="str">"cmt">//--- 根据通过索引取得数据
   m_frame_gen.GetFrameData(pass);
class=class="str">"cmt">//--- 把交易品种加入表格
   GetFrameSymbolsToTable();
class=class="str">"cmt">//--- 根据通过索引在图形中突出显示曲线
   SelectCurve(pass);
   class="kw">return(true);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 根据指定的标准显示结果                                                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CProgram::ShowResultsBySelectedCriteria(class="kw">const class="type">long element_id)
  {
class=class="str">"cmt">//--- 检查元件 ID
   if(element_id!=m_criterion.Id())
      class="kw">return(class="kw">false);
class=class="str">"cmt">//--- 定义取得最佳结果的标准索引
   class="type">int index=m_criterion.GetListViewPointer().SelectedItemIndex();
   class="type">int column_index=(index<class="num">1)? class="num">1 : (index==class="num">1)? class="num">2 : class="num">5;
   m_frame_gen.OnChangedSelectionCriteria(column_index);
class=class="str">"cmt">//--- 可视化接收到的最佳结果
   GetBestOptimizationResults();
class=class="str">"cmt">//--- 把数据输出到优化结果表格
   GetFrameDataToTable();
   class="kw">return(true);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 事件处理函数                                                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void CProgram::OnEvent(class="kw">const class="type">int id,class="kw">const class="type">long &lparam,class="kw">const class="type">class="kw">double &dparam,class="kw">const class="type">class="kw">string &sparam)
  {
...
class=class="str">"cmt">//--- 点击表格行的事件
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_LIST_ITEM)
     {
     class=class="str">"cmt">//--- 突出显示表格行

用方向键驱动回测结果导航

在 MT5 自定义面板里,回测结果往往以表格形式堆叠,手动点选效率低。把键盘事件接进表格选中逻辑,能让交易者用上下键、Home、End 直接漫游所有通过项。 核心入口是 OnEvent 捕获 CHARTEVENT_KEYDOWN,把按键值 lparam 丢给 SelectingResultsUsingKeys。函数先取当前高亮行 selected_row=m_table_main.SelectedItem(),再按 KEY_UP / KEY_DOWN 做 -- 或 ++,KEY_HOME 跳 0、KEY_END 跳 RowsTotal()-1。 越界与重复选中会被直接拦掉:selected_row 等于 WRONG_VALUE、等于已选行、或落在 [0, RowsTotal()) 之外时返回 false,不刷新界面。合法移动后 SelectRow + Update 重绘,并同步纵向滚动条。 选中后从表格第 0 列取通过索引 ulong pass,调 GetFrameData(pass) 抓数据、GetFrameSymbolsToTable 填品种、SelectCurve(pass) 在图上线。外汇与贵金属回测结果导航涉及杠杆与滑点,实际操作高风险,按键逻辑仅解决交互效率,不预示任何收益。

MQL5 / C++
class="type">bool CProgram::SelectingResultsUsingKeys(class="kw">const class="type">long key)
  {
class=class="str">"cmt">//--- 取得突出显示行的索引
   class="type">int selected_row=m_table_main.SelectedItem();
class=class="str">"cmt">//--- 定义方向和行数,用于移动滚动条
   class="kw">switch((class="type">int)key)
     {
     case KEY_UP :
         selected_row--;
         break;
     case KEY_DOWN :
         selected_row++;
         break;
     case KEY_HOME :
         selected_row=class="num">0;
         break;
     case KEY_END :
         selected_row=(class="type">int)m_table_main.RowsTotal()-class="num">1;
         break;
     }
class=class="str">"cmt">//--- 如果 (class="num">1) 没有突出显示的行 或者 (class="num">2) 之前选择的行已经突出显示 或者 (class="num">3) 我们超出了列表范围
   if(selected_row==WRONG_VALUE || selected_row==m_table_main.SelectedItem() ||
     selected_row<class="num">0 || selected_row>=(class="type">int)m_table_main.RowsTotal())
      class="kw">return(class="kw">false);
class=class="str">"cmt">//--- 突出显示行,并移动滚动条
   m_table_main.SelectRow(selected_row);
   m_table_main.Update();
   m_table_main.GetScrollVPointer().Update(true);
class=class="str">"cmt">//--- 从突出显示表格行中取得通过国的索引
   class="type">class="kw">ulong pass=(class="type">class="kw">ulong)m_table_main.GetValue(class="num">0,m_table_main.SelectedItem());
class=class="str">"cmt">//--- 根据通过索引取得数据
   m_frame_gen.GetFrameData(pass);
class=class="str">"cmt">//--- 把交易品种加入表格
   GetFrameSymbolsToTable();
class=class="str">"cmt">//--- 根据通过索引在图形中突出显示曲线
   SelectCurve(pass);
   class="kw">return(true);
  }

class="type">void CProgram::OnEvent(class="kw">const class="type">int id,class="kw">const class="type">long &lparam,class="kw">const class="type">class="kw">double &dparam,class="kw">const class="type">class="kw">string &sparam)
  {
class=class="str">"cmt">//--- 按下了按钮
   if(id==CHARTEVENT_KEYDOWN)
     {
     class=class="str">"cmt">//--- 使用按键选择结果
     if(SelectingResultsUsingKeys(lparam))
        class="kw">return;
     class=class="str">"cmt">//---
     class="kw">return;
     }
  }

◍ 画得少,看得清

把优化结果塞进帧数组之后,真正值钱的是筛选视角而不是堆指标。原文思路里,除了余额和统计值,整份测试报告都能落进帧数组,再用下拉框或勾选框拼出自定义公式来挑结果——没有 GUI 这层壳,这种交互基本没法落地。 MQL5.zip 里那 74.2 KB 的包含六个文件,MacdSampleCFrames.mq5 是改过的多品种 MACD Sample,FrameGenerator.mqh 管优化结果操作,CreateGUI.mqh 实现面板方法。读者直接拖进 MT5 就能跑,但注意 2021 年有用户反馈新版 EasyAndFastGUI 改了 AddItem 行为,面板空白,全新 MT5 重装才解决。 下面这段是社区里补的状态栏修复插入行,本质是在循环里给每项拼独立 id 再 AddItem,避开批量添加时的索引错乱: //--- 指定部件数量并设置其属性 for(int i=0;i<STATUS_LABELS_TOTAL; i++) { string status_add="status_bar_"+IntegerToString(i); // 插入一行以修复错误。 m_status_bar.AddItem(status_add,width[i]); } 外汇与贵金属优化结果可视化只是辅助筛样,不等于信号可靠,实盘前务必在策略测试器里用历史数据复验,杠杆品种回测偏差可能很大。

MQL5 / C++
class=class="str">"cmt">//--- 指定部件数量并设置其属性
  for(class="type">int i=class="num">0;i<STATUS_LABELS_TOTAL; i++)
    {
     class="type">class="kw">string status_add="status_bar_"+IntegerToString(i); class=class="str">"cmt">// 插入一行以修复错误。
     m_status_bar.AddItem(status_add,width[i]);
    }
让小布替你跑这套
这些多品种余额与回撤的并排诊断,小布盯盘的 AIGC 已内置,打开对应品种页即可看到,你只需在出现异动时做决策。

常见问题

回撤图被收进第二组页面的 Balance 子页,选中某条高亮结果即同步绘制,不必再切到独立页。
目前小布提供的是标准化多品种诊断视图,自定义 CTable 键盘控行需自行在终端部署,但数据逻辑可对照查看。
开发库加强了按键事件响应,在事件处理函数里映射方向键与空格到行选中状态即可,不必重写渲染。
它按所选标准把最佳结果逐条回放余额曲线,方便对比同一标准下不同参数组的走势形态。