跳空缺口 - 是能够获利的策略还是五五开?·进阶篇
📊

跳空缺口 - 是能够获利的策略还是五五开?·进阶篇

(2/3)· 只靠肉眼数跳空容易漏掉样本偏差,本文用脚本拉全组股票 D1 数据做量化初筛

含代码示例 第 2/3 篇
很多人拿外汇跳空当规律做单,却忽略股票 D1 缺口样本量和生命周期差异。直接目测几根 K 线就下结论,统计偏差会悄悄吃掉你的胜率。先把数据拉全再谈策略,否则五五开都可能是错觉。

按路径批量抓取品种并落盘

这段逻辑干的事很直接:先拼出当前目录路径 current_path,再用 SymbolsTotal(false) 遍历终端里全部品种,只保留 SYMBOL_PATH 包含该路径的标的,塞进 symbols_array。 过滤靠两道 continue:取不到路径的跳过,路径不匹配 current_path 的也跳过。ArrayResize 每次加 1、预留 10 个缓冲,避免频繁重分配。 若最终 size 为 0,直接打印错误并返回;否则打印「On path ... N symbols」。实测对 Stock Markets\USA\NYSE/NASDAQ(SnP100)\ 能抓到 100 个符号,输出里明确写了 100 symbols。 落盘时把路径里的 \ 和 / 全替换成下划线,作为文件名写入通用目录 5220\ 下的 .txt。最后逐行 WriteString 加 \r\n,关闭句柄。外汇与贵金属品种同样适用此遍历,但跨市场批量导出时注意点差与流动性风险偏高。

MQL5 / C++
  current_path="";
  for(class="type">int i=class="num">0;i<k_-class="num">1;i++)
     current_path=current_path+result_[i]+sep_;
  }
class=class="str">"cmt">//--- 第四步
  class="type">class="kw">string symbols_array[];
  class="type">int symbols_total=SymbolsTotal(class="kw">false);
  for(class="type">int i=class="num">0;i<symbols_total;i++)
   {
     class="type">class="kw">string symbol_name=SymbolName(i,class="kw">false);
     class="type">class="kw">string symbol_path="";
     if(!SymbolInfoString(symbol_name,SYMBOL_PATH,symbol_path))
        class="kw">continue;
     if(StringFind(symbol_path,current_path,class="num">0)==-class="num">1)
        class="kw">continue;
     class="type">int size=ArraySize(symbols_array);
     ArrayResize(symbols_array,size+class="num">1,class="num">10);
     symbols_array[size]=symbol_name;
   }
class=class="str">"cmt">//--- 第五步
  class="type">int size=ArraySize(symbols_array);
  if(size==class="num">0)
   {
     PrintFormat("ERROR: On path \"%s\" %d symbols",current_path,size);
     class="kw">return;
   }
  PrintFormat("On path \"%s\" %d symbols",current_path,size);
class=class="str">"cmt">//--- 第六步
  m_file_name=current_path;
  StringReplace(m_file_name,"\\","_");
  StringReplace(m_file_name,"/","_");
  if(m_file_txt.Open("class="num">5220\\"+m_file_name+".txt",FILE_WRITE|FILE_COMMON)==INVALID_HANDLE)
   {
     PrintFormat("ERROR: \"%s\" 文件没有在通用数据文件夹中创建",m_file_name);
     class="kw">return;
   }
class=class="str">"cmt">//--- 第七步
  for(class="type">int i=class="num">0;i<size;i++)
    m_file_txt.WriteString(symbols_array[i]+"\r\n");
  m_file_txt.Close();
  Print("Everything is fine. There are no errors");
class=class="str">"cmt">//---
  }

◍ 用 CopyRates 拉全历史算缺口

缺口统计的主逻辑放在一个独立脚本里跑,每个品种都要填一份 SGapStatistics 结构:记名称、D1 柱总数、侦测到的缺口数,以及“确认缺口”数——即当天以向上缺口开盘且收盘仍为阳线,方向一致才算确认。 取 OHLC 最顺手的是 CopyRates 的第三种形式,按起止日期拉。起点用 TimeTradeServer 加一天,终点压到 1970.1.1,等于把能拿的日线全搬回来。 请求返回 -1 就是报错,也可能数据没下全。懒人写法是“请求—睡 N 秒—再请求”,正经方案改自官方 TestLoadHistory 思路:逐品种发请求、汇总负数结果,只要有一个负码就报错误让用户重跑,没错误才读 OHLC 算缺口。 脚本只有一个 File name 参数,填由辅助脚本生成的品种组文件名(不带路径和扩展名)。跑完专家日志会吐前五个品种的统计,例如 AAPL:D1 柱 7238、缺口 3948、确认缺口 1640——确认率约 41.5%,这种比例在个股上常见,外汇贵金属往往更低。 别把一次统计当规律。外汇和贵金属杠杆高、跳空受消息驱动,缺口确认率会随品种和时段漂移,拿到数据先上 MT5 自己复跑一遍再谈策略。

MQL5 / C++
  class="kw">struct SGapStatistics
    {
      class="type">class="kw">string            name;             class=class="str">"cmt">// 交易品种名称
      class="type">int               d1_total;         class=class="str">"cmt">// D1 柱的总数
      class="type">int               gap_total;        class=class="str">"cmt">// 缺口的总数
      class="type">int               gap_confirmed;    class=class="str">"cmt">// 确认的缺口数量
    };
  class="kw">switch(res)
    {
    case -class="num">1 : Print("未知的交易品种",InpLoadedSymbol);                class="kw">break;
    case -class="num">2 : Print("请求的柱数超过了可以在图表中显示的数量"); class="kw">break;
    case -class="num">3 : Print("用户中断了执行");                class="kw">break;
    case -class="num">4 : Print("指标无法上传自身数据");        class="kw">break;
    case -class="num">5 : Print("上传失败");                          class="kw">break;
    case  class="num">0 : Print("所有的数据都已上传");                          class="kw">break;
    case  class="num">1 : Print("现有的时间序列数据足够了");     class="kw">break;
    case  class="num">2 : Print("时间序列是由已有终端数据生成的");     class="kw">break;
    class="kw">default : Print("执行结果未定义");
    }
    [name] [d1_total] [gap_total] [gap_confirmed]
[ class="num">0] "AAPL"        class="num">7238        class="num">3948           class="num">1640

「用数组打印股票基础数据」

在 MQL5 里可以用二维整型与字符串数组配合,把多只标的的编号、两个数值字段和成交量一次性排出来。上面这段输出里,ABBV 到 AGN 四只股票各自带了 759/744/364 到 761/754/385 这样的三组数,说明数组下标和列对齐是直接可控的。 你可以把这段代码粘进 MT5 的脚本里跑一遍,重点看第一列字符串宽度是否对齐——若不对齐,说明打印格式串里的空格占位需要根据字符长度动态补。外汇和贵金属市场波动剧烈、杠杆高风险大,这类数组练习仅用于熟悉语法,不代表任何品种走势判断。

MQL5 / C++
[ class="num">1] "ABBV"        class="num">759        class="num">744          class="num">364
[ class="num">2] "ABT"          class="num">762        class="num">734          class="num">374
[ class="num">3] "ACN"          class="num">759        class="num">746          class="num">388
[ class="num">4] "AGN"          class="num">761        class="num">754          class="num">385

用 CGraphic 把缺口确认率画出来

专家页面直接堆文字看不清缺口分布,所以改用 CGraphic 自绘图。脚本 Getting gap statistics CGraphic.mq5 吃一个由 Symbols on symbol tree 工具生成的品种文件,参数里 File name 指定来源,Log CheckLoadHistory 控制是否打印历史加载结果,Log Statistics 控制是否打印缺口统计。 跑完出来的百分比图很直观:大部分品种的确认缺口率在 50% 上下浮动约 6%,但有三个尖峰掉到 42% 以下。这三个低于 42% 的点意味着,对应品种日线柱往缺口反方向走的概率约 58%。 换一组 Stock Markets\RussiaMICEX20 再看,也有两个类似尖峰。但初版图没法把尖峰和具体品种名绑死,于是出了 2.0 版:开了 Log Statistics 后专家页面直接按百分比列确认缺口,PIKK.MM 和 URKA.MM 分别是 34% 和 38% 确认率,反推日线逆向概率约 66% 和 62%。 有些组品种超 1000 个,全塞进市场报价窗口慢且图挤成一团。Symbols on symbol tree 2.mq5 就此限制单文件最多 200 个品种,超了就加分片号,例如 Stock Markets_USA_NYSE_NASDAQ(SnP100)_part_0.txt。下面这段输出样例里,PIKK.MM 的 confirmed_per 是 34.31,明显低于同组多数 44~53 的区间,属于该脚本能一眼揪出的异类。

MQL5 / C++
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[name] [d1_total] [gap_total] [gap_confirmed] [confirmed_per]
***
[<span class="number">class="num">14</span>] <span class="class="type">class="kw">string">"NVTK.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">757</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">737</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">347</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">47.08</span>
<span style="background-class="type">class="kw">color:rgb(class="num">255, class="num">235, class="num">85);">[<span class="number">class="num">15</span>] <span class="class="type">class="kw">string">"PIKK.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">886</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">822</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">282</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">34.31</span></span>
[<span class="number">class="num">16</span>] <span class="class="type">class="kw">string">"ROSN.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">763</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">746</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">360</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">48.26</span>
[<span class="number">class="num">17</span>] <span class="class="type">class="kw">string">"RSTI.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">775</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">753</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">357</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">47.41</span>
[<span class="number">class="num">18</span>] <span class="class="type">class="kw">string">"RTKM.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">753</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">723</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">324</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">44.81</span>
[<span class="number">class="num">19</span>] <span class="class="type">class="kw">string">"SBER.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">762</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">754</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">400</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">53.05</span>
[<span class="number">class="num">20</span>] <span class="class="type">class="kw">string">"SBER_p.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">762</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">748</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">366</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">48.93</span>
[<span class="number">class="num">21</span>] <span class="class="type">class="kw">string">"SNGS.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">762</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">733</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">360</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">49.11</span>
[<span class="number">class="num">22</span>] <span class="class="type">class="kw">string">"TATN.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">765</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">754</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">370</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">49.07</span>
[<span class="number">class="num">23</span>] <span class="class="type">class="kw">string">"SNGS_p.MM"</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="number">class="num">751</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">708</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">305</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">43.08</span>
把样本筛选交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到分组与 D1 缺口的统计概览,你只需专注解读分布而非手工跑脚本。

常见问题

股票有固定交易时段且历史较长,缺口出现频率高、样本足;外汇连续交易缺口少,期货生命周期短,D1 回测常不够用。
在 MetaEditor 建脚本粘贴文档代码编译,MT5 打开目标品种 D1 图表,从导航器拖入脚本,填品种名、D1、起始年如 1970 即可。
可以,小布盯盘对应品种页已内置 AIGC 诊断,自动汇总分组内 D1 缺口方向与反转比例,省去手动跑 DLL 选文件。
市场报价窗口右键选交易品种或按 Ctrl+U,找到 NASDAQ(SnP100) 分组,其下品种如 ABBV 可直接挂脚本测柱数。